iOS 构建在 GitHub 操作上失败(没有 fastlane),但它会间歇性地工作

iOS build fails on GitHub Actions (without fastlane), but it works intermittently

我构建 iOS 应用程序的方法略有不同。与其将一堆代码放在 .yaml 文件中,我更喜欢将大部分内容放在 shell 脚本中并有一个更简单的 .yaml 文件...这种方法有什么问题吗?

我的构建卡在了 "Build app" 步骤。其他步骤工作正常。 间歇性地,就像每 15 次一次它神奇地起作用,但大多数时候它都失败了。它卡住了,我看不到日志,直到我取消作业,但日志没有说任何有用的东西。 运行 我本地机器上的脚本 100% 有效。 GitHub actions.

好像很特别

在GitHub 操作中使用此方法(bash 脚本)是否有任何问题和限制? 为什么会失败?

我没有使用 fastlane。 这是我的 YAML 文件:

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

和剧本

#!/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=
    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=
    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' ubuntu@MyApp.dev "mkdir -p $BUILD_PATH"
    scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/Apps/* ubuntu@MyApp.dev:$BUILD_PATH
    scp -i .github/ssh/id_rsa -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no' -r ios/build/manifest.plist ubuntu@MyApp.dev:$BUILD_PATH
}

大多数时候,日志卡在这一行:

/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

感谢这里的回答: Jenkins - Xcode build works codesign fails

发生在我​​身上的问题是,我试图仅遵循 Jamieson 的第一个答案(已接受的答案),但也许它不再是最新的了。

我使用了 Stephen Quan 的答案,效果非常好! 我现在的最后一个钥匙串部分是:

# 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 }')

# New requirement for MacOS 10.12+
security set-key-partition-list -S apple-tool:,apple: -s -k $KEYCHAIN_PASSWORD $KEYCHAIN