ในบทความนี้ เราแบ่งปันประสบการณ์ในการประกอบและส่งมอบแอปพลิเคชัน iOS ให้กับผู้ใช้ ซึ่งสตูดิโอ Plarium Krasnodar ได้สั่งสมไว้ในกระบวนการดีบัก CI/CD
การอบรม
ทุกคนที่มีส่วนร่วมในการพัฒนาแอพพลิเคชั่นสำหรับอุปกรณ์ Apple ไม่ทางใดก็ทางหนึ่งต่างชื่นชมความสะดวกสบายของโครงสร้างพื้นฐานที่เป็นข้อโต้แย้งอยู่แล้ว พบปัญหาได้ทุกที่: ตั้งแต่เมนูโปรไฟล์นักพัฒนาไปจนถึงเครื่องมือแก้ไขข้อบกพร่องและเครื่องมือสร้าง
มีบทความมากมายเกี่ยวกับ "พื้นฐาน" บนอินเทอร์เน็ต ดังนั้นเราจะพยายามเน้นประเด็นหลัก ต่อไปนี้คือสิ่งที่คุณต้องมีเพื่อสร้างแอปพลิเคชันของคุณให้สำเร็จ:
บัญชีนักพัฒนาซอฟต์แวร์ ;- อุปกรณ์ที่ใช้ macOS ทำหน้าที่เป็นเซิร์ฟเวอร์บิลด์
- สร้างขึ้น
ใบรับรองนักพัฒนา ซึ่งจะนำไปใช้ในการลงนามในใบสมัครต่อไป - สร้างแอพพลิเคชั่นที่มีเอกลักษณ์เฉพาะตัว
ID (ควรสังเกตความสำคัญของ Bundle Identifier เนื่องจากการใช้ wildcard ID ทำให้ไม่สามารถใช้ฟังก์ชันต่างๆ ของแอปพลิเคชันได้ เช่น โดเมนที่เกี่ยวข้อง การแจ้งเตือนแบบพุช การลงชื่อเข้าใช้ของ Apple และอื่นๆ) โปรไฟล์ ลายเซ็นแอปพลิเคชัน
ต้องสร้างใบรับรองนักพัฒนาผ่านพวงกุญแจบนอุปกรณ์ macOS ใด ๆ ประเภทของใบรับรองมีความสำคัญมาก ขึ้นอยู่กับสภาพแวดล้อมของแอปพลิเคชัน (Dev, QA, Staging, Production) ซึ่งจะแตกต่างกันไป (การพัฒนาหรือการจัดจำหน่าย) เช่นเดียวกับประเภทของโปรไฟล์ลายเซ็นแอปพลิเคชัน
โปรไฟล์ประเภทหลัก:
- การพัฒนา - มีไว้สำหรับการลงนามในใบสมัครของทีมพัฒนา จะใช้ใบรับรองการพัฒนา (ชื่อประเภท นักพัฒนา iPhone: XXXXX)
- เฉพาะกิจ - มีไว้สำหรับการลงนามในแอปพลิเคชันทดสอบและการตรวจสอบภายในโดยแผนก QA จะใช้ใบรับรองการจัดจำหน่ายของนักพัฒนา (ชื่อประเภท การจัดจำหน่าย iPhone: XXXXX)
- App Store - รุ่นสำหรับการทดสอบภายนอกผ่าน TestFlight และอัปโหลดไปยัง App Store จะใช้ใบรับรองการจัดจำหน่ายของนักพัฒนา
เมื่อสร้างโปรไฟล์การพัฒนาและเฉพาะกิจ ระบบจะระบุด้วย
เพื่อความชัดเจน คุณสามารถนำเสนอโปรไฟล์ของนักพัฒนาซอฟต์แวร์ในรูปแบบตารางด้านล่างนี้ ซึ่งช่วยให้เข้าใจได้ง่ายขึ้นว่าเราต้องการพารามิเตอร์ใดในการประกอบและหาได้จากที่ไหน
การชุมนุม
เพื่อให้ง่ายต่อการแยกแอสเซมบลีตามโครงการและสภาพแวดล้อม เราใช้ชื่อโปรไฟล์เช่น ${ProjectName}_${Instance}
นั่นคือชื่อโปรเจ็กต์ + อินสแตนซ์ (ขึ้นอยู่กับสภาพแวดล้อมของแอปพลิเคชัน: Dev, QA, GD, Staging, Live และอื่นๆ)
เมื่ออิมพอร์ตไปยังบิลด์เซิร์ฟเวอร์ โปรไฟล์จะเปลี่ยนชื่อเป็น ID เฉพาะและถูกย้ายไปยังโฟลเดอร์ /Users/$Username/Library/MobileDevice/Provisioning Profiles
(ที่ไหน $Username
สอดคล้องกับชื่อบัญชีผู้ใช้ของบิลด์เซิร์ฟเวอร์)
มีสองวิธีในการสร้างไฟล์ *.ipa - แบบเดิม (PackageApplication) และแบบสมัยใหม่ (ผ่านการสร้างและส่งออก XcAchive) วิธีแรกถือว่าล้าสมัย เนื่องจากตั้งแต่เวอร์ชัน 8.3 โมดูลการบรรจุไฟล์แอปได้ถูกลบออกจากการกระจาย Xcode หากต้องการใช้งาน คุณจะต้องคัดลอกโมดูลจาก Xcode เก่า (เวอร์ชัน 8.2 และเก่ากว่า) ไปยังโฟลเดอร์:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/
จากนั้นรันคำสั่ง:
chmod +x /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/*
ต่อไปคุณจะต้องรวบรวมไฟล์ *.app ของแอปพลิเคชัน:
xcodebuild
-workspace $ProjectDir/$ProjectName.xcworkspace
-scheme $SchemeName
-sdk iphoneos
build
-configuration Release
-derivedDataPath build
CODE_SIGN_IDENTITY=”$DevAccName”
PROVISIONING_PROFILE=”$ProfileId”
DEPLOYMENT_POSTPROCESSING=YES
SKIP_INSTALL=YES
ENABLE_BITCODE=NO
ที่ไหน:
-workspace
— เส้นทางไปยังไฟล์โครงการ
-scheme
— แบบแผนที่ใช้ระบุไว้ในโครงการ
-derivedDataPath
— เส้นทางสำหรับดาวน์โหลดแอปพลิเคชันที่ประกอบ (*.app)
CODE_SIGN_IDENTITY
— ชื่อของบัญชีนักพัฒนา ซึ่งสามารถตรวจสอบได้ในพวงกุญแจ (นักพัฒนา iPhone: XXXX XXXXXXX โดยไม่มี TeamID ในวงเล็บ)
PROVISIONING_PROFILE
— ID โปรไฟล์สำหรับการลงนามแอปพลิเคชัน ซึ่งสามารถรับได้ด้วยคำสั่ง:
cd "/Users/$Username/Library/MobileDevice/Provisioning Profiles/" && find *.mobileprovision -type f | xargs grep -li ">${ProjectName}_${Instance}<" | sed -e 's/.mobileprovision//'
หากแอปพลิเคชันใช้โปรไฟล์เพิ่มเติม (เช่น สำหรับการแจ้งเตือนแบบพุช) ให้ใช้แทน PROVISIONING_PROFILE
ระบุ:
APP_PROFILE=”$AppProfile”
EXTENSION_PROFILE=”$ExtProfile”
จากนั้น ไฟล์ *.app ที่เป็นผลลัพธ์ควรถูกบรรจุลงใน *.ipa เมื่อต้องการทำเช่นนี้ คุณสามารถใช้คำสั่งเช่น:
/usr/bin/xcrun --sdk iphoneos PackageApplication
-v $(find "$ProjectDir/build/Build/Products/Release-iphoneos" -name "*.app")
-o "$ProjectDir/$ProjectName_$Instance.ipa"
อย่างไรก็ตาม วิธีการนี้ถือว่าล้าสมัยในมุมมองของ Apple มีความเกี่ยวข้องกับการรับ *.ipa โดยการส่งออกจากไฟล์เก็บถาวรแอปพลิเคชัน
ก่อนอื่นคุณต้องรวบรวมไฟล์เก็บถาวรด้วยคำสั่ง:
xcodebuild
-workspace $ProjectDir/$ProjectName.xcworkspace
-scheme $SchemeName
-sdk iphoneos
-configuration Release
archive
-archivePath $ProjectDir/build/$ProjectName.xcarchive
CODE_SIGN_IDENTITY=”$DevAccName”
PROVISIONING_PROFILE=”$ProfileId”
ENABLE_BITCODE=NO
SYNCHRONOUS_SYMBOL_PROCESSING=FALSE
ความแตกต่างอยู่ที่วิธีการประกอบและตัวเลือกต่างๆ SYNCHRONOUS_SYMBOL_PROCESSING
ซึ่งปิดใช้งานการยกเลิกการโหลดสัญลักษณ์ในขณะสร้าง
ต่อไปเราต้องสร้างไฟล์ที่มีการตั้งค่าการส่งออก:
ExportSettings="$ProjectDir/exportOptions.plist"
cat << EOF > $ExportSettings
<?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>compileBitcode</key>
<false/>
<key>uploadBitcode</key>
<false/>
<key>uploadSymbols</key>
<false/>
<key>method</key>
<string>$Method</string>
<key>provisioningProfiles</key>
<dict>
<key>$BundleID</key>
<string>$ProfileId</string>
</dict>
<key>signingCertificate</key>
<string>$DevAccName</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>$TeamID</string>
<key>thinning</key>
<string><none></string>
</dict>
</plist>
EOF
ที่ไหน:
$Method
— วิธีการจัดส่ง สอดคล้องกับประเภทโปรไฟล์ลายเซ็นของแอปพลิเคชัน นั่นคือ สำหรับการพัฒนา ค่าจะถูกพัฒนา สำหรับ Ad Hoc - เฉพาะกิจ และสำหรับ App Store - app-store
$BundleID
— ID แอปพลิเคชัน ซึ่งระบุไว้ในการตั้งค่าแอปพลิเคชัน คุณสามารถตรวจสอบด้วยคำสั่ง:
defaults read $ProjectDir/Info CFBundleIdentifier
$DevAccName и $ProfileId
— การตั้งค่าชื่อนักพัฒนาและ ID โปรไฟล์ลายเซ็นที่ใช้ก่อนหน้านี้และจะต้องตรงกับค่าในการตั้งค่าการส่งออก
$TeamID
— รหัสสิบหลักในวงเล็บหลังชื่อนักพัฒนา ตัวอย่าง: นักพัฒนา iPhone: …… (XXXXXXXXXX); สามารถตรวจสอบได้ในพวงกุญแจ
ต่อไป เมื่อใช้คำสั่งส่งออก เราได้รับไฟล์ *.ipa ที่จำเป็น:
xcodebuild
-exportArchive
-archivePath $ProjectDir/build/$ProjectName.xcarchive
-exportPath $ProjectDir
-exportOptionsPlist $ExportSettings
จัดส่งสินค้า
ตอนนี้ไฟล์ที่รวบรวมจะต้องถูกส่งไปยังผู้ใช้ปลายทางซึ่งก็คือการติดตั้งบนอุปกรณ์
มีบริการมากมายสำหรับการเผยแพร่ Development และ Ad Hoc builds เช่น HockeyApp, AppBlade และอื่นๆ แต่ในบทความนี้ เราจะพูดถึงเซิร์ฟเวอร์แบบสแตนด์อโลนสำหรับการกระจายแอปพลิเคชัน
การติดตั้งแอปพลิเคชันสำหรับ iOS จะเกิดขึ้นใน 2 ขั้นตอน:
- การรับรายการการติดตั้งแอปพลิเคชันผ่านบริการรายการ
- การติดตั้งไฟล์ *.ipa ตามข้อมูลที่ระบุในรายการผ่าน HTTPS
ดังนั้นก่อนอื่นเราจำเป็นต้องสร้างรายการการติดตั้ง (ประเภทไฟล์ *.plist) ด้วยคำสั่ง:
cat << EOF > $manifest
<?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>$ipaUrl</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>$BundleID</string>
<key>bundle-version</key>
<string>$AppVersion</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>$ProjectName_$Instance</string>
<key>subtitle</key>
<string>$Instance</string>
</dict>
</dict>
</array>
</dict>
</plist>
EOF
อย่างที่คุณเห็น รายการนี้มีพารามิเตอร์เกือบทั้งหมดที่เกี่ยวข้องกับการสร้างแอปพลิเคชัน
เวอร์ชันแอปพลิเคชัน ($AppVersion
) สามารถตรวจสอบได้ด้วยคำสั่ง:
defaults read $ProjectDir/Info CFBundleVersion
พารามิเตอร์ $ipaUrl
มีลิงก์โดยตรงเพื่อดาวน์โหลดไฟล์ *.ipa ตั้งแต่ iOS เวอร์ชันที่ 7 จะต้องติดตั้งแอปพลิเคชันผ่าน HTTPS ในเวอร์ชันที่แปด รูปแบบของรายการมีการเปลี่ยนแปลงเล็กน้อย: บล็อกที่มีการตั้งค่าสำหรับไอคอนแอปพลิเคชันเช่น
<images>
<image>...</image>
</images>
ดังนั้นในการติดตั้งแอปพลิเคชันหน้า HTML ธรรมดาที่มีลิงก์เช่นนี้ก็เพียงพอแล้ว:
itms-services://?action=download-manifest&url=https://$ServerUrl/$ProjectName/$Instance/iOS/$AppVersion/manifest.plist
สำหรับความต้องการของแผนกพัฒนาและทดสอบ Plarium ได้สร้างแอปพลิเคชันการติดตั้งแบบบิวด์ของตัวเอง ซึ่งทำให้เรา:
- เอกราชและความเป็นอิสระ
- การรวมศูนย์การควบคุมการเข้าถึงและการติดตั้งแอปพลิเคชันที่ปลอดภัยผ่านลิงก์ที่สร้างขึ้นแบบไดนามิก "ชั่วคราว"
- ฟังก์ชันการทำงานที่ขยายได้ (นั่นคือ หากจำเป็น ทีมพัฒนาสามารถรวมฟังก์ชันที่ขาดหายไปเข้ากับแอปพลิเคชันที่มีอยู่ได้)
การทดสอบ
ตอนนี้เราจะพูดถึงการทดสอบแอปพลิเคชันก่อนเผยแพร่โดยใช้
เงื่อนไขที่จำเป็นสำหรับการดาวน์โหลดคือประเภทของโปรไฟล์ลายเซ็น App Store และการมีอยู่ของคีย์ API ที่สร้างขึ้น
มีหลายวิธีในการดาวน์โหลดแอปพลิเคชัน:
- ผ่าน Xcode (ออแกไนเซอร์)
- ผ่านทางอัลทูล
- ผ่าน Application Loader สำหรับ Xcode เวอร์ชันเก่า (ปัจจุบันคือ Transporter)
สำหรับการดาวน์โหลดอัตโนมัติ จะใช้ altool ซึ่งมีวิธีการอนุญาตสองวิธี:
- รหัสผ่านเฉพาะแอป
- คีย์ API
ขอแนะนำให้ดาวน์โหลดแอปพลิเคชันโดยใช้คีย์ API
หากต้องการรับคีย์ API ให้ไปที่
ถัดไป นำเข้าคีย์ที่ดาวน์โหลดไปยังเซิร์ฟเวอร์บิลด์:
mkdir -p ~/.appstoreconnect/private_keys
mv ~/Downloads/AuthKey_${KeyID}.p8 ~/.appstoreconnect/private_keys/
ก่อนที่จะอัปโหลดแอปพลิเคชันไปยัง TestFlight คุณต้องตรวจสอบแอปพลิเคชันก่อน โดยเราจะดำเนินการนี้ด้วยคำสั่ง:
xcrun altool
--validate-app
-t ios
-f $(find "$ProjectDir" -name "*.ipa")
--apiKey “$KeyID”
--apiIssuer “$IssuerID”
ที่ไหน apiKey
и apiIssuer
มีค่าฟิลด์จากหน้าการสร้างคีย์ API
ต่อไป เมื่อตรวจสอบสำเร็จแล้ว เราจะโหลดแอปพลิเคชันด้วยคำสั่ง --upload-app
ด้วยพารามิเตอร์เดียวกัน
แอปพลิเคชันนี้จะได้รับการทดสอบโดย Apple ภายในหนึ่งหรือสองวัน จากนั้นจะพร้อมให้ผู้ทดสอบภายนอกใช้งานได้ โดยพวกเขาจะได้รับลิงก์ทางอีเมลสำหรับการติดตั้ง
อีกวิธีในการดาวน์โหลดแอปพลิเคชันผ่าน altool คือการใช้รหัสผ่านเฉพาะแอป
หากต้องการรับรหัสผ่านเฉพาะแอป คุณต้องไปที่
ถัดไป คุณควรสร้างบันทึกเซิร์ฟเวอร์บิลด์ในพวงกุญแจด้วยรหัสผ่านนี้ จาก Xcode เวอร์ชัน 11 สามารถทำได้ด้วยคำสั่ง:
xcrun altool --store-password-in-keychain-item "Altool" -u "$DeveloperName" -p $AppPswd
ที่ไหน:
$DeveloperName
— ชื่อบัญชีนักพัฒนา iOS ที่ใช้ในการเข้าสู่ระบบบริการของ Apple
$AppPswd
- สร้างรหัสผ่านเฉพาะแอป
ต่อไปเราจะรับค่าของพารามิเตอร์ asc-provider และตรวจสอบความสำเร็จของการนำเข้ารหัสผ่านด้วยคำสั่ง:
xcrun altool --list-providers -u "$DeveloperName" -p "@keychain:Altool"
เราได้รับผลลัพธ์:
Provider listing:
- Long Name - - Short Name -
XXXXXXX XXXXXXXXX
อย่างที่คุณเห็น ค่าชื่อย่อที่ต้องการ (asc-provider) เกิดขึ้นพร้อมกับพารามิเตอร์ $TeamID ที่เราใช้เมื่อสร้างแอปพลิเคชัน
ในการตรวจสอบและโหลดแอปพลิเคชันลงใน TestFlight ให้ใช้คำสั่ง:
xcrun altool
--(validate|upload)-app
-f $(find "$ProjectDir" -name "*.ipa")
-u "$DeveloperName"
-p "@keychain:Altool"
เป็นค่าพารามิเตอร์ -p
คุณสามารถรับค่านั้นได้ $AppPswd
ในรูปแบบที่ไม่เข้ารหัส (ชัดเจน)
อย่างไรก็ตาม ดังที่กล่าวไปแล้ว จากมุมมองของประสิทธิภาพ เป็นการดีกว่าที่จะเลือกคีย์ API สำหรับการอนุญาต altool เนื่องจาก Xcode เวอร์ชันต่างๆ มีปัญหาบางอย่าง ("ไม่เห็น" พวงกุญแจ ข้อผิดพลาดในการอนุญาตระหว่างการอัปโหลด ฯลฯ )
นั่นคือทั้งหมดจริงๆ ฉันขอให้ทุกคนมีส่วนร่วมในการสร้างที่ประสบความสำเร็จและการเปิดตัวที่ไร้ปัญหาใน App Store
ที่มา: will.com