@@ -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