Build Và Deploy app iOS tự động sử dụng Jenkins

Chúng ta sẽ sử dụng project (Testproject) để tìm hiểu xem làm thế nào mà Jenkins có thể được dùng để build, sign và deploy các dự án iOS. Sẽ có tất cả 4 bước cho toàn bộ quá trình này. Lưu ý rằng chúng ta cần có tài khoản doanh nghiệp để build app theo cách này (Tài khoản enterprise mua 299 USD/ năm). Hướng dẫn này dùng để build app có sử dụng cocoapod để quản lý các open source của bên thứ 3, nhưng 4 bước sau đây nó cũng đúng với bất kỳ ứng dụng iOS nào. Bởi nếu ta sử dụng cocoaPods, chỉ là chúng ta thêm 1 workspace của xcode kết hợp 1 scheme tương ứng, nó không ảnh hưởng để dự án chúng ta đang phát triển.

Bước 1 – Poll SCM (Supply Chain Management) • Developer kiểm tra các thay đổi trên branch master hằng ngày, thường thì vào lúc mọi người đã xử lý xong các tasks, hay bugs và merger vào master, thông thường thì thời điểm tốt là vào lúc nửa đêm. • Nếu không có thay đổ gì thì không build project. • Nếu có bất kỳ chỉnh sửa gì xuất hiện chúng ta sẽ thực hiện sang bước tiếp theo.

Bước 2: Build Xcode Hình bên dưới là hình chụp từ plugin của Jenkins trong xcode

• Clean before build – check nếu không muốn bất kỳ đối tượng nào được cache khi chúng ta build mới. • Xcode Schema File – TestProjectDev ◦ Do các xây dựng app hiện tại có sử dụng cocoapod nên xcode tạo 1 workspace cho toàn bộ dự án (TestProject.xcworkspace), nên chúng ta build sẽ dựa trên Schemes bởi xcode không hỗ trợ target dựa trên workspace. ◦ TestProjectDev đây là project chúng ta chỉ định build từ workspace trên • Configuration – Release ◦ Thêm 1 config cho bản release. Dĩ nhiên bản Debug và Release. có 1 số khác biệt. Có thể dễ dàng kể ra như debug ta thấy thường được build cho chỉ định 1 device hay kiến trúc nhất định, như thế nó sẽ giảm được thời gian biên dịch xuống, rất tốt cho việc phát trển, còn bản release thì chúng ta sẽ build tương thích với tất cả các kiến trúc được hỗ trợ. • Workspace File – Đây là file chính để mở project bằng xcode (TestProject.xcworkspace) nếu tuỳ chọn này không được thiết lập, mặc định xcode sẽ tìm file *.xcodeproj đầu tiên mà nó thấy trong thư mục. Điều này dẫn tới việc build thất bại, nên khuyến cáo các bạn nếu build trên 1 workspace cần phải chỉ định thông số này. • Unlock Keychain ◦ Truy cập vào keychain lấy thông số sign, rất cần thiết để file .ipa có thể chạy được trên device thật. ◦ Vị trí keychain là mặc định

Bước 3 – Resigning

• Bước này sẽ chạy nếu như bước 2 thực hiện thành công (tất nhiên rồi) • Thêm 1 điều kiện phải thoả mãn nữa là trong mỗi lần build "BUILD" phải xuất hiện trong log text • Kết quả của việc build bước này nếu fails mà các bước trước thành công thì cả tiến trình sẽ dừng lại.

Các bạn tham khảo script build dưới đây:

#!/bin/sh

PROJECT_BUILDDIR="${WORKSPACE}/build/TestProject/Build/Products/Release-iphoneos"
APPLICATION_NAME="TestProjectDev"
BUILD_HISTORY_DIR="/Users/administrator/Provisioning/builds"
DEVELOPER_NAME="iPhone Distribution: Test Company LTD"
PROVISIONING_PROFILE="/Users/administrator/Provisioning/TestProjectDevDistributionProfile.mobileprovision"
HOST_LOCATION="/Library/WebServer/Documents/apps"

#Sign The .app file and create .ipa file
/usr/bin/xcrun -sdk iphoneos PackageApplication -v  "${PROJECT_BUILDDIR}/${APPLICATION_NAME}.app" -o  "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}.ipa" --sign ${DEVELOPER_NAME} --embed ${PROVISIONING_PROFILE}

#Get the version from the Info.plist file
APP_PATH="${PROJECT_BUILDDIR}/${APPLICATION_NAME}.app"
VERSION=`defaults read ${APP_PATH}/Info CFBundleShortVersionString`
BUNDLE_ID=`defaults read ${APP_PATH}/Info CFBundleIdentifier`

# Create plist
cat ${HOST_LOCATION}/template.plist | sed -e "s/\${APP_NAME}/$APPLICATION_NAME/" -e "s/\${BUNDLE_ID}/$BUNDLE_ID/" -e "s/\${BUNDLE_VERSION}/$VERSION/" > ${HOST_LOCATION}/${APPLICATION_NAME}.plist

• Phần đầu tiên sẽ quy định các biến chung cho cả file script: ◦ PROJECT_BUILDDIR – thư mục tập tin .ipa được lưu từ bước trước đó. ◦ APPLICATION_NAME – Trong trường hợp này là TestProjectDev ◦ BUILD_HISTORY_DIR – sau khi re-signed thì app sẽ được lưu ở đây ◦ DEVELOPER_NAME – nó phải đúng với tên file .mobileprovision được dùng để sign app. ◦ PROVISIONING_PROFILE – đường dẫn file .mobileprovision dùng để sign. Có thể download trực tiếp từ trang develop hoặc có thể lấy nó ở trong thư mục mặc định khi build app (xcode tự lấy từ develop nếu chúng ta sử dụng auto signing). ◦ HOST_LOCATION – nơi mà app sign cuối cùng sẽ tồn tại • Giai đoạn tiếp theo của quá trình là sẽ re-sign lại app sử dụng xcode command line có tên xcrun. Lưu ý rằng phiên bản ở thư mục /usr/bin/ là phiên bản hiện tại được xcode lựa chon thông qua công cụ xcodeselect nằm trong command line tool. Điều này cần phải lưu ý vì nó rất quan trọng, bởi tuỳ mục đích mà bạn có thể cài nhiều hơn 1 phiên bản xcode trên máy tính của bạn. Mỗi version xocde đều lưu trữ các command line tool trong file .app của các ứng dụng. (bạn có thể chỉ định command line tool nào được sự dụng trong xcode preferences) • Sau khi re-signing, chúng ta sẽ lấy thông tin version, và bundle-id. Những thành phần này sẽ được sử dụng trong bước tiếp theo: ◦ APP_PATH – đường dẫn đầy đủ của file .app đã được re-signed ◦ VERSION – Chính là tham sô CFBundleShortVersionString. trong plist. ◦ BUNDLE_ID – chính là CFBundleIdentifier nằm trong plist. Với TestProject, thì nó sẽ là au.com.wordpress.danielbeard.TestProject. với tham số này thì không nên thay đổi app có sẵn.

• Đồng thời chúng ta tạo thêm 1 file plist cho việc cài đặt app từ url (nhớ url phải là https). Trong file này chứa các mô tả chung của app, icon, url. ◦ Việc tạo ra file này khá đơn giản, đó là dùng cat để tạo 1 bản template.plist ở đường dẫn mới và sau đó dùng sed để replace giá trị của BUNDLE_ID và BUNDLE_VERSION. Các giá trị trên được đọc từ file Info.plist nằm trong thư mục .app. • Dưới đây là ví dụ về file template.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>items</key>
        <array>
                <dict>
                        <key>assets</key>
                        <array>
                                <dict>
                                        <key>kind</key>
                                        <string>software-package</string>
                                        <key>url</key>
                                        <string>http://hostlocation/apps/${APP_NAME}.ipa</string>
                                </dict>
                        </array>
                        <key>metadata</key>
                        <dict>
                                <key>bundle-identifier</key>
                                <string>${BUNDLE_ID}</string>
                                <key>bundle-version</key>
                                <string>${BUNDLE_VERSION}</string>
                                <key>kind</key>
                                <string>software</string>
                                <key>title</key>
                                <string>${APP_NAME}</string>
                        </dict>
                </dict>
        </array>
</dict>
</plist>

Step 4 – Copy file ipa đã sign tới thư mục host Bước này đơn giản là lấy file ipa đã sign với provision doanh nghiệp cuối cùng đưa lên server để url có thể trỏ đến và thực hiện cài đặt, trong trường hợp test app thì thư mục trên server là /Library/Webserver/Documents/apps

Script như sau:

#!/bin/sh

APPLICATION_NAME="TestProjectDev.ipa"
BUILD_HISTORY_DIR="/Users/administrator/Provisioning/builds"
HOST_LOCATION="/Library/WebServer/Documents/apps/"

cp "${BUILD_HISTORY_DIR}/${APPLICATION_NAME}" "${HOST_LOCATION}${APPLICATION_NAME}"

Vậy là chúng ta đã có file ipa và file plist ở chung 1 thư mục, bước cuối cùng là chỉ cần cung cấp url trỏ đến file plist này là có thể cài đặt app trên các thiết bị phần cứng khác nhau.

Đã xong, sau này các quy trình trên đều thực hiện 1 cách tự động, rất tốt cho việc tối ưu hoá hiệu suất công việc.

Bài viết được dịch và bổ sung dựa trên bài viết gốc tại https://danielbeard.wordpress.com/2013/04/23/auto-build-and-deploy-ios-apps-using-jenkins/ cảm ơn các bạn đã theo dõi.


All Rights Reserved