The deliver action fails to upload the build to TestFlight. The error seems to be related to the App Store Connect API Key and altool.
This is my first time trying out both the Fastlane and GitHub Actions. I followed this blog to setup the CD pipeline.
All the lanes work except the upload_release. In it, I have the deliver action that results in the below error.
2023-12-04T01:38:46.4266500Z [01:38:46]: [33m[altool] "Error Domain=ITunesConnectionAuthenticationErrorDomain Code=-26000 \"Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_***.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_***.p8, NSStringEncoding=4}\" UserInfo={NSLocalizedRecoverySuggestion=Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_***.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_***.p8, NSStringEncoding=4}, NSLocalizedDescription=Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_***.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_***.p8, NSStringEncoding=4}, NSLocalizedFailureReason=App Store operation failed.}"
Complete output when running fastlane, including the stack trace and command used
Run bundle exec fastlane ios build_upload_testflight
bundle exec fastlane ios build_upload_testflight
shell: /bin/bash -e {0}
env:
PATH: /usr/local/opt/pipx_bin:/Users/runner/.cargo/bin:/usr/local/opt/curl/bin:/usr/local/bin:/usr/local/sbin:/Users/runner/bin:/Users/runner/.yarn/bin:/Users/runner/Library/Android/sdk/tools:/Users/runner/Library/Android/sdk/platform-tools:/Library/Frameworks/Python.framework/Versions/Current/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/usr/bin:/bin:/usr/sbin:/sbin:/Users/runner/.dotnet/tools:/Users/runner/.ghcup/bin
ASC_KEY_ID: ***
ASC_ISSUER_ID: ***
ASC_KEY: ***
SIGNING_KEY_PASSWORD: ***
SIGNING_KEY_FILE_PATH: signing-cert.p1[2](https://github.com/companyName/appName-iOS/actions/runs/7080820352/job/19269238310#step:8:2)
[01:[3](https://github.com/companyName/appName-iOS/actions/runs/7080820352/job/19269238310#step:8:3)0:56]: Sending anonymous analytics information
[01:30:56]: Learn more at https://docs.fastlane.tools/#metrics
[01:30:56]: No personal or sensitive data is sent.
[01:30:56]: You can disable this by adding `opt_out_usage` at the top of your Fastfile
[01:30:56]: ------------------------------
[01:30:56]: --- Step: default_platform ---
[01:30:56]: ------------------------------
[01:30:56]: Driving the lane 'ios build_upload_testflight' 🚀
[01:30:56]: -------------------------------------------------
[01:30:56]: --- Step: Switch to ios load_asc_api_key lane ---
[01:30:56]: -------------------------------------------------
[01:30:56]: Cruising over to lane 'ios load_asc_api_key' 🚖
[01:30:56]: ---------------------------------------
[01:30:56]: --- Step: app_store_connect_api_key ---
[01:30:56]: ---------------------------------------
[01:30:56]: Cruising back to lane 'ios build_upload_testflight' 🚘
[01:30:56]: ------------------------------------------------
[01:30:56]: --- Step: Switch to ios prepare_signing lane ---
[01:30:56]: ------------------------------------------------
[01:30:56]: Cruising over to lane 'ios prepare_signing' 🚖
[01:30:56]: -----------------------------
[01:30:56]: --- Step: create_keychain ---
[01:30:56]: -----------------------------
[01:30:56]: $ security list-keychains -d user
[01:30:56]: ▸ "/Users/runner/Library/Keychains/signing-db"
[01:30:56]: Found keychain '/Users/runner/Library/Keychains/signing-db' in list-keychains, adding to search list skipped
[01:30:56]: --------------------------------
[01:30:56]: --- Step: import_certificate ---
[01:30:56]: --------------------------------
[01:30:56]: Setting key partition list... (this can take a minute if there are a lot of keys installed)
[01:30:56]: ------------------
[01:30:56]: --- Step: sigh ---
[01:30:56]: ------------------
[01:30:56]: Creating authorization token for App Store Connect API
[01:30:56]: Fetching profiles...
[01:30:57]: Verifying certificates...
[01:30:59]: Found 1 matching profile(s)
[01:30:59]: Downloading provisioning profile...
[01:30:59]: Successfully downloaded provisioning profile...
[01:30:59]: Installing provisioning profile...
/Users/runner/work/-iOS/-iOS/AppStore_com.clientName.***STG.mobileprovision
[01:30:59]: Setting Provisioning Profile type to 'app-store'
[01:30:59]: Cruising back to lane 'ios build_upload_testflight' 🚘
[01:30:59]: -----------------------------------------------------------------
[01:30:59]: --- Step: Switch to ios fetch_and_increment_build_number lane ---
[01:30:59]: -----------------------------------------------------------------
[01:30:59]: Cruising over to lane 'ios fetch_and_increment_build_number' 🚖
[01:30:59]: --------------------------------
[01:30:59]: --- Step: get_version_number ---
[01:30:59]: --------------------------------
[01:31:00]: --------------------------------------------
[01:31:00]: --- Step: latest_testflight_build_number ---
[01:31:00]: --------------------------------------------
[01:31:00]: Creating authorization token for App Store Connect API
[01:31:01]: Fetching the latest build number for version 2.0.1
[01:31:01]: Latest upload for version 2.0.1 on ios platform is build: 17
[01:31:01]: ------------------------------------
[01:31:01]: --- Step: increment_build_number ---
[01:31:01]: ------------------------------------
Current version of project *** is:
1
9
/Users/runner/work/-iOS/-iOS
[01:31:03]: $ cd /Users/runner/work/-iOS/-iOS && agvtool new-version -all 18 && cd -
[01:31:03]: ▸ Setting version of project *** to:
[01:31:03]: ▸ 18.
[01:31:03]: ▸ Also setting CFBundleVersion key (assuming it exists)
[01:31:04]: ▸ Updating CFBundleVersion in Info.plist(s)...
[01:31:04]: ▸ Updated CFBundleVersion in ".xcodeproj/..//Common/Configuration/plist/DEV Simulator Info.plist" to 18
[01:31:04]: ▸ Updated CFBundleVersion in ".xcodeproj/..//Common/Configuration/plist/Info.plist" to 18
[01:31:04]: ▸ Updated CFBundleVersion in ".xcodeproj/..//Common/Configuration/plist/STG Info.plist" to 18
[01:31:04]: ▸ Updated CFBundleVersion in ".xcodeproj/..//Common/Configuration/plist/TST Info.plist" to 18
[01:31:04]: ▸ Updated CFBundleVersion in ".xcodeproj/../Tests/Info.plist" to 18
[01:31:04]: ▸ /Users/runner/work/-iOS/-iOS
[01:31:04]: Cruising back to lane 'ios build_upload_testflight' 🚘
[01:31:04]: ----------------------------------------------
[01:31:04]: --- Step: Switch to ios build_release lane ---
[01:31:04]: ----------------------------------------------
[01:31:04]: Cruising over to lane 'ios build_release' 🚖
[01:31:04]: ------------------------------------------
[01:31:04]: --- Step: update_code_signing_settings ---
[01:31:04]: ------------------------------------------
[01:31:04]: Updating the Automatic Codesigning flag to disabled for the given project '/Users/runner/work/-iOS/-iOS/.xcodeproj/project.pbxproj'
[01:31:04]: Skipping *** not selected ( STG)
[01:31:04]: Skipping Debug not selected (Release)
[01:31:04]: Set Code Sign identity to: Apple Distribution for target: *** STG for build configuration: Release
[01:31:04]: Set Provisioning Profile name to: STG Distribution for target: *** STG for build configuration: Release
[01:31:04]: Set Bundle identifier to: com.clientName.STG for target: *** STG for build configuration: Release
[01:31:04]: Skipping *** DEV not selected ( STG)
[01:31:04]: Skipping *** DEV Simulator not selected ( STG)
[01:31:04]: Skipping Tests not selected ( STG)
[01:31:04]: Successfully updated project settings to use Code Sign Style = 'Manual'
[01:31:04]: Modified Targets:
[01:31:04]: * *** STG
[01:31:04]: Modified Build Configurations:
[01:31:04]: * Release
[01:31:04]: -----------------------
[01:31:04]: --- Step: cocoapods ---
[01:31:04]: -----------------------
[01:31:06]: $ bundle exec pod install --clean-install
[01:31:13]: ▸ Analyzing dependencies
[01:31:13]: ▸ Adding spec repo trunk with CDN https://cdn.cocoapods.org/
[01:31:13]: ▸ CocoaPods 1.14.3 is available.
[01:31:13]: ▸ To update use: gem install cocoapods
[01:31:13]: ▸ For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.14.3
[01:31:13]: ▸ Downloading dependencies
[01:31:13]: ▸ Installing Alamofire (5.4.4)
[01:31:15]: ▸ Installing Connectivity (5.0.0)
[01:31:17]: ▸ Installing IQKeyboardManagerSwift (6.5.11)
[01:31:20]: ▸ Installing JTAppleCalendar (8.0.4)
[01:31:21]: ▸ Installing PinCodeTextField (0.1.0)
[01:31:23]: ▸ Installing Socket.IO-Client-Swift (16.0.1)
[01:31:24]: ▸ Installing Starscream (4.0.4)
[01:31:25]: ▸ Installing lottie-ios (3.2.3)
[01:31:29]: ▸ Generating Pods project
[01:31:29]: ▸ Integrating client project
[01:31:29]: ▸ Pod installation complete! There are 7 dependencies from the Podfile and 8 total pods installed.
[01:31:29]: --------------------
[01:31:29]: --- Step: xcodes ---
[01:31:29]: --------------------
[01:31:29]: Running xcodes version 1.4.1
[01:31:29]: $ /usr/local/bin/xcodes installed '14.3.1'
[01:31:29]: ▸ /Applications/Xcode_14.3.1.app
[01:31:29]: Setting Xcode version '14.3.1' at '/Applications/Xcode_14.3.1.app' for all build steps
[01:31:29]: -----------------
[01:31:29]: --- Step: gym ---
[01:31:29]: -----------------
[01:31:30]: Resolving Swift Package Manager dependencies...
[01:31:30]: $ xcodebuild -resolvePackageDependencies -workspace ***.xcworkspace -scheme ***\ STG -configuration Release
[01:31:31]: ▸ 2023-12-04 01:31:31.641 xcodebuild[7463:37875] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
[01:31:31]: ▸ Command line invocation:
[01:31:31]: ▸ /Applications/Xcode_14.3.1.app/Contents/Developer/usr/bin/xcodebuild -resolvePackageDependencies -workspace .xcworkspace -scheme " STG" -configuration Release
[01:31:31]: ▸ User defaults from command line:
[01:31:31]: ▸ IDEPackageSupportUseBuiltinSCM = YES
[01:32:36]: ▸ Resolve Package Graph
[01:34:19]: $ xcodebuild -showBuildSettings -workspace ***.xcworkspace -scheme ***\ STG -configuration Release
2023-12-04 01:34:22.199 xcodebuild[8974:42658] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
[01:34:22]: Command timed out after 3 seconds on try 1 of 4, trying again with a 6 second timeout...
2023-12-04 01:34:23.790 xcodebuild[8976:42691] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
[01:34:28]: Command timed out after 6 seconds on try 2 of 4, trying again with a 12 second timeout...
2023-12-04 01:34:30.473 xcodebuild[8981:42741] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
2023-12-04 01:34:36.347 xcodebuild[8974:42809] Requested but did not find extension point with identifier Xcode.InterfaceBuilderBuildSupport.PlatformDefinition
2023-12-04 01:34:36.974 xcodebuild[8976:42886] Requested but did not find extension point with identifier Xcode.InterfaceBuilderBuildSupport.PlatformDefinition
[01:34:40]: Command timed out after 12 seconds on try 3 of 4, trying again with a 24 second timeout...
2023-12-04 01:34:41.990 xcodebuild[9184:43331] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
2023-12-04 01:34:43.348 xcodebuild[8981:43507] Requested but did not find extension point with identifier Xcode.InterfaceBuilderBuildSupport.PlatformDefinition
2023-12-04 01:34:54.207 xcodebuild[9184:43628] Requested but did not find extension point with identifier Xcode.InterfaceBuilderBuildSupport.PlatformDefinition
[01:34:55]: Detected provisioning profile mapping: {:"com.clientName.***STG"=>"STG Distribution", :"country.appName.appNameapp"=>" AppStore - Jan 10, 2022", :"com.clientName.***TST"=>"match AppStore com.clientName.***TST"}
[01:34:55]: $ set -o pipefail && xcodebuild -workspace .xcworkspace -scheme \ STG -configuration Release -destination 'generic/platform=iOS' -archivePath /Users/runner/Library/Developer/Xcode/Archives/2023-12-04/\ STG\ 2023-12-04\ 01.34.55.xcarchive archive | tee /Users/runner/Library/Logs/gym/\ STG-\ STG.log | xcpretty
[01:34:56]: ▸ 2023-12-04 01:34:56.572 xcodebuild[9290:43687] DVTCoreDeviceEnabledState: DVTCoreDeviceEnabledState_Disabled set via user default (DVTEnableCoreDevice=disabled)
[01:35:13]: ▸ 2023-12-04 01:35:13.556 xcodebuild[9290:43687] [MT] IDEFileReferenceDebug: [Load] <IDESwiftPackageCore.IDESwiftPackageSpecialFolderFileReference, 0x6000011bb300: name:Docs.docc path:group:Docs.docc> Failed to load container at path: /Users/runner/Library/Developer/Xcode/DerivedData/-afhujhumhapxtmgbhchvzeyjrald/SourcePackages/checkouts/swift-protobuf/Sources/protoc-gen-swift/Docs.docc, Error: Error Domain=com.apple.dt.IDEContainerErrorDomain Code=6 "Cannot open "Docs.docc" as a "Swift Package Folder" because it is already open as a "Folder"." UserInfo={NSLocalizedDescription=Cannot open "Docs.docc" as a "Swift Package Folder" because it is already open as a "Folder".}
[01:38:42]: Successfully exported and compressed dSYM file
[01:38:42]: Successfully exported and signed the ipa file:
[01:38:42]: /Users/runner/work/-iOS/-iOS/*** STG.ipa
[01:38:42]: Cruising back to lane 'ios build_upload_testflight' 🚘
[01:38:42]: -----------------------------------------------
[01:38:42]: --- Step: Switch to ios upload_release lane ---
[01:38:42]: -----------------------------------------------
[01:38:42]: Cruising over to lane 'ios upload_release' 🚖
[01:38:42]: ---------------------
[01:38:42]: --- Step: deliver ---
[01:38:42]: ---------------------
[01:38:42]: Creating authorization token for App Store Connect API
[01:38:42]: Uploading binary to App Store Connect
[01:38:44]: Going to upload updated app to App Store Connect
[01:38:44]: This might take a few minutes. Please don't interrupt the script.
01:38:46: [altool] 2023-12-04 01:38:46.423 *** Error: Unable to upload archive. Failed to authenticate with errors: (
01:38:46: [altool] ) (-1011)
01:38:46: [altool] {
01:38:46: [altool] NSLocalizedDescription = "Unable to upload archive.";
01:38:46: [altool] NSLocalizedFailureReason = "Failed to authenticate with errors: (\n "Error Domain=ITunesConnectionAuthenticationErrorDomain Code=-26000 \"Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_.p8, NSStringEncoding=4}\" UserInfo={NSLocalizedRecoverySuggestion=Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_.p8, NSStringEncoding=4}, NSLocalizedDescription=Failed to generate JWT token: Error Domain=NSCocoaErrorDomain Code=261 \"The file \U201cAuthKey_.p8\U201d couldn\U2019t be opened using text encoding Unicode (UTF-8).\" UserInfo={NSFilePath=/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/deliver-20231204-7022-lxllu8/AuthKey_.p8, NSStringEncoding=4}, NSLocalizedFailureReason=App Store operation failed.}"\n)";
[!] Error uploading ipa file:
[Application Loader Error Output]: Error uploading '/var/folders/q4/3s60g5510ydbd3qc3p4xflm80000gn/T/6e977970-0c61-468b-8a18-f5bdbf65c337.ipa'.
[Application Loader Error Output]: Unable to upload archive. Failed to authenticate with errors: (
[Application Loader Error Output]: The call to the altool completed with a non-zero exit status: 1. This indicates a failure.
Error: Process completed with exit code 1.
default_platform(:ios)
platform :ios do
# desc "Load AppStore Connect API Key to use in subsequent lanes"
lane :load_asc_api_key do
app_store_connect_api_key(
key_id: ENV["ASC_KEY_ID"],
issuer_id: ENV["ASC_ISSUER_ID"],
key_content: ENV["ASC_KEY"],
is_key_content_base64: true,
in_house: false # Detecting this via ASC private key is currently not supported
)
end
desc "Bump build number based on the most recent TestFlight build number"
lane :fetch_and_increment_build_number do
#fetch read your app identifier defined in your Appfile
app_identifier = CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
api_key = lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
current_version = get_version_number(
target: "appName STG" # replace with your main target, required if you have more than one non-test target
)
latest_build_number = latest_testflight_build_number(
api_key: api_key,
version: current_version,
app_identifier: app_identifier
)
increment_build_number(
build_number: (latest_build_number + 1),
)
end
desc "Installs signing certificate in the keychain and downloads provisioning profiles from the App Store Connect"
lane :prepare_signing do |options|
team_id = CredentialsManager::AppfileConfig.try_fetch_value(:team_id)
api_key = lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
keychain_name = "signing"
keychain_password = "temp"
delete_keychain(
name: keychain_name
) if File.exist? File.expand_path("~/Library/Keychains/#{keychain_name}-db")
create_keychain(
name: keychain_name,
password: keychain_password,
default_keychain: true,
unlock: true,
timeout: 3600
)
import_certificate(
certificate_path: ENV["SIGNING_KEY_FILE_PATH"],
certificate_password: ENV["SIGNING_KEY_PASSWORD"],
keychain_name: keychain_name,
keychain_password: keychain_password
)
# fetches and installs provisioning profiles from ASC
sigh(
api_key: api_key,
readonly: true
)
end
desc "Build the iOS app for release"
lane :build_release do |options|
app_identifier = CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier)
profile_name = "appNameSTG Distribution"
export_method = "app-store"
# turn off automatic signing during build so correct code signing identity is guaranteed to be used
update_code_signing_settings(
use_automatic_signing: false,
targets: ["appName STG"],
code_sign_identity: "Apple Distribution",
bundle_identifier: app_identifier,
profile_name: profile_name,
build_configurations: ["Release"]
)
# install Pods
cocoapods(
clean_install: true
)
# Specify the Xcode version
xcodes(
version: "14.3.1",
select_for_current_build_only: true
)
# build the app
gym(
scheme: "appName STG",
workspace: "appName.xcworkspace",
configuration: "Release",
export_options: {
method: export_method,
provisioningProfiles: {
app_identifier => profile_name
}
}
)
end
desc "Upload to TestFlight / AppStore Connect"
lane :upload_release do
api_key = lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
deliver(
api_key: api_key,
skip_screenshots: true,
skip_metadata: true,
skip_app_version_update: true,
force: true, # skips verification of HTML preview file (since this will be run from a CI machine)
run_precheck_before_submit: false # not supported through ASC API yet
)
end
desc "Build and upload to TestFlight"
lane :build_upload_testflight do
load_asc_api_key
prepare_signing
fetch_and_increment_build_number
build_release
upload_release
end
end
`./fastlane/Appfile`
app_identifier("com.clientName.appNameSTG") # The bundle identifier of the staging app
# apple_id("[[APPLE_ID]]") # Your Apple email address
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile
I'm still facing issues with the deliver action failing to upload builds to TestFlight.
Could someone provide guidance on resolving this? Your help is much appreciated.
I wanted to bring your attention back to this issue I opened on Dec 4, 2023. Unfortunately, we haven't had any responses yet.
I understand everyone's busy, but if you could spare a moment, your insights would be incredibly valuable. I'm reaching out to the following contributors for their expertise:
JWT token: Error Domain=NSCocoaErrorDomain Code=261 "The file U201cAuthKey_***.p8U201d couldnU2019t be opened using text encoding Unicode (UTF-8)
I suspect your p8 file is incorrectly encoded. Questions: Are you sure the content of ASC_KEY is base64 encoded? Have you tried with is_key_content_base64: false