Reputation: 5674
I have slightly different approach for building iOS apps. Instead of putting a bunch of code in the .yaml file, I prefer to put most stuff in a shell script and have a simpler .yaml file... is there any problem in this approach?
My build gets stuck in the "Build app" step. The other steps work fine. Intermittently, like once every 15 times it just magically works, but most of the time it fails. It gets stuck and I can't see the log, until I cancel the job, but the log doesn't say anything useful. Running the scripts in my local machine works 100% of time. It seems to be something very particular to GitHub actions.
Is there any problem, limitation on using this approach (bash script) in GitHub actions? Why would this fail?
I am not using using fastlane. Here is my YAML file:
name: Build iOS
on:
push:
branches:
- master
jobs:
build:
runs-on: macOS-latest
steps:
- uses: actions/checkout@v2
- name: Switch XCode Version
run: sudo xcode-select -s /Applications/Xcode_11.2.app
- name: Get dependencies
run: source .github/ios/build.sh && get_dependencies
- name: Decrypt secrets
run: source .github/ios/build.sh && decrypt_secrets ${{ secrets.SECRET_KEY }}
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
- name: Set up code signing
run: source .github/ios/build.sh && setup_code_signing
- name: Build app
run: source .github/ios/build.sh && build_app
- name: Upload artifacts
run: source .github/ios/build.sh && upload_artifacts
and the script
#!/bin/bash
PROVISIONING_PROFILE="MyApp"
CODE_SIGN_IDENTITY="Apple Development: MyApp (XXXXXXXXXX)"
DOMAIN="MyApp.com"
PRODUCT_BUNDLE_IDENTIFIER="com.MyApp.app"
# Get dependencies
function get_dependencies()
{
yarn
cd ios
pod install
cd ..
}
function decrypt
{
INPUT=$1
OUTPUT="${1%.*}"
openssl aes-256-cbc -salt -a -d -in $INPUT -out $OUTPUT -pass pass:$SECRET_KEY
}
# Decrypt secrets
function decrypt_secrets
{
export SECRET_KEY=$1
decrypt .github/ios/secrets/MyApp.mobileprovision.encrypted
decrypt .github/ios/secrets/MyApp.p12.encrypted
decrypt .github/ssh/id_rsa.encrypted
}
# Set up code signing
function setup_code_signing()
{
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# provisioning
cp .github/ios/secrets/MyApp.mobileprovision ~/Library/MobileDevice/Provisioning\ Profiles/$PROVISIONING_PROFILE.mobileprovision
# keychain
security create-keychain -p "MyApp" build.keychain
security import ./.github/ios/secrets/MyApp.p12 -t agg -k ~/Library/Keychains/build.keychain -P "" -A
security list-keychains -s ~/Library/Keychains/build.keychain
security default-keychain -s ~/Library/Keychains/build.keychain
security unlock-keychain -p "MyApp" ~/Library/Keychains/build.keychain
security set-key-partition-list -S apple-tool:,apple: -s -k "MyApp" ~/Library/Keychains/build.keychain
}
# Build
function build_app()
{
# dev environment
echo "API_URL=https://backend.$DOMAIN/" > .env
# build number
BUILD_NUMBER=${GITHUB_RUN_NUMBER:-1}
# ExportOptions.plist
sed -e "s/__BUILD_NUMBER__/$BUILD_NUMBER/g" \
-e "s/__PRODUCT_BUNDLE_IDENTIFIER__/$PRODUCT_BUNDLE_IDENTIFIER/g" \
-e "s/__CODE_SIGN_IDENTITY__/$CODE_SIGN_IDENTITY/g" \
.github/ios/ExportOptions.plist > ios/ExportOptions.plist
cd ios
set -e
set -o pipefail
# archive
xcodebuild archive \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-sdk iphoneos13.2 \
-configuration Release \
-archivePath "$PWD/build/MyApp.xcarchive" \
PRODUCT_BUNDLE_IDENTIFIER="$PRODUCT_BUNDLE_IDENTIFIER" \
PROVISIONING_PROFILE="$PROVISIONING_PROFILE" \
CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY" \
CURRENT_PROJECT_VERSION="$BUILD_NUMBER"
# export
xcodebuild \
-exportArchive \
-archivePath "$PWD/build/MyApp.xcarchive" \
-exportOptionsPlist "$PWD/ExportOptions.plist" \
-exportPath "$PWD/build"
}
# Upload artifacts
function upload_artifacts()
{
chmod 600 .github/ssh/id_rsa
BUILD_PATH="www/app/builds/$GITHUB_RUN_NUMBER"
ssh -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' [email protected] "mkdir -p $BUILD_PATH"
scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/Apps/* [email protected]:$BUILD_PATH
scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/manifest.plist [email protected]:$BUILD_PATH
}
Most of the time, the log gets stuck on this line:
/usr/bin/codesign --force --sign F4D55F28BEBE840ADF175A67B471FFBF2E27B222 --entitlements /Users/runner/Library/Developer/Xcode/DerivedData/MyApp-fhnolcbrhrsoglcxtgrffszyvmwz/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/IntermediateBuildFilesPath/MyApp.build/Release-iphoneos/MyApp.build/MyApp.app.xcent --timestamp=none /Users/runner/Library/Developer/Xcode/DerivedData/MyApp-fhnolcbrhrsoglcxtgrffszyvmwz/Build/Intermediates.noindex/ArchiveIntermediates/MyApp/InstallationBuildProductsLocation/Applications/MyApp.app
Upvotes: 2
Views: 2089
Reputation: 5674
Kudos to the answers from here: Jenkins - Xcode build works codesign fails
The problem that happened to me is that I was trying to follow the first only the first answer from Jamieson (the accepted one), but maybe it is not up to date anymore.
I used the answer from Stephen Quan and it worked perfectly! My final keychain part now is:
# Create temporary keychain
KEYCHAIN="MyApp$$.keychain"
KEYCHAIN_PASSWORD="MyApp"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
# Append keychain to the search list
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | sed s/\"//g)
security list-keychains
# Unlock the keychain
security set-keychain-settings "$KEYCHAIN"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
# Import certificate
security import .github/ios/secrets/MyApp.p12 -k "$KEYCHAIN" -P "" -T "/usr/bin/codesign"
# Detect the iOS identity
IOS_IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN" | head -1 | grep '"' | sed -e 's/[^"]*"//' -e 's/".*//')
IOS_UUID=$(security find-identity -v -p codesigning "$KEYCHAIN" | head -1 | grep '"' | awk '{print $2}')
# New requirement for MacOS 10.12+
security set-key-partition-list -S apple-tool:,apple: -s -k $KEYCHAIN_PASSWORD $KEYCHAIN
Upvotes: 3