Documentation Index
Fetch the complete documentation index at: https://docs.asccli.sh/llms.txt
Use this file to discover all available pages before exploring further.
GitHub Actions Integration
Use the official setup-asc action to automate App Store Connect workflows in GitHub Actions
Official Action
The rudrankriyam/setup-asc action provides:
- Automatic version detection and caching
- Support for all platforms (macOS, Linux, Windows)
- Matrix build support for multiple app configurations
- Integration with GitHub Secrets for credential management
Repository: github.com/rudrankriyam/setup-asc
Quick Start
Basic Workflow
.github/workflows/testflight.yml
name: Deploy to TestFlight
on:
push:
tags:
- 'v*'
jobs:
deploy:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
with:
version: latest
- name: Verify installation
run: asc --version
- name: Upload to TestFlight
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
run: |
asc builds upload \
--app "${{ secrets.APP_ID }}" \
--ipa "MyApp.ipa"
Setup Action Configuration
| Input | Description | Required | Default |
|---|
version | Version to install (latest, 1.2.3, etc.) | No | latest |
token | GitHub token for API rate limiting | No | ${{ github.token }} |
Example: Pin to Specific Version
- uses: rudrankriyam/setup-asc@v1
with:
version: '1.0.0'
Complete Workflows
TestFlight Distribution
.github/workflows/testflight-release.yml
name: TestFlight Release
on:
push:
branches: [main]
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: macos-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
with:
version: latest
- name: Build IPA
run: |
xcodebuild -workspace MyApp.xcworkspace \
-scheme MyApp \
-configuration Release \
-archivePath build/MyApp.xcarchive \
archive
xcodebuild -exportArchive \
-archivePath build/MyApp.xcarchive \
-exportPath build \
-exportOptionsPlist ExportOptions.plist
- name: Upload to TestFlight
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
asc builds upload \
--app "$ASC_APP_ID" \
--ipa build/MyApp.ipa
- name: Wait for processing
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
# Wait for build to process (simplified example)
sleep 120
# Get latest build
BUILD_ID=$(asc builds list \
--app "$ASC_APP_ID" \
--output json \
--limit 1 | jq -r '.[0].id')
# Add to external testers
asc builds add-groups \
--build-id "$BUILD_ID" \
--group "External Testers"
App Store Submission
.github/workflows/app-store-submit.yml
name: Submit to App Store
on:
workflow_dispatch:
inputs:
version:
description: 'Version to submit'
required: true
type: string
jobs:
submit:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
- name: Validate version
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
asc validate \
--app "$ASC_APP_ID" \
--version "${{ inputs.version }}"
- name: Publish to the App Store
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
asc publish appstore \
--app "$ASC_APP_ID" \
--ipa "./build/MyApp.ipa" \
--version "${{ inputs.version }}" \
--submit \
--confirm
- name: Notify on success
if: success()
run: |
echo "::notice::Version ${{ inputs.version }} submitted successfully"
.github/workflows/metadata-sync.yml
name: Sync App Metadata
on:
push:
paths:
- 'metadata/**'
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
- name: Update app description
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
# Update en-US description
asc apps info edit \
--app "$ASC_APP_ID" \
--locale en-US \
--description "$(cat metadata/en-US/description.txt)"
- name: Upload screenshots
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
# Upload iPhone 6.7" screenshots
for screenshot in metadata/en-US/screenshots/iphone67/*.png; do
asc screenshots upload \
--version-localization "$VERSION_LOCALIZATION_ID" \
--device-type "IPHONE_65" \
--path "$screenshot"
done
Crash Monitoring
.github/workflows/crash-monitor.yml
name: Monitor Crashes
on:
schedule:
# Run daily at 9 AM UTC
- cron: '0 9 * * *'
workflow_dispatch:
jobs:
monitor:
runs-on: ubuntu-latest
steps:
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
- name: Fetch recent crashes
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
ASC_APP_ID: ${{ secrets.APP_ID }}
run: |
asc testflight crashes list \
--app "$ASC_APP_ID" \
--sort -createdDate \
--limit 10 \
--output json > crashes.json
- name: Upload crash report
uses: actions/upload-artifact@v4
with:
name: crash-report-${{ github.run_number }}
path: crashes.json
- name: Check for critical crashes
run: |
CRASH_COUNT=$(jq 'length' crashes.json)
echo "Found $CRASH_COUNT recent crashes"
if [ "$CRASH_COUNT" -gt 5 ]; then
echo "::warning::High crash count detected: $CRASH_COUNT"
fi
Matrix Builds
Multiple Apps
.github/workflows/multi-app-deploy.yml
name: Deploy Multiple Apps
on:
workflow_dispatch:
jobs:
deploy:
runs-on: macos-latest
strategy:
matrix:
app:
- name: MyApp
id: 123456789
scheme: MyApp
- name: MyAppPro
id: 987654321
scheme: MyAppPro
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup App Store Connect CLI
uses: rudrankriyam/setup-asc@v1
- name: Build ${{ matrix.app.name }}
run: |
xcodebuild -scheme ${{ matrix.app.scheme }} \
-archivePath build/${{ matrix.app.name }}.xcarchive \
archive
xcodebuild -exportArchive \
-archivePath build/${{ matrix.app.name }}.xcarchive \
-exportPath build \
-exportOptionsPlist ExportOptions.plist
- name: Upload ${{ matrix.app.name }}
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
run: |
asc builds upload \
--app "${{ matrix.app.id }}" \
--ipa build/${{ matrix.app.name }}.ipa
Authentication Setup
GitHub Secrets Configuration
- Navigate to your repository Settings > Secrets and variables > Actions
- Click New repository secret
- Add the following secrets:
| Secret Name | Value |
|---|
ASC_KEY_ID | Your App Store Connect Key ID |
ASC_ISSUER_ID | Your App Store Connect Issuer ID |
ASC_PRIVATE_KEY_B64 | Base64-encoded .p8 private key |
APP_ID | Your app’s ID (optional, for convenience) |
Base64 Encoding Private Key
# macOS/Linux
base64 -i AuthKey_ABC123.p8 | pbcopy
# Alternative (output to file)
base64 -i AuthKey_ABC123.p8 > key.txt
Using Private Key File (Alternative)
If you prefer not to use base64 encoding:
steps:
- name: Write private key
run: |
echo "${{ secrets.ASC_PRIVATE_KEY }}" > /tmp/AuthKey.p8
chmod 600 /tmp/AuthKey.p8
- name: Run asc command
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_PATH: /tmp/AuthKey.p8
run: asc apps list
- name: Cleanup
if: always()
run: rm -f /tmp/AuthKey.p8
Environment Variables
Set default environment variables for all jobs:
env:
ASC_DEFAULT_OUTPUT: json
ASC_TIMEOUT: 2m
ASC_UPLOAD_TIMEOUT: 10m
jobs:
deploy:
runs-on: macos-latest
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
# ...
Caching
The setup-asc action automatically caches the asc binary. You can also cache build artifacts:
steps:
- name: Cache build artifacts
uses: actions/cache@v4
with:
path: |
build/
DerivedData/
key: ${{ runner.os }}-build-${{ hashFiles('**/*.swift') }}
restore-keys: |
${{ runner.os }}-build-
Conditional Workflows
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
Manual approval for production
jobs:
deploy-staging:
runs-on: macos-latest
# ... deploy to TestFlight
deploy-production:
runs-on: macos-latest
needs: deploy-staging
environment: production # Requires manual approval
# ... submit to App Store
Troubleshooting
Enable Debug Logging
- name: Upload with debug logging
env:
ASC_DEBUG: api
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
run: asc builds upload --app "$APP_ID" --ipa MyApp.ipa
Verify Credentials
- name: Test authentication
env:
ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
ASC_PRIVATE_KEY_B64: ${{ secrets.ASC_PRIVATE_KEY_B64 }}
run: |
echo "Testing App Store Connect authentication..."
asc apps list --limit 1
Common Issues
- Verify all three secrets are set correctly
- Check that private key is properly base64-encoded
- Ensure API key has not been revoked in App Store Connect
- Verify Key ID and Issuer ID match the API key
The setup-asc action failed to find the specified version:
- Check releases for available versions
- Use
latest for the most recent release
- Ensure version format is correct (e.g.,
1.0.0, not v1.0.0)
- Increase
ASC_UPLOAD_TIMEOUT environment variable
- Check network connectivity from GitHub runner
- Verify IPA file is not corrupted
- Add delays between API calls
- Use pagination wisely with
--limit
- Consider spreading operations across multiple jobs
Best Practices
Use explicit versions
Pin action versions for reproducibility:uses: rudrankriyam/setup-asc@v1
Set timeouts
Prevent hanging workflows:jobs:
deploy:
timeout-minutes: 30
Separate build and deploy
Use separate jobs for build and deployment:jobs:
build:
# Build IPA
deploy:
needs: build
# Upload to TestFlight
Use environments
Leverage GitHub Environments for approvals:
Examples Repository
For more complete examples, see:
github.com/rudrankriyam/setup-asc