วิธีติดตั้ง Maven Repository ส่วนตัวเพื่อใช้แจกจ่ายไลบรารี่แอนดรอยด์ในงานภายในบริษัท

Posted on 20 Feb 2016 21:40 | 8528 reads | 0 shares
 

วันก่อนมีคนถามมาว่า "สุดท้ายโปรเจคนึงจะมี Library Module ใส่รวมกันเต็มไปหมด เราจะมีวิธีการจัดการไลบรารี่เหล่านี้ยังไงให้มีระเบียบและเหมาะสมกับการเอาไปใช้งานในงานถัดๆไปมากที่สุด"

เป็นคำถามที่ดีครับ บล็อกนี้เราเลยขอมาสอนวิธีที่น่าจะดีที่สุดแล้วคือการ "ตั้ง Maven Repository ส่วนตัวเพื่อใช้กันภายใน" ครับ

ทำไมต้องตั้ง Maven Repository เอง?

จริงอยู่ที่ Library Module ที่เราทำขึ้นมามันก็เป็นแค่ก้อนของ Source Code ที่อยู่ภายในโฟลเดอร์นึงภายใต้โปรเจคแอนดรอยด์ หากจะเอาไปใช้ก็ก็อปโค้ดตัวนี้ไปแปะอีกโปรเจคนึงและใช้งานได้ทันที

ก็ฟังดูสะดวกดี แต่คำถามแรกเลยคือ "หากบริษัทเริ่มใหญ่และมีโปรเจคเริ่มเยอะ เรายังจะควรแจกเป็น Source Code แบบนี้อยู่มั้ย?"

คำตอบคือ "ไม่ควร" ครับ สาเหตุที่สนับสนุนความคิดมีอยู่หลายข้อมากเช่น

1) หากมีโปรเจคเริ่มเยอะ กลายเป็นว่าจะมี Source Code ซ้ำกันไปซ้ำกันมานี้กระจัดกระจายอยู่ตามโปรเจคต่างๆเยอะมาก

2) หากต้องการอัปเดตไลบรารี่เป็นเวอร์ชันใหม่ การแจกจ่ายเป็น Source Code แล้วไล่อัปเดตทีละโปรเจคนั้นเป็นไปด้วยความยากลำบากมาก

3) หากอัปเดตไลบรารี่เป็นเวอร์ชันใหม่แล้วทำให้โปรเจคเดิมพัง เราจำเป็นต้องปรับไลบรารี่กลับเป็นเวอร์ชันเก่าเพื่อให้โปรเจคยังใช้งานได้อยู่ระหว่างรอการแก้ไขจากทีมทำไลบรารี่ ในกรณีแบบนี้เราต้องเก็บ Source Code ของเวอร์ชันเก่าๆไว้ด้วยทุกเวอร์ชัน ซึ่งถ้ามีแค่สัก 10 โปรเจคก็จัดการเรื่องนี้ยากมากๆแล้ว

4) ในมุมมองของการทำงานแล้ว ทีมอื่นจะเอาไลบรารี่ตัวนี้ "ไปใช้งาน" จึงไม่จำเป็นจะต้องเห็น Source Code แต่อย่างใด แค่รู้วิธีใช้งานก็พอ

5) ไลบรารี่ที่ส่งไป "ไม่ควรจะแก้ไขได้" หากมีปัญหาอะไรควรจะแจ้งกลับมาที่คนทำเพื่อดำเนินการแก้ไข แต่ถ้าหากส่งเป็น Source Code ก็อาจจะเกิดปัญหาว่าคนอื่นอาจจะเผลอแก้โค้ดเราได้ สุดท้ายจะไม่สามารถควบคุมเวอร์ชันของ Source Code ได้เลย

และนี่คือเหตุผลว่าเราไม่ควรแจกจ่ายไลบรารี่ในรูปแบบของ Source Code ดังนั้นวิธีที่ดีที่สุดเลยคือ "ควรจะส่งไปในรูปแบบที่คอมไพล์เสร็จแล้ว" หรือก็คือไฟล์ .jar หรือ .aar นั่นเอง

อันนี้ดูดีขึ้นแล้ว โหลดไฟล์ .jar หรือ .aar ไปใส่โปรเจคแล้วเรียกใช้งาน แก้ปัญหาได้เกือบทั้งหมดที่ลิสต์มาด้านบน แต่ก็ยังลำบากอยู่เรื่องนึงคือ "วิธีการแจกจ่ายไลบรารี่" คนในทีมต้องมาส่งไฟล์ ต้องมาดาวน์โหลด ต้องมาควบคุมเวอร์ชันด้วยการก็อปไฟล์แปะ ดังนั้นมันก็ยังถือว่าไม่ Perfect

จะดีกว่ามั้ยถ้าเราสามารถใส่ dependency เข้าไปใน build.gradle ได้เลยบรรทัดเดียวอย่างที่ทำอยู่กับไลบรารี่ต่างๆ

compile 'my.company:library:1.1.0'

หากมีปัญหากับไลบรารี่เวอร์ชันใหม่ก็ปรับเลขเวอร์ชันลงและใช้งานได้ทันที

compile 'my.company:library:1.0.0'

ตอบโจทย์ในทุกมิติ แจกจ่ายไลบรารี่ก็ง่าย แก้ไขเวอร์ชั่นได้ในการปรับเลขไม่กี่ตัว ไม่มีปัญหาเรื่องแก้ Source Code มั่ว ฯลฯ

และนี่คือเหตุผลว่าหากเราทำงานเป็นบริษัทและมีการทำไลบรารี่เพื่อใช้ภายใน เราควรจะมี Maven Repository ไว้ตัวนึงเพื่อไว้แจกจ่ายไลบรารี่ใช้งานกันครับ แต่จะไปใช้ตัวที่เป็น Public Repository ก็คงไม่ได้เพราะไลบรารี่พวกนี้เป็นสิ่งที่ทำไว้ใช้เพื่อการภายใน ก็เลยต้องทำเป็น Private Repository ที่ใช้กันได้เฉพาะคนที่กำหนดเท่านั้น

ซึ่งมีอยู่สองแนวทางคือ

1) ใช้บริการสำเร็จรูป - ที่ดังๆก็มี Bintray Premium และ JitPack Private Repositories ซึ่งค่าใช้จ่ายก็ใช่เล่นอยู่ หลายสิบเหรียญต่อเดือนเลยแหละ ยิ่งมีไลบรารี่เยอะก็ยิ่งต้องจ่ายเยอะขึ้น ดูแล้วไม่ค่อยดีในระยะยาว

2) ตั้ง Server เอง - มี Open Source Software ให้เลือกอยู่หลายตัว เช่น Artifactory หรือ Nexus พอลงแล้วก็ใช้งานได้ทันที จะใส่ไลบรารี่กี่ร้อยกี่พันตัวก็ได้ จ่ายเท่าเดิมเดือนละ $5-$10 สบายๆ

ในบล็อกนี้เราจะพามาสอนตั้ง Server เองกันครับ เพราะเราสามารถทำได้ในราคาที่ประหยัดกว่า ค่าใช้จ่ายไม่บานปลายครับ โดยตัวที่เราจะมาสอนในบล็อกนี้คือ Artifactory ครับ

การติดตั้ง Artifactory

เพื่อความสะดวกในการสอน เราเลยขอควบคุม Environment กันนิดนึงละกันครับ แต่ละคนอาจจะใช้ OS ต่างกันไป แต่ในบทความนี้ขอสอนเป็นการติดตั้งบน Ubuntu 14.04 LTS บน DigitalOcean ครับ หรือใครอยากจะลองตั้ง VM บน VirtualBox ขึ้นมาก็ได้ครับ แล้วแต่ศรัทธาเลย

สร้างเครื่อง Ubuntu 14.04 LTS

เริ่มต้นให้สร้าง Instance บน DigitalOcean ก่อนเลย โดยเลือกให้เป็น

OS: Ubuntu 14.04 LTS

Size: เลือกตัวราคา $10 ต่อเดือน

Region: Singapore (เพื่อความเร็ว) 

จากนั้นก็กดสร้าง Instance ขึ้นมาได้เลยครับ

หลังจาก Instance ถูกสร้างขึ้นมาเสร็จให้ ssh เข้าไปด้วยยูสเซอร์ root โดยใช้พาสเวิร์ดที่ถูกส่งไปทางอีเมล

ติดตั้ง Java 8

Java 8 ไม่ได้มาพร้อม Repository มาตรฐานของ 14.04 LTS เราเลยจะติดตั้งผ่าน PPA Repository กันด้วยคำสั่งตามนี้ครับ

# add-apt-repository ppa:webupd8team/java
# apt-get update
# apt-get install oracle-java8-installer

เป็นอันเรียบร้อย

ติดตั้ง Artifactory

ดาวน์โหลดไฟล์สำหรับติดตั้ง Artifactory มาให้เรียบร้อย

$ wget https://bintray.com/artifact/download/jfrog/artifactory-debs/pool/main/j/jfrog-artifactory-oss-deb/jfrog-artifactory-oss-4.5.1.deb

หากตอนที่ท่านอ่านบล็อกนี้อยู่มีเวอร์ชันที่ใหม่กว่านี้ก็สามารถเปลี่ยนเลข 4.5.1 เป็นเลขเวอร์ชันที่คุณต้องการได้เลย โดยคุณสามารถดูเลขเวอร์ชันทั้งหมดได้จากเว็บ Bintray ครับ

จากนั้นให้ทำการติดตั้งด้วยคำสั่งตามนี้

$ gpg --keyserver pgpkeys.mit.edu --recv-key 6B219DCCD7639232 
$ gpg -a --export 6B219DCCD7639232 | sudo apt-key add -
$ apt-get update
$ dpkg -i jfrog-artifactory-oss-4.5.1.deb

รอจนติดตั้งเสร็จก็สั่งรันได้เลยทันที

service artifactory start

โดย Artifactory จะพ่วงมาพร้อม Tomcat ก็เลยไม่ต้องลงอะไรเพิ่มอีกแล้ว เริ่มใช้งานได้เลยครับ

การตั้งค่า Artifactory

เปิด Browser และเข้า http://IPADDRESS:8081/artifactory/ จะปรากฏเป็นหน้าเว็บให้ล็อกอิน

ให้ Login ด้วยชื่อผู้ใช้ admin และรหัสผ่าน password ครับ พอ Login สำเร็จแล้วให้เข้าไปเปลี่ยน Password ก่อนเลยเป็นอย่างแรกที่ Admin -> Security -> Users -> admin เพื่อความปลอดภัยในการใช้งานครับ

และเพื่อความเหมาะสมในการใช้งานจริง เราไม่ควรจะทำงานกับไลบรารี่ผ่านสถานะ admin เราเลยจะทิ้ง User นี้ไว้อย่างนี้และสร้าง User ใหม่กันครับ และเพื่อความเป็นระบบระเบียบ เราเลยขอพาไปสร้างระบบ Groups และ Permissions เพื่อให้รองรับการเพิ่ม User หลังจากนี้ได้โดยง่าย

สร้าง Group

เข้าไปที่หน้า Admin -> Security -> Groups และกดที่ +New ตรงมุมขวาบน

เราจะทำการสร้าง Group ของคนที่สามารถอัปโหลดไลบรารี่ขึ้น Repository ได้ เราเลยขอตั้งชื่อกลุ่มว่า contributors และใส่ข้อความกำกับไปว่า A group for library contributors ครับ ส่วนในบริเวณ Users ไม่ต้องเลือก User ไหนเลย ปล่อยว่างไว้ครับ

จากนั้นก็กด Save เพื่อยืนยันการสร้างกลุ่มใหม่ เป็นอันเสร็จเรียบร้อยครับ

สร้าง Permission

คราวนี้เราจะกำหนดสิทธิ์การเข้าถึงของคนในกลุ่ม contributors กันด้วยการไปที่หน้า Admin -> Security -> Permissions และกด +New ตรงมุมขวาบน

ใส่ชื่อ Permission ตัวนี้ไปว่า Contribute to Anything เลือกติ๊กเลือกช่อง Any Local Repository และ Any Remote Repository เพื่อกำหนดว่าเราสามารถทำงานได้กับทุก Repository ที่มีอยู่บนระบบ จากนั้นกด Next

ในหน้า Groups ให้เลือก contributors และกำหนดสิทธิ์ตั้งแต่ Delete/Overwrite ไปจนถึง Read ตามภาพ จากนั้นกด Save & Finish

ตอนนี้เราได้สิทธิ์ของคนที่สามารถอัปโหลดไลบรารี่ขึ้นระบบเรียบร้อยครับ

สร้าง User ใหม่

สุดท้ายเราจะสร้าง User ใหม่พร้อมมอบสิทธิ์ที่เราสร้างไปเมื่อกี้ให้กับ User คนนั้นๆ โดยกดที่ปุ่ม +New ตรงด้านขวาบนของหน้า Admin -> Security -> Users

กรอก Username, Password และ อีเมล ให้เรียบร้อย ส่วนใน Related Groups ให้กดเพิ่ม contributors เข้าไปครับ

กด Save และก็เรียบร้อย เรามีแอคเค้าท์สำหรับทำงานเพื่ออัปโหลดไลบรารี่ขึ้นไปรวมถึงใช้เพื่อดาวน์โหลดไลบรารี่บน Server มาใช้งานแล้วครับ

หากหลังจากนี้มีผู้ใช้ที่ต้องการให้อัปโหลดไลบรารี่ได้เพิ่มเติมก็สามารถสร้าง User ใหม่และกำหนดให้อยู่ในกลุ่ม contributors ได้ทันที

แต่ถ้าต้องการผู้ใช้ที่สามารถดึงไลบรารี่ไปใช้ได้อย่างเดียวไม่สามารถอัปโหลดได้ ก็จัดให้ User นั้นๆอยู่ในกลุ่ม readers ได้ครับ สามารถควบคุมสิทธิ์ของ User ได้อย่างอิสระเลย

ดึงค่า Encrypted Password

ในขั้นตอนถัดไปเราจำเป็นต้องใช้ Password ในการทำงานและเพื่อไม่ให้เกิดปัญหาหากข้อมูลรั่วไหล บน Artifactory เลยเปิดให้เราสามารถใช้ Password ในรูปแบบที่ถูก Encrypt ไว้แล้วได้ด้วย นี่คือวิธีเอาค่านั้นมาครับ

เริ่มต้นด้วยการ Logout จาก User admin ก่อนและ Login ใหม่ด้วย User Account ที่เพิ่งสร้างขึ้นมาในขั้นตอนก่อนหน้านี้

หลังจาก Login เสร็จแล้วให้คลิกที่ชื่อ Username ของตัวเองด้านขวาบนของหน้าจอ

และกรอก Password ตามด้วยกดปุ่ม Unlock

จะปรากฎข้อมูลขึ้นมาดังนี้

ให้คัดลอกข้อความในกล่อง Encrypted Password เก็บไว้ เราจะใช้กันในขั้นตอนถัดไปครับ

ปรับ Artifactory เข้าสู่โหมด Private

โดย Default แล้ว ไลบรารี่ที่ถูกอัปโหลดขึ้นบน Artifactory จะสามารถเข้าถึงได้แบบ Public เราเลยจำเป็นต้องเปิดโหมด Private เพื่อให้คนที่มีแอคเค้าท์เท่านั้นที่สามารถเข้าถึงไลบรารี่ต่างๆได้

วิธีการเปิดโหมด Private ก็ง่ายๆ กดที่ Admin -> Security -> General และเคลียร์เครื่องหมายถูกออกจากกล่อง Allow Anonymous Access ครับ

เป็นอันเรียบร้อย Server พร้อมใช้งานแล้วครับ

การอัปโหลดไลบรารี่จาก Android Studio ขึ้น Artifactory

เริ่มต้นด้วยการกำหนด Username/Password ของ Artifactory ไว้ในสคริปต์ก่อน โดยเราจะไปกำหนดกันในไฟล์ที่ไม่เกี่ยวข้องกับโปรเจคของเราและต้องไม่ไปอยู่ใน Version Control เพื่อป้องกันรหัสผ่านรั่วไหล เราเลยจะไปใส่กันไว้ในไฟล์ HOME_DIR/.gradle/gradle.properties ครับ

โดย HOME_DIR สำหรับ Mac OS X และ Linux คือ ~ ในขณะที่ Windows ในกรณีส่วนใหญ่คือ C:\Users\USERNAME ลองกดเข้าไปดูจะเห็นว่ามีโฟลเดอร์ .gradle อยู่แล้ว สามารถเข้าไปทำงานภายในโฟลเดอร์นั้นได้ทันทีครับ

ใช้ Text Editor ที่ถนัดสร้างไฟล์ gradle.properties ขึ้นมาภายใต้โฟลเดอร์ HOME_DIR/.gradle/ หากยังไม่มี หรือแก้ไขไฟล์เดิมหากมีอยู่แล้ว เพิ่มบรรทัดเข้าไปดังด้านล่าง โดยเปลี่ยนคำว่า YOUR_USERNAME และ YOUR_ENCRYPTED_PASSWORD ให้เป็นไปตามแอคเค้าท์ที่คุณสร้างเมื่อขั้นตอนก่อนหน้านี้

# HOME_DIR/.gradle/gradle.properties

artifactory_username=YOUR_USERNAME
artifactory_password=YOUR_ENCRYPTED_PASSWORD

คราวนี้ไปที่โปรเจคของคุณใน Android Studio เปิดไฟล์ build.gradle ระดับโปรเจค และเพิ่มบรรทัด classpath ไปดังนี้

buildscript {
    dependencies {
        // Add this line
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.0.1"
    }
}

ต่อมาให้เปิดไฟล์ build.gradle ของ Library Module ที่เราต้องการจะเอาขึ้น Artifactory ขึ้นมา เพิ่มสองบรรทัดนี้เข้าไปที่ด้านบนสุดของไฟล์

apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'

และด้านล่างสุดของไฟล์ ให้ใส่สคริปต์เพิ่มตามรูปแบบดังนี้

def libraryGroupId = 'my.group.package'
def libraryArtifactId = 'thelibrary'
def libraryVersion = '1.0.0'

โดยโค้ดด้านบนจะทำให้เราสามารถดึงไลบรารี่ตัวนี้มาใช้ได้ด้วยคำสั่ง compile 'my.group.package:thelibrary:1.0.0' หากต้องการหน้าตาของคำสั่งเป็นแบบไหน ให้ปรับข้อมูล libraryGroupId, libraryArtifactId และ libraryVersion ตามที่ต้องการได้เลยครับ

จากนั้นให้ใส่ต่อท้ายไฟล์เดิม (build.gradle ของโมดูล) เพิ่มไปอีกว่า

publishing {
    publications {
        aar(MavenPublication) {
            groupId libraryGroupId
            version libraryVersion
            artifactId libraryArtifactId

            artifact("$buildDir/outputs/aar/${artifactId}-release.aar")
        }
    }
}

artifactory {
    contextUrl = 'http://IPADDRESS:8081/artifactory'
    publish {
        repository {
            repoKey = 'libs-release-local'

            username = artifactory_username
            password = artifactory_password
        }
        defaults {
            publications('aar')
            publishArtifacts = true

            properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'core']
            publishPom = true
        }
    }
}

สคริปต์พร้อมแล้ว เย้ !

อัปโหลดไลบรารี่

เราสามารถสั่งอัปโหลดไลบรารี่ที่ถูกสร้างขึ้นมาขึ้น Artifactory ด้วยการกดที่ Terminal ใน Android Studio

จากนั้นพิมพ์คำสั่งตามนี้

Windows:

gradlew.bat assembleRelease artifactoryPublish

Mac OS X & Linux:

./gradlew assembleRelease artifactoryPublish

รอจนกระทั่งมันทำงานเสร็จและขึ้นว่า BUILD SUCCESSFUL ก็เป็นอันเรียบร้อย

ไลบรารี่ของท่านถูกอัปโหลดขึ้นไปบน Artifactory เรียบร้อยและพร้อมใช้งานแล้ว

ตรวจสอบความถูกต้อง

กดเข้าไปที่เว็บเดิม http://IPADDRESS:8081/artifactory และกดไปที่ Artifacts -> libs-release-local จะเจอกับไลบรารี่ที่เราเพิ่งอัปโหลดไปอยู่ในนั้นพร้อมระบุด้วยว่า User ไหนเป็นคนอัปโหลดมา

หากเจอก็แปลว่าทุกอย่างเรียบร้อยดีแต่ถ้าไม่มีให้ตรวจสอบความถูกต้องระหว่างขั้นตอนการอัปโหลดอีกครั้งครับ

Repository ที่เราอัปโหลดไลบรารี่ขึ้นไปสามารถเข้าถึงได้ที่ http://IPADDRESS:8081/artifactory/libs-release-local/. ลองเข้าไปเช็คดูได้ครับ

การเรียกใช้งาน

ไลบรารี่พร้อมใช้แล้ว เราก็ใช้เลยละกันครับ เริ่มด้วยการประกาศเพิ่ม Maven Repository ไว้ในไฟล์ build.gradle ระดับโปรเจค เพิ่มบรรทัด maven { ... } ไว้ดังนี้

allprojects {
    repositories {
        jcenter()
        // Add these lines
        maven {
            url "http://IPADDRESS:8081/artifactory/libs-release-local"
            credentials {
                username = "${artifactory_username}"
                password = "${artifactory_password}"
            }
        }
    }
}

และไปที่ไฟล์ build.gradle ของโมดูลที่คุณต้องการจะเรียกไลบรารี่เอามาใช้งาน และใส่ dependency ได้เลย

dependencies {
    compile 'my.group.package:thelibrary:1.0.0'
}

เป็นอันสมบูรณ์แบบครบทั้งระบบแล้ว ตั้งแต่อัปโหลดจนถึงการแจกจ่ายให้คนเอาไปใช้งาน แค่นี้การจัดการไลบรารี่ก็เป็นระบบขึ้นเยอะมาก ต่อให้มีเป็นร้อยโปรเจคหรือมีเป็นพันไลบรารี่ ก็ไม่ใช่ปัญหาอีกต่อไป ลองทำกันดูได้ครับ =)

บล็อกนี้ก็สอนเรื่องการทำ Private Repository ไป แต่ถ้าใครต้องการอัปโหลดไลบรารี่ที่ตัวเองทำไปยัง Public Repository เพื่อให้ใครก็ได้ในโลกเอาไปใช้งานได้ ลองไปอ่านอีกบล็อกนึงได้ครับ "วิธีการนำ Android Library ที่เขียนขึ้น jcenter และ Maven Central ผ่าน Android Studio ให้คนอื่นนำไปใช้งาน"

ก็หวังว่าบล็อกนี้จะมีประโยชน์ต่อบริษัทต่างๆนะครับ =)

ผู้เขียน: nuuneoi (Android GDE, CTO & CEO at The Cheese Factory)
นักพัฒนาแบบ Full-Stack ที่มีประสบการณ์ในการพัฒนาแอพฯแอนดรอยด์มากว่า 6 ปีและอยู่ในวงการพัฒนาแอพฯมือถือมากว่า 12 ปี มีความสนใจทางด้าน Infrastucture, Service Side, Design, UI&UX, Hardware, Optimization, Cooking, Photographing, Blogging, Training, Public Speaking และรักที่จะแชร์เรื่องราวให้ผู้คนได้อ่านได้ฟังกันผ่าน Blog