Дар ин мақола мо таҷрибаи ҷамъоварӣ ва расонидани замимаҳои iOS-ро ба корбарон мубодила мекунем, ки студияи Plarium Краснодар дар ҷараёни ислоҳи CI/CD ҷамъ кардааст.
Омодагӣ
Ҳар як шахсе, ки ба ин ё он роҳ дар таҳияи замимаҳо барои дастгоҳҳои Apple машғул аст, аллакай бароҳатии баҳсбарангези инфрасохторро қадр кардааст. Мушкилот дар ҳама ҷо пайдо мешаванд: аз менюи профили таҳиякунанда то абзорҳои ислоҳ ва сохтани.
Дар Интернет мақолаҳои зиёде дар бораи "асосиҳо" мавҷуданд, аз ин рӯ мо кӯшиш мекунем, ки чизи асосиро таъкид кунем. Ин аст он чизе ки ба шумо барои бомуваффақият сохтани аризаи худ лозим аст:
ҳисоби таҳиякунанда ;- дастгоҳи дар MacOS асосёфта, ки ҳамчун сервери сохта амал мекунад;
- тавлидшуда
шаҳодатномаи таҳиякунанда , ки минбаъд барои имзои ариза истифода мешавад; - замимаи бо беназир сохташуда
ID (аҳамияти Идентификатори маҷмӯаро бояд қайд кард, зеро истифодаи ID аломати ваҳшӣ истифодаи бисёр функсияҳои барномаро ғайриимкон месозад, масалан: Доменҳои алоқаманд, Огоҳиҳои Push, Sign In Apple ва ғайра); профил имзоҳои ариза.
Шаҳодатномаи таҳиягар бояд тавассути Keychain дар ҳама гуна дастгоҳи macOS тавлид карда шавад. Навъи шаҳодатнома хеле муҳим аст. Вобаста аз муҳити барнома (Dev, QA, Staging, Production) он фарқ мекунад (таҳия ё тақсимот), инчунин намуди профили имзои барнома.
Намудҳои асосии профилҳо:
- Таҳия - барои имзои аризаи дастаи таҳиякунанда пешбинӣ шудааст, шаҳодатномаи рушд истифода мешавад (номи навъи iPhone Developer: XXXXXX);
- Ad Hoc - барои имзои аризаи санҷишӣ ва санҷиши дохилӣ аз ҷониби шӯъбаи QA пешбинӣ шудааст, шаҳодатномаи тақсимоти таҳиякунанда истифода мешавад (номи навъи iPhone Distribution: XXXXX);
- Дӯкони App - сохтани релиз барои санҷиши беруна тавассути TestFlight ва боргузорӣ ба Дӯкони App, шаҳодатномаи тақсимоти таҳиягар истифода мешавад.
Ҳангоми тавлиди профилҳои рушд ва махсус, он инчунин нишон дода мешавад
Барои равшанӣ, шумо метавонед профили таҳиягарро дар шакли ҷадвали зер пешниҳод кунед. Ин фаҳмидани он, ки барои васлкунӣ ба мо кадом параметрҳо лозим аст ва онҳоро аз куҷо гирифтан осонтар мекунад.
Ассамблея
Барои осонтар кардани ҷудо кардани маҷлисҳо аз рӯи лоиҳа ва муҳити зист, мо номҳои профилҳоро истифода мебарем ${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
— номи ҳисоби таҳиягар, ки онро дар Keychain тафтиш кардан мумкин аст (Developer 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//'
Агар барнома профили иловагиро истифода барад (масалан, барои огоҳиҳои Push), ба ҷои 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 - ad-hoc ва барои App Store - app-store.
$BundleID
— ID-и барнома, ки дар танзимоти барнома муайян шудааст. Шумо метавонед бо фармони зерин тафтиш кунед:
defaults read $ProjectDir/Info CFBundleIdentifier
$DevAccName и $ProfileId
— номи таҳиякунанда ва танзимоти ID профили имзо, ки қаблан истифода мешуданд ва бояд ба арзишҳои танзимоти содирот мувофиқат кунанд.
$TeamID
- ID даҳ рақам дар қавс пас аз номи таҳиякунанда, мисол: Developer iPhone: …… (XXXXXXXXX); дар Keychain тафтиш кардан мумкин аст.
Баъдан, бо истифода аз фармони содирот, мо файли зарурии *.ipa -ро мегирем:
xcodebuild
-exportArchive
-archivePath $ProjectDir/build/$ProjectName.xcarchive
-exportPath $ProjectDir
-exportOptionsPlist $ExportSettings
Маълумоти интиқол
Акнун файли ҷамъшуда бояд ба корбари ниҳоӣ расонида шавад, яъне дар дастгоҳ насб карда шавад.
Хидматҳои зиёде барои паҳн кардани сохторҳои таҳия ва Ad Hoc мавҷуданд, ба монанди HockeyApp, AppBlade ва дигарон, аммо дар ин мақола мо дар бораи сервери мустақил барои паҳн кардани барномаҳо сӯҳбат хоҳем кард.
Насби барнома барои iOS дар 2 марҳила сурат мегирад:
- Қабули манифести насби барнома тавассути хидмати Items.
- Насби файли *.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, барнома бояд тавассути 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 (ташкилгар),
- тавассути altool,
- тавассути 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 ин истифодаи пароли мушаххаси барнома мебошад.
Барои гирифтани пароли мушаххаси барнома шумо бояд ба он равед
Баъдан, шумо бояд бо ин парол дар Keychain сабти сервер эҷод кунед. Аз версияи 11-и Xcode инро бо фармон иҷро кардан мумкин аст:
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 Калиди авторизатсияро интихоб кунед, зеро версияҳои гуногуни Xcode мушкилоти муайян доранд (" Keychain намебинад, хатогиҳои авторизатсия ҳангоми боргузорӣ ва ғайра).
Дар асл, ҳамааш ҳамин аст. Ман ба ҳама хоҳишмандам, ки дар Дӯкони Барномасозони бомуваффақият ва нашрҳои бе мушкилот иштирок кунанд.
Манбаъ: will.com