Skip to content

Commit 5666752

Browse files
katipallyCopilot
andcommitted
fix(ci): full manual signing — no cloud signing, explicit provisioning profiles
Cloud signing (allowProvisioningUpdates with app-store-connect method) requires team opt-in to cloud-managed distribution certs and fails with 'Cloud signing permission error' for accounts without that permission. Switch to manual signing: - Install provisioning profiles (IOS_PROVISIONING_PROFILE_APP/NS) from secrets - Archive with CODE_SIGN_STYLE=Manual + Apple Distribution cert from keychain - Export with signingStyle=manual + explicit profile names in ExportOptions - Upload separately via xcrun altool with API key auth Requires 2 new GitHub secrets: IOS_PROVISIONING_PROFILE_APP (base64 of companion_app.mobileprovision) IOS_PROVISIONING_PROFILE_NS (base64 of companion_ns.mobileprovision) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4a7274b commit 5666752

1 file changed

Lines changed: 44 additions & 48 deletions

File tree

.github/workflows/ios-testflight.yml

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,13 @@ jobs:
8181
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${BUILD}" \
8282
NotificationService/Info.plist
8383
84-
- name: Create temporary keychain
84+
- name: Create temporary keychain & install signing assets
8585
env:
8686
KEYCHAIN_PASSWORD: ${{ secrets.IOS_KEYCHAIN_PASSWORD }}
8787
DIST_CERT_B64: ${{ secrets.IOS_DISTRIBUTION_CERTIFICATE }}
8888
DIST_CERT_PASSWORD: ${{ secrets.IOS_DISTRIBUTION_CERT_PASSWORD }}
89+
PROFILE_APP_B64: ${{ secrets.IOS_PROVISIONING_PROFILE_APP }}
90+
PROFILE_NS_B64: ${{ secrets.IOS_PROVISIONING_PROFILE_NS }}
8991
run: |
9092
set -euo pipefail
9193
KEYCHAIN_PATH="$RUNNER_TEMP/ios-build.keychain-db"
@@ -94,29 +96,32 @@ jobs:
9496
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
9597
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
9698
97-
# Import the distribution certificate if provided.
98-
# If the cert is revoked, skip import — allowProvisioningUpdates will
99-
# create a fresh distribution certificate via the App Manager API key.
100-
if [[ -n "$DIST_CERT_B64" ]]; then
101-
echo "$DIST_CERT_B64" | base64 -D > "$RUNNER_TEMP/dist.p12"
102-
IMPORT_RC=0
103-
security import "$RUNNER_TEMP/dist.p12" \
104-
-k "$KEYCHAIN_PATH" \
105-
-P "$DIST_CERT_PASSWORD" \
106-
-T /usr/bin/codesign \
107-
-T /usr/bin/security 2>&1 || IMPORT_RC=$?
108-
rm -f "$RUNNER_TEMP/dist.p12"
109-
if [ $IMPORT_RC -ne 0 ]; then
110-
echo "::warning::Distribution cert import failed (rc=${IMPORT_RC}) — may be revoked. allowProvisioningUpdates will create a fresh cert."
111-
else
112-
security set-key-partition-list \
113-
-S apple-tool:,apple:,codesign: \
114-
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
115-
echo "Distribution certificate imported successfully."
116-
fi
117-
else
118-
echo "::warning::IOS_DISTRIBUTION_CERTIFICATE not set — relying on allowProvisioningUpdates."
119-
fi
99+
# Import distribution certificate (must be valid — not revoked).
100+
echo "$DIST_CERT_B64" | base64 -D > "$RUNNER_TEMP/dist.p12"
101+
security import "$RUNNER_TEMP/dist.p12" \
102+
-k "$KEYCHAIN_PATH" \
103+
-P "$DIST_CERT_PASSWORD" \
104+
-T /usr/bin/codesign \
105+
-T /usr/bin/security
106+
security set-key-partition-list \
107+
-S apple-tool:,apple:,codesign: \
108+
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
109+
rm -f "$RUNNER_TEMP/dist.p12"
110+
echo "Distribution certificate imported."
111+
112+
# Install provisioning profiles.
113+
PP_DIR="$HOME/Library/MobileDevice/Provisioning Profiles"
114+
mkdir -p "$PP_DIR"
115+
echo "$PROFILE_APP_B64" | base64 -D > "$RUNNER_TEMP/app.mobileprovision"
116+
echo "$PROFILE_NS_B64" | base64 -D > "$RUNNER_TEMP/ns.mobileprovision"
117+
# Install using the UUID embedded in the profile as the filename.
118+
for f in "$RUNNER_TEMP/app.mobileprovision" "$RUNNER_TEMP/ns.mobileprovision"; do
119+
UUID=$(security cms -D -i "$f" 2>/dev/null | \
120+
/usr/libexec/PlistBuddy -c "Print :UUID" /dev/stdin 2>/dev/null || \
121+
grep -a -o '[0-9A-F]\{8\}-[0-9A-F]\{4\}-[0-9A-F]\{4\}-[0-9A-F]\{4\}-[0-9A-F]\{12\}' "$f" | head -1)
122+
cp "$f" "$PP_DIR/${UUID}.mobileprovision"
123+
echo "Installed profile: $UUID"
124+
done
120125
121126
- name: Write App Store Connect API key
122127
id: write-api-key
@@ -210,62 +215,53 @@ jobs:
210215
working-directory: DoomCoderCompanion
211216
env:
212217
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
213-
ASC_KEY_ID: ${{ steps.write-api-key.outputs.key_id }}
214-
ASC_ISSUER_ID: ${{ steps.write-api-key.outputs.issuer_id }}
215-
ASC_KEY_PATH: ${{ steps.write-api-key.outputs.key_path }}
216218
run: |
217-
# Strip the agent's stale GIT_CONFIG vars so SwiftPM can resolve bare repos.
218219
unset GIT_CONFIG_COUNT GIT_CONFIG_KEY_0 GIT_CONFIG_VALUE_0
219-
echo "Using key: $(basename "${ASC_KEY_PATH}")"
220+
# Manual signing: uses the distribution cert + profiles installed above.
221+
# No allowProvisioningUpdates / cloud signing — avoids "Cloud signing
222+
# permission error" which requires team-level cloud cert opt-in.
220223
xcodebuild \
221224
-project DoomCoderCompanion.xcodeproj \
222225
-scheme DoomCoderCompanion \
223226
-configuration Release \
224227
-destination 'generic/platform=iOS' \
225228
-archivePath "$RUNNER_TEMP/DoomCoderCompanion.xcarchive" \
226-
-allowProvisioningUpdates \
227-
-authenticationKeyPath "${ASC_KEY_PATH}" \
228-
-authenticationKeyID "${ASC_KEY_ID}" \
229-
-authenticationKeyIssuerID "${ASC_ISSUER_ID}" \
229+
CODE_SIGN_STYLE=Manual \
230+
CODE_SIGN_IDENTITY="Apple Distribution" \
230231
DEVELOPMENT_TEAM="${APPLE_TEAM_ID}" \
232+
PROVISIONING_PROFILE_SPECIFIER="DoomCoder Companion AppStore" \
231233
archive
232234
233235
- name: Write ExportOptions.plist
234236
run: |
235-
# method=app-store: traditional cert-based signing (uses dist cert from keychain).
236-
# destination=export: produce a signed IPA locally; upload is a separate step.
237-
# This avoids "Cloud signing permission error" from method=app-store-connect
238-
# which requires cloud-managed distribution certificates.
239237
TEAM_ID="${{ secrets.APPLE_TEAM_ID }}"
240238
cat > "$RUNNER_TEMP/ExportOptions.plist" << PLIST_EOF
241239
<?xml version="1.0" encoding="UTF-8"?>
242240
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
243241
<plist version="1.0">
244242
<dict>
245-
<key>method</key><string>app-store</string>
243+
<key>method</key><string>app-store-connect</string>
246244
<key>teamID</key><string>${TEAM_ID}</string>
245+
<key>signingStyle</key><string>manual</string>
246+
<key>provisioningProfiles</key>
247+
<dict>
248+
<key>com.doomcoder.app.companion</key><string>DoomCoder Companion AppStore</string>
249+
<key>com.doomcoder.app.companion.NotificationService</key><string>DoomCoder Companion NS AppStore</string>
250+
</dict>
247251
<key>uploadSymbols</key><true/>
248252
<key>manageAppVersionAndBuildNumber</key><false/>
249253
</dict>
250254
</plist>
251255
PLIST_EOF
252256
253257
- name: Export archive to IPA
254-
env:
255-
ASC_KEY_ID: ${{ steps.write-api-key.outputs.key_id }}
256-
ASC_ISSUER_ID: ${{ steps.write-api-key.outputs.issuer_id }}
257-
ASC_KEY_PATH: ${{ steps.write-api-key.outputs.key_path }}
258258
run: |
259259
unset GIT_CONFIG_COUNT GIT_CONFIG_KEY_0 GIT_CONFIG_VALUE_0
260260
xcodebuild \
261261
-exportArchive \
262262
-archivePath "$RUNNER_TEMP/DoomCoderCompanion.xcarchive" \
263263
-exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist" \
264-
-exportPath "$RUNNER_TEMP/export" \
265-
-allowProvisioningUpdates \
266-
-authenticationKeyPath "${ASC_KEY_PATH}" \
267-
-authenticationKeyID "${ASC_KEY_ID}" \
268-
-authenticationKeyIssuerID "${ASC_ISSUER_ID}"
264+
-exportPath "$RUNNER_TEMP/export"
269265
echo "IPA exported:"
270266
ls -lh "$RUNNER_TEMP/export/"*.ipa 2>/dev/null || ls -lh "$RUNNER_TEMP/export/"
271267
@@ -280,7 +276,7 @@ jobs:
280276
ls -la "$RUNNER_TEMP/export/"
281277
exit 1
282278
fi
283-
echo "Uploading: $IPA_PATH"
279+
echo "Uploading: $(basename "$IPA_PATH")"
284280
xcrun altool --upload-app \
285281
--type ios \
286282
--file "$IPA_PATH" \

0 commit comments

Comments
 (0)