ืืืืืจ ืื, ืื ื ืืืืงืื ืืช ืืืืืื ืฉื ืืจืืื ืืืกืคืงื โโืฉื ืืืฉืืื iOS ืืืฉืชืืฉืื, ืืฉืจ ืฆืืจ ืืกืืืืื ืฉื Plarium Krasnodar ืืชืืืื ืฉื ืืืชืืจ ืืืืื CI/CD.
ืืืจืื
ืื ืืื ืฉืขืืกืง ืืืจื ืื ืื ืืืจืช ืืคืืชืื ืืคืืืงืฆืืืช ืืืืฉืืจื ืืคื ืืืจ ืืขืจืื ืืช ืื ืืืืช ืืฉื ืืื ืืืืืืงืช ืฉื ืืชืฉืชืืช. ืงืฉืืื ื ืืฆืืื ืืื ืืงืื: ืืชืคืจืื ืคืจืืคืื ืืืคืชื ืืขื ืืืื ื ืืคืื ืืื ืืื.
ืืฉ ืืจืื ืืืืจืื ืขื ื"ืืกืืืืช" ืืืื ืืจื ื, ืื ื ื ืกื ืืืืืืฉ ืืช ืืขืืงืจ. ืื ื ืื ืฉืืชื ืฆืจืื ืืื ืืื ืืช ืืช ืืืืฉืื ืฉืื ืืืฆืืื:
ืืฉืืื ืืคืชื ;- ืืืฉืืจ ืืืืกืก macOS ืืคืืขื ืืฉืจืช build;
- ื ืืฆืจ
ืชืขืืืช ืืคืชื , ืืฉืจ ืืฉืืฉ ืขืื ืืืชืืื ืขื ืืืงืฉื; - ื ืืฆืจ ืืืฉืื ืขื ืืืืืื
ID (ืืฉ ืืฆืืื ืืช ืืืฉืืืืช ืฉื ืืืื ืืืืืื, ืืืืืื ืฉืืฉืืืืฉ ืืืืื ืืืื ืื ืืืคืฉืจ ืืืฉืชืืฉ ืืคืื ืงืฆืืืช ืจืืืช ืฉื ืืืคืืืงืฆืื, ืืืฉื: ืืืืืื ืื ืืฉืืืืื, ืืืืขืืช ืืืืคื, Apple Sign In ืืืืจืืช); ืคืจืืคืื ืืชืืืืช ืืคืืืงืฆืื.
ืืฉ ืืืคืืง ืืืฉืืจ ืืคืชื ืืืืฆืขืืช ืืืืืง ืืคืชืืืช ืืื ืืืฉืืจ macOS. ืกืื ืืชืขืืื ืืฉืื ืืืื. ืืืชืื ืืกืืืืช ืืืคืืืงืฆืื (Dev, QA, Staging, Production) ืื ืืืื ืฉืื ื (ืคืืชืื ืื ืืคืฆื), ืืื ืื ืกืื ืคืจืืคืื ืืชืืืช ืืืคืืืงืฆืื.
ืกืืื ืคืจืืคืืืื ืขืืงืจืืื:
- ืคืืชืื - ืืืืขื ืืืชืืื ืขื ืืืคืืืงืฆืื ืฉื ืฆืืืช ืืคืืชืื, ื ืขืฉื ืฉืืืืฉ ืืชืขืืืช ืคืืชืื (ืฉื ืกืื ืืืืคืื ืืคืชื: XXXXX);
- ืื ืืืง - ืืืืขื ืืืชืืื ืขื ืืคืืืงืฆืืืช ืืืืงื ืืืืืืช ืคื ืืื ืขื ืืื ืืืืงืช QA, ื ืขืฉื ืฉืืืืฉ ืืชืขืืืช ืืคืฆื ืฉื ืืืคืชื (ืฉื ืกืื iPhone Distribution: XXXXX);
- App Store - ืฉืืจืืจ build ืืืืืงื ืืืฆืื ืืช ืืืืฆืขืืช TestFlight ืืืขืืื ื-App Store, ื ืขืฉื ืฉืืืืฉ ืืชืขืืืช ืืืคืฆื ืฉื ืืืคืชื.
ืืขืช ืืฆืืจืช ืคืจืืคืืื ืคืืชืื ืืื ืืืง, ืื ืื ืืฆืืื
ืืฉื ืืืืืจืืช, ืืชื ืืืื ืืืฆืื ืืช ืคืจืืคืื ืืืคืชื ืืฆืืจื ืฉื ืืืื ืืืื. ืื ืงื ืืืชืจ ืืืืื ืืืื ืคืจืืืจืื ืื ื ืฆืจืืืื ืืืจืืื ืืืืืคื ืืืฉืื ืืืชื.
ืืขืฆืจืช
ืืื ืืืงื ืขื ืืคืจืืช ืืืืืืื ืืคื ืคืจืืืงื ืืกืืืื, ืื ื ืืฉืชืืฉืื ืืฉืืืช ืคืจืืคืืืื ืืื ${ProjectName}_${Instance}
, ืืืืืจ, ืฉื ืืคืจืืืงื + ืืืคืข (ืชืืื ืืกืืืืช ืืืคืืืงืฆืื: Dev, QA, GD, Staging, Live ืืื ืืืื).
ืืืฉืจ ืืืืื ืืฉืจืช ื-build, ืืคืจืืคืื ืืฉื ื ืืช ืฉืื ืืืืื ืืืืืื ืืืืขืืจ ืืชืืงืื /Users/$Username/Library/MobileDevice/Provisioning Profiles
(ืืืคื $Username
ืืชืืื ืืฉื ืืฉืืื ืืืฉืชืืฉ ืฉื ืฉืจืช ื-build).
ืืฉื ื ืฉืชื ืืจืืื ืืื ืืช ืงืืืฅ *.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
- ืฉื ืืฉืืื ืืืคืชื, ืฉื ืืชื ืืืืช ืืืืืืง ืืคืชืืืช (ืืคืชื ืืืืคืื: XXXX XXXXXXX, ืืื TeamID ืืกืืืจืืื).
PROVISIONING_PROFILE
- ืืืื ืคืจืืคืื ืืืชืืื ืขื ืืืงืฉื, ืฉื ืืชื ืืืฉืื ืืืืฆืขืืช ืืคืงืืื:
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"
ืขื ืืืช, ืฉืืื ืื ื ืืฉืืช ืืืืืฉื ืช ืื ืงืืืช ืืืื ืฉื โโืืคื. ืจืืืื ืื ืืืฉืื *.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 - ืื ืืช ืืคืืืงืฆืืืช.
$BundleID
โ ืืืื ืืืฉืื, ืืืฆืืื ืืืืืจืืช ืืืืฉืื. ืืชื ืืืื ืืืืืง ืขื ืืคืงืืื:
defaults read $ProjectDir/Info CFBundleIdentifier
$DevAccName ะธ $ProfileId
- ืืืืจืืช ืฉื ืืคืชื ืืืืื ืคืจืืคืื ืืชืืื ืฉืืื ืืฉืืืืฉ ืืขืืจ ืืืืืืืช ืืืชืืื ืืขืจืืื ืืืืืจืืช ืืืืฆืื.
$TeamID
- ืืืื ืื ืขืฉืจ ืกืคืจืืช ืืกืืืจืืื ืืืจื ืฉื ืืืคืชื, ืืืืื: ืืคืชื iPhone: โฆโฆ (XXXXXXXXXX); ื ืืชื ืืืืืง ืืืืืืง ืืคืชืืืช.
ืืืืจ ืืื, ืืืืฆืขืืช ืคืงืืืช ืืืืฆืื, ื ืงืื ืืช ืงืืืฅ *.ipa ืืืจืืฉ:
xcodebuild
-exportArchive
-archivePath $ProjectDir/build/$ProjectName.xcarchive
-exportPath $ProjectDir
-exportOptionsPlist $ExportSettings
ืืฉืืื
ืืขืช ืืฉ ืืืขืืืจ ืืช ืืงืืืฅ ืฉื ืืกืฃ ืืืฉืชืืฉ ืืงืฆื, ืืืืืจ ืืืชืงืื ืืืืฉืืจ.
ืืฉื ื ืฉืืจืืชืื ืจืืื ืืืคืฆืช ืคืืชืื ืืื ืืืช ืื ืืืง, ืืื HockeyApp, AppBlade ืืืืจืื, ืื ืืืืืจ ืื ื ืืืจ ืขื ืฉืจืช ืขืฆืืื ืืืคืฆืช ืืคืืืงืฆืืืช.
ืืชืงื ืช ืืืคืืืงืฆืื ืขืืืจ iOS ืืชืืฆืขืช ืืฉื ื ืฉืืืื:
- ืงืืืช ืื ืืคืกื ืืชืงื ืช ืืืคืืืงืฆืื ืืจื ืฉืืจืืช ืืคืจืืืื.
- ืืชืงื ื ืฉื ืงืืืฅ *.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
ืืฆืจืื ืืืืงืืช ืืคืืชืื ืืืืืืงื, ืคืืจืืื ืืฆืจื ืืืฉืื ืืชืงื ืช ืื ืืื ืืฉืื, ืืืขื ืืง ืื ื:
- ืืืืื ืืืื ืืขืฆืืืืช,
- ืจืืืื ืืงืจืช ืืืฉื ืืืชืงื ื ืืืืืืืช ืฉื ืืืฉืืืื ืืืืฆืขืืช ืงืืฉืืจืื "ืืื ืืื" ืฉื ืืฆืจื ืืืืคื ืืื ืื,
- ืคืื ืงืฆืืื ืืืืช ืื ืืชื ืช ืืืจืืื (ืืืืืจ, ืฆืืืช ืืคืืชืื, ืืืืืช ืืฆืืจื, ืืืื ืืฉืื ืคืื ืงืฆืืืช ืืกืจืืช ืืืคืืืงืฆืื ืงืืืืช).
ืืืืงื
ืืขืช ื ืืืจ ืขื ืืืืงืืช ืืจืื ืฉืืจืืจ ืฉื ืืืคืืืงืฆืื ืืืืฆืขืืช
ืืชื ืืื ืื ืืจืฉืื ืืืืจืื ืื ืกืื ืคืจืืคืื ืืืชืืื ืฉื App Store ืืื ืืืืืช ืฉื ืืคืชืืืช API ืฉื ืืฆืจื.
ืืฉื ื ืืกืคืจ ืืจืืื ืืืืจืื ืืช ืืืคืืืงืฆืื:
- ืืืืฆืขืืช Xcode (ืืืจืื),
- ืืจื altool,
- ืืืืฆืขืืช Application Loader ืขืืืจ ืืจืกืืืช ืืฉื ืืช ืืืชืจ ืฉื Xcode (ืืืื Transporter).
ืืืืจืื ืืืืืืืืช, ื ืขืฉื ืฉืืืืฉ ื-altool, ืฉืืฉ ืื ืื ืฉืชื ืฉืืืืช ืืจืฉืื:
- ืกืืกืื ืกืคืฆืืคืืช ืืืคืืืงืฆืื,
- ืืคืชื API.
ืขืืืฃ ืืืืจืื ืืช ืืืคืืืงืฆืื ืืืืฆืขืืช ืืคืชื ื-API.
ืืื ืืงืื ืืช ืืคืชื ื-API, ืขืืืจ ืื
ืืืืจ ืืื, ืืืื ืืช ืืืคืชื ืฉืืืจื ืืฉืจืช ื-build:
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
ืขื ืืืชื ืคืจืืืจืื.
ืืืคืืืงืฆืื ืชืืืืง ืขื ืืื ืืคื ืชืื ืืื ืื ืืืืืื ืืืืืจ ืืื ืชืืคืื ืืืืื ื ืืืืืงืื ืืืฆืื ืืื: ืื ืืงืืื ืงืืฉืืจืื ืืืื"ื ืืืชืงื ื.
ืืจื ื ืืกืคืช ืืืืจืื ืืคืืืงืฆืื ืืจื altool ืืื ืืืฉืชืืฉ ืืกืืกืื ืกืคืฆืืคืืช ืืืคืืืงืฆืื.
ืืื ืืงืื ืืช ืืกืืกืื ืืกืคืฆืืคืืช ืืืคืืืงืฆืื ืขืืื ืืขืืืจ ืื
ืืืืจ ืืื, ืขืืื ืืืฆืืจ ืจืฉืืืช ืฉืจืช ืืื ืืช ืืืืืืง ืืคืชืืืช ืขื ืกืืกืื ืื. ืืืจืกื 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
ืืคื ืฉืืชื ืืืื ืืจืืืช, ืขืจื ื-Short Name ืื ืืจืฉ (asc-provider) ืขืืื ืืงื ื ืืื ืขื ืืคืจืืืจ $TeamID ืื ืืฉืชืืฉื ื ืืขืช ืื ืืืช ืืืคืืืงืฆืื.
ืืื ืืืืช ืืืืขืื ืืช ืืืคืืืงืฆืื ื-TestFlight, ืืฉืชืืฉ ืืคืงืืื:
xcrun altool
--(validate|upload)-app
-f $(find "$ProjectDir" -name "*.ipa")
-u "$DeveloperName"
-p "@keychain:Altool"
ืืขืจื ืคืจืืืจ -p
ืืชื ืืืื ืืงืืช ืืช ืืขืจื $AppPswd
ืืฆืืจื ืื ืืืฆืคื ืช (ืืคืืจืฉืช).
ืขื ืืืช, ืืคื ืฉืืืจ ืฆืืื, ืื ืงืืืช ืืื ืฉื ืืืฆืืขืื, ืขืืืฃ ืืืืืจ ื-API Key ืืืจืฉืืช altool, ืืืืืื ืฉืืืจืกืืืช ืฉืื ืืช ืฉื Xcode ืืฉ ืืขืืืช ืืกืืืืืช ("ืื ืจืืื" Keychain, ืฉืืืืืช ืืจืฉืื ืืืืื ืืขืืื ืืื').
ืื ืืื, ืืขืฆื. ืื ื ืืืื ืืื ืืืขืืจืืื ืื ืืื ืืืฆืืืช ืืืืืืจืืช ืืื ืืขืืืช ื-App Store.
ืืงืืจ: www.habr.com