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

# 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](https://github.com/rudrankriyam/setup-asc)

## Quick Start

### Basic Workflow

```yaml .github/workflows/testflight.yml theme={null} theme={null}
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

### Inputs

| 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

```yaml theme={null} theme={null}
- uses: rudrankriyam/setup-asc@v1
  with:
    version: '1.0.0'
```

## Complete Workflows

### TestFlight Distribution

```yaml .github/workflows/testflight-release.yml theme={null} theme={null}
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

```yaml .github/workflows/app-store-submit.yml theme={null} theme={null}
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"
```

### Metadata Sync

```yaml .github/workflows/metadata-sync.yml theme={null} theme={null}
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

```yaml .github/workflows/crash-monitor.yml theme={null} theme={null}
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

```yaml .github/workflows/multi-app-deploy.yml theme={null} theme={null}
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

1. Navigate to your repository **Settings > Secrets and variables > Actions**
2. Click **New repository secret**
3. 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

```bash theme={null} theme={null}
# 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:

```yaml theme={null} theme={null}
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:

```yaml theme={null} theme={null}
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:

```yaml theme={null} theme={null}
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

### Deploy only on tags

```yaml theme={null} theme={null}
on:
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'
```

### Manual approval for production

```yaml theme={null} theme={null}
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

```yaml theme={null} theme={null}
- 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

```yaml theme={null} theme={null}
- 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

<AccordionGroup>
  <Accordion title="Authentication failed">
    * 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
  </Accordion>

  <Accordion title="Version not found">
    The setup-asc action failed to find the specified version:

    * Check [releases](https://github.com/rorkai/App-Store-Connect-CLI/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`)
  </Accordion>

  <Accordion title="Upload timeout">
    * Increase `ASC_UPLOAD_TIMEOUT` environment variable
    * Check network connectivity from GitHub runner
    * Verify IPA file is not corrupted
  </Accordion>

  <Accordion title="Rate limiting">
    * Add delays between API calls
    * Use pagination wisely with `--limit`
    * Consider spreading operations across multiple jobs
  </Accordion>
</AccordionGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Use explicit versions" icon="lock">
    Pin action versions for reproducibility:

    ```yaml theme={null} theme={null}
    uses: rudrankriyam/setup-asc@v1
    ```
  </Card>

  <Card title="Set timeouts" icon="clock">
    Prevent hanging workflows:

    ```yaml theme={null} theme={null}
    jobs:
      deploy:
        timeout-minutes: 30
    ```
  </Card>

  <Card title="Separate build and deploy" icon="code-branch">
    Use separate jobs for build and deployment:

    ```yaml theme={null} theme={null}
    jobs:
      build:
        # Build IPA
      deploy:
        needs: build
        # Upload to TestFlight
    ```
  </Card>

  <Card title="Use environments" icon="shield-check">
    Leverage GitHub Environments for approvals:

    ```yaml theme={null} theme={null}
    environment: production
    ```
  </Card>
</CardGroup>

## Examples Repository

For more complete examples, see:
[github.com/rudrankriyam/setup-asc](https://github.com/rudrankriyam/setup-asc)

## Related Resources

* [CI/CD Overview](/cicd/overview)
* [Authentication Guide](/authentication)
* [Commands Reference](/commands/overview)
