This section walks you through how to automate your iOS app deployment to TestFlight using GitHub Actions, in conjunction with the Fastlane setup described in the Fastlane Setup Guide.
Before setting up the GitHub Action, ensure the following are in place:
To allow GitHub Actions to pull certificates from your private Match repository:
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
ssh-keygen -t rsa -b 4096 -C "github-actions" -f ./github_actions_key
This creates:
3. Go to your certificates GitHub repo (the one used by match)
Navigate to: Settings > Deploy keys > Add deploy key
Go to your main app repository on GitHub (the one running the action):
1. Navigate to your repository → Settings → Secrets and variables → Actions → Secrets
2. Add the following secrets:
Important: Do not commit your .p8 file or SSH keys to version control. Store them securely
To securely use your App Store Connect API key in GitHub Actions, you need to encode the AuthKey.p8 file in Base64 and store it as a secret.
Steps:
1. Encode AuthKey.p8 to base64
Run this command in your terminal where the .p8 file is located:
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
base64 -i AuthKey.p8 -o AuthKey_base64.txt
Navigate to your repository → Settings → Secrets and variables → Actions → Secrets
Add a new secret:
Name: ASC_KEY_BASE64
Value: Paste the entire base64 string of your AuthKey.p8
Create a new file in your project at the following location:
.github/workflows/ios-testflight.yml
Paste the following:
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
name: iOS TestFlight Deployment
on:
workflow_dispatch:
jobs:
deploy-to-testflight:
name: Build and deploy to TestFlight
runs-on: macos-15
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install SSH Key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
bundler-cache: true
bundler: "2.4.22"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: "3.29.2"
channel: "stable"
- name: Install Flutter dependencies
run: flutter pub get
- name: Install Ruby dependencies
working-directory: ./ios
run: bundle install
- name: Decode App Store Connect API Key
run: |
echo "${{ secrets.ASC_KEY_BASE64 }}" | base64 --decode > ./ios/AuthKey.p8
- name: Build and upload to TestFlight
working-directory: ./ios
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_KEY_PATH: ./AuthKey.p8
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
run: bundle exec fastlane upload_to_testflight_function
When the iOS TestFlight Deployment workflow is triggered manually via GitHub Actions, it follows a defined series of steps to build and distribute your iOS app using TestFlight:
1. Сheckout the Repository
The workflow checks out the code from your GitHub repository so the runner has access to all project files.
2. Install the SSH Key
Installs the SSH key stored in GitHub Secrets to allow secure access to your private repository for provisioning profiles and certificates.
3. Set Up Ruby, Bundler, and Flutter
4. Install Project Dependencies
5. Decode App Store Connect API Key
Takes a base64-encoded App Store Connect API key from GitHub Secrets, decodes it, and writes it as AuthKey.p8 to be used for authentication with Apple Developer APIs.
6. Build and Upload to TestFlight
Runs the Fastlane lane upload_to_testflight_function, which performs the following tasks:
Ensure that your workflow YAML file (ios-testflight.yml) is committed and pushed to the default branch of your repository (typically main or master).
Once it is available in the default branch, you can manually trigger the GitHub Action from the GitHub interface:
1. Access GitHub Actions
2. Select the Workflow
3. Trigger the Workflow
4. Monitor the Workflow Execution