Skip to content

Runner (self-hosted, macOS) as service fails code-signing step on xcode archive #3407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Adam-Beno opened this issue Jul 28, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@Adam-Beno
Copy link

Describe the bug
Runner fails xcode signing step while being run as a service via ./svh.sh start, however while using the runner via ./run.sh the job completes successfully

To Reproduce

  1. Create fresh ReactNative app
  2. Setup Fastlane (just ios, since android works fine). See example file below
  3. Setup workflow file. see example below
  4. Configure self-hosted runner on macOS
  5. Launch runner as service ./svc.sh install > ./svc.sh start
  6. Trigger a job for the runner
  7. Archive fails on codesigning step

Expected behavior
Using runner as service should result in the same output as using the runner via the run command.

Runner Version and Platform

System

System: MacMini
Chip: Apple M2
Memory: 8GB
macOS: Sonoma 14.5

Runner

$ tar xzf ./actions-runner-osx-arm64-2.317.0.tar.gz

Gemfile

source 'https://rubygems.org'

# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
ruby ">= 2.7.7"

# Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
# bound in the template on Cocoapods with next React Native release.
gem 'cocoapods', '>= 1.13', '< 1.15'
gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'

gem "fastlane", "~> 2.222"

What's not working?

xcodebuild fails on signing step for the first native module of a RN app. There is not really an explanation on why. Here is a rundown of things I tried to fix the issue

Note: This whole time I was able to compile the app both in XCode and by manually executing the fastlane

1. Restarting mac mini (i know i know.. its a meme but you never know)

2. Switching between automatic and manual signing

Signing is the usual culprit when building iOS apps via CI but doing any changes had no effect on the archive error.

Initially I used automatic signing from XCode by enabling it in XCode on the project itself and in Gymfile via

xcargs("-allowProvisioningUpdates")

Next I tried switching over to manual signing using Match and modifying the fastlane configs accordingly, yet the app still won't build

3. Configure fastlane to use different keychain

I noticed in the docs for fastlane they recommend adding setup_ci setup_ci to resolve potentional keychain issues but this had no effect on the error either.

4. Upgraded Ruby

Initially I used the system provided Ruby but then I found a similar error online and someone mentioned that upgrading Ruby fixed it for them. So I ended up using Ruby 2.7.7 via rvm.

Job Log Output

Fastlane Output

Creating temporary keychain: "fastlane_tmp_keychain".
Found keychain '~/Library/Keychains/fastlane_tmp_keychain', creation skipped
If creating a new Keychain DB is required please set the `require_create` option true to cause the action to fail
$ security list-keychains -d user
▸ "/Users/adambeno/Library/Keychains/login.keychain-db"
▸ "/Users/adambeno/Library/Keychains/fastlane_tmp_keychain-db"
Found keychain '/Users/adambeno/Library/Keychains/fastlane_tmp_keychain-db' in list-keychains, adding to search list skipped
Enabling match readonly mode.

...

All required keys, certificates and provisioning profiles are installed 🙌
Setting Provisioning Profile type to 'app-store'
Cruising back to lane 'ios deploy' 🚘

...

Resolving Swift Package Manager dependencies...
$ xcodebuild -resolvePackageDependencies -workspace ./ios/REDACTED.xcworkspace -scheme REDACTED
▸ Command line invocation:
▸     /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -resolvePackageDependencies -workspace ./ios/REDACTED.xcworkspace -scheme REDACTED
▸ User defaults from command line:
▸     IDEPackageSupportUseBuiltinSCM = YES
▸ resolved source packages: 
$ xcodebuild -showBuildSettings -workspace ./ios/REDACTED.xcworkspace -scheme REDACTED 2>&1
Command timed out after 3 seconds on try 1 of 4, trying again with a 6 second timeout...
Command timed out after 6 seconds on try 2 of 4, trying again with a 12 second timeout...
Detected provisioning profile mapping: {:"my.redacted.app"=>"match AppStore my.redacted.app"}

...

Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -workspace ./ios/REDACTED.xcworkspace -scheme REDACTED -sdk iphoneos17.5 -destination generic/platform=iOS -archivePath "/Users/adambeno/Library/Developer/Xcode/Archives/2024-07-28/app 2024-07-28 19.18.59.xcarchive" clean archive

User defaults from command line:
    IDEArchivePathOverride = /Users/adambeno/Library/Developer/Xcode/Archives/2024-07-28/app 2024-07-28 19.18.59.xcarchive
    IDEPackageSupportUseBuiltinSCM = YES

Build settings from command line:
    SDKROOT = iphoneos17.5


** CLEAN SUCCEEDED **

Prepare packages

ComputeTargetDependencyGraph
note: Building targets in dependency order
note: Target dependency graph (173 targets) 

...
ERROR HAPPENS HERE

mkdir -p /Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/BuildProductsPath/Release-iphoneos/REDACTED.app/Frameworks
rsync --delete -av --filter P .*.?????? --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "/Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/BuildProductsPath/Release-iphoneos/XCFrameworkIntermediates/ffmpeg-kit-ios-min-gpl/ffmpegkit.framework" "/Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/InstallationBuildProductsLocation/Applications/REDACTED.app/Frameworks"
building file list ... done
ffmpegkit.framework/
ffmpegkit.framework/Info.plist
ffmpegkit.framework/LICENSE
ffmpegkit.framework/SOURCE
ffmpegkit.framework/ffmpegkit
ffmpegkit.framework/strip-frameworks.sh

sent 595181 bytes  received 136 bytes  1190634.00 bytes/sec
total size is 594685  speedup is 1.00
Code Signing /Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/InstallationBuildProductsLocation/Applications/REDACTED.app/Frameworks/ffmpegkit.framework with Identity Apple Distribution: REDACTED (REDACTED)
/usr/bin/codesign --force --sign 229CEREDACTEDCAC  --preserve-metadata=identifier,entitlements '/Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/InstallationBuildProductsLocation/Applications/REDACTED.app/Frameworks/ffmpegkit.framework'

# THIS ??
/Users/adambeno/Library/Developer/Xcode/DerivedData/REDACTED-bjrkhordkwvgekgrnokrjfrpnvrj/Build/Intermediates.noindex/ArchiveIntermediates/REDACTED/InstallationBuildProductsLocation/Applications/REDACTED.app/Frameworks/ffmpegkit.framework: errSecInternalComponent


Command PhaseScriptExecution failed with a nonzero exit code

EOF

Configs

Workflow

name: Build and distribute the Android and iOS apps

on:
  push:
    branches:
      - master

jobs:
  build-ios:
    runs-on: [self-hosted, macOS]
    timeout-minutes: 20

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install NPM
        run: npm ci

      - name: Install bundle
        run: bundle install

      - name: Build app
        run: bundle exec fastlane ios deploy

Fastfile

fastlane_require "dotenv"

before_all do
  ensure_git_status_clean
  update_fastlane
  Dotenv.overload ".env"
end

platform :ios do

  private_lane :signing do |options|
    setup_ci(timeout: 0)
    
    match(
      type: options[:type],
      readonly: is_ci
    )
  end

  private_lane :appstore_connect do
    app_store_connect_api_key(
      key_id: ENV["APPSTORE_CONNECT_KEY_ID"],
      issuer_id: ENV["APPSTORE_CONNECT_ISSUER"],
      key_filepath: ENV["APPSTORE_CONNECT_KEY"],
      duration: 1200, # optional (maximum 1200)
      in_house: true # optional but may be required if using match/sigh
    )
  end


  desc "Build new version of the app"
  lane :build do
    # Install pods
    cocoapods(
      podfile: "./ios",
      clean_install: true
    )

    signing(type: "appstore")

    # Build the .ipa from gymfile
    gym
  end

  lane :deploy do
    # Configure appstore connect API
    appstore_connect

    # Install pods
    cocoapods(
      podfile: "./ios",
      clean_install: true
    )

    signing(type: "appstore")

    # Build the app
    gym
    
    # Distribute app to TestFlight
    pilot
  end
end

Appfile

json_key_file("./service-account.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
package_name("my.redacted.app") # e.g. com.krausefx.app

app_identifier("myredacted.app") # The bundle identifier of your app
apple_id("accounts@redacted.my") # Your Apple Developer Portal username

itc_team_id("REDACTED") # App Store Connect Team ID
team_id("REDACTED") # Developer Portal Team ID

# For more information about the Appfile, see:
#     https://docs.fastlane.tools/advanced/#appfile

Gymfile

# For more information about this configuration visit
# https://docs.fastlane.tools/actions/gym/#gymfile

# In general, you can use the options available
# fastlane gym --help

# Remove the # in front of the line to enable the option

workspace("./ios/REDACTED.xcworkspace")
sdk("iphoneos17.5")
scheme("REDACTED")

clean(true)
export_method("app-store")

# Enable automatic signing via xcode
# xcargs("-allowProvisioningUpdates") // Switched over to manual signing

include_symbols(true)
include_bitcode(false)

output_directory("./fastlane/builds/")
output_name("app.ipa")
buildlog_path("./fastlane/logs/")

Conclusion

I intially thought it's the service being unable to reach the keychain but after setting up the setup_ci step in fastlane and it having access to the chain + being able to write the certs I really have no idea what could be causing this issue. Maybe it's just xcode being xcode again...

At least I can still use the pipeline with ./run.sh to keep my autobuilds going 🙏

@Adam-Beno Adam-Beno added the bug Something isn't working label Jul 28, 2024
@kaijietti
Copy link

I encountered the same issue, when i am using runner as service, i got error like this:

CodeSign /Users/administrator/path/to/target.appex (in target 'target' from project 'project' at path '/Users/administrator/path/to/project.xcodeproj')
    cd xxx
    
    Signing Identity:     "Apple Development: xxx xx (XXXXXXX)"
    Provisioning Profile: "iOS Team Provisioning Profile: com.xxx.xxx"
                          (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
    
    /usr/bin/codesign --force --sign XXXXXXXXXXXXXXXXXXXXX --entitlements /Users/administrator/xxxx.appex.xcent --generate-entitlement-der /Users/administrator/xxxx.appex
/Users/administrator/xxxx.appex: errSecInternalComponent
Command CodeSign failed with a nonzero exit code

But when i am using ./run.sh in terminal directly, everything is fine.

@kaijietti
Copy link

@Adam-Beno, I managed to code-signing when running runner as a service, i just tried unlocking login keychain (my signing key is on the login keychain) before running the xcodebuild cmd, and it works!
Here's my code:

# ....
print("unlocking login keychain...")
# check if there is a file named login.keychain-password in the LOGIN_KEYCHAIN_PASSWORD_PATH
login_keychain_password_path = LOGIN_KEYCHAIN_PASSWORD_PATH.joinpath(
    "login.keychain-password"
)
if login_keychain_password_path.exists():
    keychain_password = login_keychain_password_path.read_text().strip()
    if keychain_password:
        print("unlocking login keychain with password...")
        subprocess.run(
            [
                "security",
                "unlock-keychain",
                "-p",
                keychain_password,
                "login.keychain",
            ],
            check=True,
        )
    else:
        print("unlocking login keychain without password...")
        subprocess.run(
            [
                "security",
                "unlock-keychain",
                "login.keychain",
            ],
            check=True,
        )
else:
    print("login.keychain-password file not found, don't unlock login keychain")

## ....

print("cleaning...")
subprocess.run(
    [
        "xcodebuild",
        "clean",
        "-project",
        XCODE_PROJECT_PATH,
        "-scheme",
        scheme,
        "-derivedDataPath",
        derived_data_path,
        "-resultBundlePath",
        xcode_result_bundle_path("build_clean"),
        # *xcodebuild_authenticate_args,
    ],
    check=True,
    env=env,
)

print("archiving...")
subprocess.run(
    [
        "xcodebuild",
        "archive",
        "-project",
        XCODE_PROJECT_PATH,
        "-scheme",
        scheme,
        "-configuration",
        build_configuration,
        "-sdk",
        "iphoneos",
        "-destination",
        "generic/platform=iOS",
        "-archivePath",
        archive_path,
        "-derivedDataPath",
        derived_data_path,
        "-resultBundlePath",
        xcode_result_bundle_path("build_archive"),
        "-showBuildTimingSummary",
        *xcodebuild_authenticate_args,
    ],
    check=True,
    env=env,
)

@doubuns
Copy link

doubuns commented Oct 29, 2024

I encountered the same problem when using svc.sh to start runner.
After looking at the code of run.sh and svc.sh, I found that run.sh updates ca certificates, but svc.sh does not update.

In order to perform xcode compilation normally, you can only use run.sh to start runner.

@paxbun
Copy link

paxbun commented Nov 30, 2024

@douba0 I don't know the exact reason, but if run.sh works well while svc.sh does not, setting SessionCreate to false in bin/actions.runner.plist.template like the following may be a solution.

<plist version="1.0">
  ...
  <key>SessionCreate</key>
  <false/>
</plist>

After reinstalling the service, the signing task in my workflow worked well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants