Skip to content

TestFlight

TestFlight #52

Workflow file for this run

name: TestFlight
on:
workflow_dispatch:
inputs:
version:
description: 'Marketing version (e.g. 1.2.0). Leave empty to keep current.'
required: false
type: string
permissions:
contents: write
jobs:
testflight:
runs-on: macos-26
env:
APP_STORE_API_KEY: ${{ secrets.APP_STORE_API_KEY }}
APP_STORE_API_ISSUER: ${{ secrets.APP_STORE_API_ISSUER }}
steps:
- uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Secrets
env:
MAPBOX_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
WK_KEY_ID: ${{ secrets.WEATHERKIT_KEY_ID }}
WK_TEAM_ID: ${{ secrets.WEATHERKIT_TEAM_ID }}
WK_PRIVATE_KEY: ${{ secrets.WEATHERKIT_PRIVATE_KEY }}
run: |
printf 'MAPBOX_ACCESS_TOKEN = %s\nWEATHERKIT_KEY_ID = %s\nWEATHERKIT_TEAM_ID = %s\nWEATHERKIT_PRIVATE_KEY = %s\n' \
"$MAPBOX_TOKEN" "$WK_KEY_ID" "$WK_TEAM_ID" "$WK_PRIVATE_KEY" > Secrets.xcconfig
- name: Setup Mapbox netrc
env:
MAPBOX_TOKEN: ${{ secrets.MAPBOX_SECRET_TOKEN }}
run: |
echo "machine api.mapbox.com" >> ~/.netrc
echo "login mapbox" >> ~/.netrc
echo "password $MAPBOX_TOKEN" >> ~/.netrc
chmod 600 ~/.netrc
- name: Setup API Key
env:
API_KEY_BASE64: ${{ secrets.APP_STORE_API_KEY_BASE64 }}
run: |
mkdir -p ~/.private_keys
echo "$API_KEY_BASE64" | base64 -d > ~/.private_keys/AuthKey_"$APP_STORE_API_KEY".p8
- name: Install Distribution Certificate
env:
CERT_BASE64: ${{ secrets.DISTRIBUTION_CERT_BASE64 }}
CERT_PASSWORD: ${{ secrets.DISTRIBUTION_CERT_PASSWORD }}
run: |
CERT_PATH="$RUNNER_TEMP/certificate.p12"
KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
echo "$CERT_BASE64" | base64 -d > "$CERT_PATH"
security create-keychain -p "ci" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "ci" "$KEYCHAIN_PATH"
security import "$CERT_PATH" -P "$CERT_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -k "ci" "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH" login.keychain-db
- name: Install Provisioning Profiles
env:
PROFILE_BASE64: ${{ secrets.PROVISIONING_PROFILE_BASE64 }}
WIDGET_PROFILE_BASE64: ${{ secrets.WIDGET_PROVISIONING_PROFILE_BASE64 }}
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo "$PROFILE_BASE64" | base64 -d > ~/Library/MobileDevice/Provisioning\ Profiles/pilgrim.mobileprovision
echo "$WIDGET_PROFILE_BASE64" | base64 -d > ~/Library/MobileDevice/Provisioning\ Profiles/pilgrim-widget.mobileprovision
- name: Set Marketing Version
if: inputs.version != ''
env:
NEW_VERSION: ${{ inputs.version }}
run: |
sed -i '' "s/MARKETING_VERSION = [^;]*/MARKETING_VERSION = $NEW_VERSION/" Pilgrim.xcodeproj/project.pbxproj
- name: Bump Build Number
run: scripts/release.sh bump
- name: Commit Build Bump
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add Pilgrim.xcodeproj/project.pbxproj
git commit -m "chore: bump build number [skip ci]"
git push
- name: Snapshot Development Certs
env:
APP_STORE_API_KEY: ${{ secrets.APP_STORE_API_KEY }}
APP_STORE_API_ISSUER: ${{ secrets.APP_STORE_API_ISSUER }}
run: |
set -e
# Set up a venv with PyJWT + cryptography for the cert
# cleanup script. Using a venv (rather than pip --user)
# sidesteps macOS PEP 668 "externally managed environment"
# restrictions on the system Python. PyJWT generates raw
# r||s ECDSA signatures which Apple's API requires; the
# previous bash+openssl version produced DER signatures and
# silently failed with 401 NOT_AUTHORIZED on every build.
VENV="$RUNNER_TEMP/cert-cleanup-venv"
python3 -m venv "$VENV"
"$VENV/bin/pip" install --quiet --upgrade pip
"$VENV/bin/pip" install --quiet pyjwt cryptography
export APP_STORE_API_KEY_PATH="$HOME/.private_keys/AuthKey_${APP_STORE_API_KEY}.p8"
"$VENV/bin/python" scripts/asc-cert-cleanup.py snapshot "$RUNNER_TEMP/pre_build_certs.txt"
- name: Archive
run: scripts/release.sh archive
- name: Export
run: scripts/release.sh export
- name: Upload to App Store Connect
run: scripts/release.sh upload
- name: Revoke Auto-Created Development Certs
if: always()
env:
APP_STORE_API_KEY: ${{ secrets.APP_STORE_API_KEY }}
APP_STORE_API_ISSUER: ${{ secrets.APP_STORE_API_ISSUER }}
run: |
set -e
# Reuse the venv created in the Snapshot step. If that step
# failed before creating the venv, create one now — always-run
# semantics mean this step must tolerate any prior state.
VENV="$RUNNER_TEMP/cert-cleanup-venv"
if [ ! -x "$VENV/bin/python" ]; then
python3 -m venv "$VENV"
"$VENV/bin/pip" install --quiet --upgrade pip
"$VENV/bin/pip" install --quiet pyjwt cryptography
fi
export APP_STORE_API_KEY_PATH="$HOME/.private_keys/AuthKey_${APP_STORE_API_KEY}.p8"
"$VENV/bin/python" scripts/asc-cert-cleanup.py revoke "$RUNNER_TEMP/pre_build_certs.txt"
- name: Cleanup
if: always()
run: security delete-keychain "$RUNNER_TEMP/app-signing.keychain-db" 2>/dev/null || true