Skip to content

iOS Release

iOS Release #1

Workflow file for this run

# Publish Refetch to TestFlight / the App Store.
#
# Builds a signed IPA and uploads it through the Fastlane lanes in
# `ios/fastlane/`. Manual only — there is no push trigger.
#
# Repository secrets (Settings → Secrets and variables → Actions):
#
# APP_IDENTIFIER iOS bundle id (io.appwrite.refetch)
# APPLE_ID Apple Developer account email
# TEAM_ID Apple Developer Team ID (10 chars)
# ITC_TEAM_ID App Store Connect team id (numeric)
# APP_STORE_CONNECT_KEY_ID App Store Connect API key id
# APP_STORE_CONNECT_ISSUER_ID App Store Connect issuer id
# APP_STORE_CONNECT_KEY_CONTENT Base64-encoded .p8 private key
# MATCH_GIT_URL SSH URL of the private certificates repo
# MATCH_PASSWORD Passphrase the certificates repo is encrypted with
# MATCH_DEPLOY_KEY Private half of a read-only deploy key on that
# repo, used to clone it
#
# APPLE_ID and ITC_TEAM_ID only matter if fastlane falls back to Apple ID
# login. These lanes authenticate with the App Store Connect API key, so both
# are optional.
name: iOS Release
on:
workflow_dispatch:
inputs:
release_type:
description: "Where to send the build"
required: true
type: choice
default: beta
options:
- beta # TestFlight
- release # App Store review
- build # signed IPA only, no upload
build_number:
description: "Override the build number (TestFlight rejects a re-upload at the same one). Blank uses pubspec.yaml."
required: false
type: string
jobs:
publish:
name: Build and upload to App Store Connect (${{ inputs.release_type }})
runs-on: macos-latest
timeout-minutes: 90
env:
# Read by ios/fastlane/{Appfile,Matchfile,Fastfile}.
APP_IDENTIFIER: ${{ secrets.APP_IDENTIFIER }}
APPLE_ID: ${{ secrets.APPLE_ID }}
TEAM_ID: ${{ secrets.TEAM_ID }}
ITC_TEAM_ID: ${{ secrets.ITC_TEAM_ID }}
APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }}
MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
# Keep fastlane's output readable in the Actions log.
FASTLANE_SKIP_UPDATE_CHECK: "1"
FASTLANE_HIDE_CHANGELOG: "1"
steps:
- name: Check out repository
uses: actions/checkout@v4
# match clones the certificates repo over SSH using a read-only deploy
# key scoped to that repo alone. IdentitiesOnly stops ssh offering any
# other key the runner might pick up.
- name: Authorise the certificates repo
env:
MATCH_DEPLOY_KEY: ${{ secrets.MATCH_DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$MATCH_DEPLOY_KEY" > ~/.ssh/match_ed25519
chmod 600 ~/.ssh/match_ed25519
ssh-keyscan -t ed25519 github.com >> ~/.ssh/known_hosts 2>/dev/null
cat >> ~/.ssh/config <<'SSHCONFIG'
Host github.com
IdentityFile ~/.ssh/match_ed25519
IdentitiesOnly yes
SSHCONFIG
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
# Pinned to the version we develop against locally — bump in lockstep.
flutter-version: "3.44.6"
channel: stable
cache: true
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: true
working-directory: ios
- name: Install Flutter dependencies
run: flutter pub get
- name: Run tests
run: flutter test
# Generates Runner.xcworkspace and installs the pods that fastlane's
# build_app then archives with the match-provisioned signing identity.
- name: Build Flutter iOS
run: |
if [ -n "${{ inputs.build_number }}" ]; then
flutter build ios --release --no-codesign --build-number="${{ inputs.build_number }}"
else
flutter build ios --release --no-codesign
fi
- name: Run Fastlane ${{ inputs.release_type }}
working-directory: ios
run: bundle exec fastlane ${{ inputs.release_type }}
- name: Upload IPA artifact
if: success()
uses: actions/upload-artifact@v4
with:
name: refetch-ios-${{ inputs.release_type }}
path: build/ios/*.ipa
if-no-files-found: warn