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

# Circleci

# CircleCI Integration

> Use the official CircleCI orb to integrate App Store Connect CLI into your pipelines

## Official CircleCI Orb

The `asc` orb provides reusable commands and jobs for CircleCI pipelines:

* **Install command** - Set up `asc` in your jobs
* **Pre-built jobs** - Ready-to-use workflows for common tasks
* **Caching support** - Automatic binary caching for faster builds

**Repository**: [github.com/rudrankriyam/asc-orb](https://github.com/rudrankriyam/asc-orb)

## Quick Start

### Basic Configuration

```yaml .circleci/config.yml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

workflows:
  deploy:
    jobs:
      - asc/testflight:
          context: app-store-connect
          app-id: "123456789"
          ipa-path: "build/MyApp.ipa"
```

## Orb Commands

### Install Command

Installs the `asc` CLI:

```yaml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

jobs:
  custom-deploy:
    macos:
      xcode: 15.2.0
    steps:
      - checkout
      
      - asc/install:
          version: latest
      
      - run:
          name: Upload to TestFlight
          command: |
            asc builds upload \
              --app "$APP_ID" \
              --ipa build/MyApp.ipa

workflows:
  deploy:
    jobs:
      - custom-deploy
```

**Parameters:**

| Parameter | Description        | Default  |
| --------- | ------------------ | -------- |
| `version` | Version to install | `latest` |

### Run Command

Installs and executes an `asc` command:

```yaml theme={null} theme={null}
jobs:
  list-apps:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/run:
          command: apps list
```

**Parameters:**

| Parameter | Description        | Required |
| --------- | ------------------ | -------- |
| `command` | Command to execute | Yes      |
| `version` | Version to install | No       |

## Pre-Built Jobs

### TestFlight Upload Job

```yaml theme={null} theme={null}
workflows:
  deploy:
    jobs:
      - build-ipa:
          # Your build job
      
      - asc/testflight:
          requires:
            - build-ipa
          context: app-store-connect
          app-id: "123456789"
          ipa-path: "build/MyApp.ipa"
```

**Parameters:**

| Parameter  | Description              | Required |
| ---------- | ------------------------ | -------- |
| `app-id`   | App Store Connect app ID | Yes      |
| `ipa-path` | Path to IPA file         | Yes      |
| `version`  | `asc` version to use     | No       |

### App Store Submit Job

```yaml theme={null} theme={null}
workflows:
  release:
    jobs:
      - asc/submit:
          context: app-store-connect
          app-id: "123456789"
          version: "1.0.0"
          filters:
            tags:
              only: /^v.*/
```

**Parameters:**

| Parameter     | Description              | Required |
| ------------- | ------------------------ | -------- |
| `app-id`      | App Store Connect app ID | Yes      |
| `app-version` | Version to submit        | Yes      |
| `asc-version` | `asc` CLI version to use | No       |

## Complete Workflows

### Full TestFlight Pipeline

```yaml .circleci/config.yml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

executors:
  macos-executor:
    macos:
      xcode: 15.2.0
    resource_class: macos.m1.medium.gen1

jobs:
  build:
    executor: macos-executor
    steps:
      - checkout
      
      - restore_cache:
          keys:
            - v1-deps-{{ checksum "Podfile.lock" }}
      
      - run:
          name: Install Dependencies
          command: pod install
      
      - save_cache:
          key: v1-deps-{{ checksum "Podfile.lock" }}
          paths:
            - Pods
      
      - run:
          name: Build Archive
          command: |
            xcodebuild -workspace MyApp.xcworkspace \
              -scheme MyApp \
              -configuration Release \
              -archivePath build/MyApp.xcarchive \
              archive
      
      - run:
          name: Export IPA
          command: |
            xcodebuild -exportArchive \
              -archivePath build/MyApp.xcarchive \
              -exportPath build \
              -exportOptionsPlist ExportOptions.plist
      
      - persist_to_workspace:
          root: build
          paths:
            - MyApp.ipa
  
  deploy:
    executor: macos-executor
    steps:
      - attach_workspace:
          at: build
      
      - asc/install
      
      - run:
          name: Upload to TestFlight
          command: |
            asc builds upload \
              --app "$ASC_APP_ID" \
              --ipa build/MyApp.ipa
      
      - run:
          name: Add to Beta Group
          command: |
            # Wait for processing
            sleep 120
            
            # Get latest build ID
            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"

workflows:
  build-and-deploy:
    jobs:
      - build:
          filters:
            branches:
              only: main
      
      - deploy:
          requires:
            - build
          context: app-store-connect
```

### App Store Release Pipeline

```yaml .circleci/config.yml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

jobs:
  validate:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/install
      
      - run:
          name: Validate Version
          command: |
            asc validate \
              --app "$ASC_APP_ID" \
              --version "$CIRCLE_TAG"
  
  release:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/install
      
      - run:
          name: Run App Store Publish Command
          command: |
            asc publish appstore \
              --app "$ASC_APP_ID" \
              --ipa "./build/MyApp.ipa" \
              --version "$CIRCLE_TAG" \
              --submit \
              --confirm
  
  monitor:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/install
      
      - run:
          name: Check Review Status
          command: |
            VERSION_ID=$(asc versions list \
              --app "$ASC_APP_ID" \
              --version "$CIRCLE_TAG" \
              --output json | jq -r '.data[0].id')

            asc submit status \
              --version-id "$VERSION_ID" \
              --output json > review-status.json
      
      - store_artifacts:
          path: review-status.json

workflows:
  release:
    jobs:
      - validate:
          context: app-store-connect
          filters:
            tags:
              only: /^v.*/
            branches:
              ignore: /.*/
      
      - approve-submission:
          type: approval
          requires:
            - validate
          filters:
            tags:
              only: /^v.*/
      
      - release:
          context: app-store-connect
          requires:
            - approve-submission
          filters:
            tags:
              only: /^v.*/
      
      - monitor:
          context: app-store-connect
          requires:
            - release
          filters:
            tags:
              only: /^v.*/
```

### Metadata Sync Workflow

```yaml .circleci/config.yml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

jobs:
  sync-description:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      
      - asc/install
      
      - run:
          name: Update Description
          command: |
            asc apps info edit \
              --app "$ASC_APP_ID" \
              --locale en-US \
              --description "$(cat metadata/en-US/description.txt)"
  
  sync-screenshots:
    macos:
      xcode: 15.2.0
    steps:
      - checkout
      
      - asc/install
      
      - run:
          name: Upload Screenshots
          command: |
            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

workflows:
  metadata-update:
    jobs:
      - sync-description:
          context: app-store-connect
          filters:
            branches:
              only: main
      
      - sync-screenshots:
          context: app-store-connect
          filters:
            branches:
              only: main
```

### Scheduled Monitoring

```yaml .circleci/config.yml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

jobs:
  monitor-crashes:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/install
      
      - run:
          name: Fetch Crashes
          command: |
            asc testflight crashes list \
              --app "$ASC_APP_ID" \
              --sort -createdDate \
              --limit 20 \
              --output json > crashes.json
      
      - run:
          name: Analyze Crash Count
          command: |
            CRASH_COUNT=$(jq 'length' crashes.json)
            echo "Found $CRASH_COUNT recent crashes"
            
            if [ "$CRASH_COUNT" -gt 10 ]; then
              echo "WARNING: High crash count detected!"
            fi
      
      - store_artifacts:
          path: crashes.json
  
  monitor-feedback:
    docker:
      - image: cimg/base:stable
    steps:
      - asc/install
      
      - run:
          name: Fetch Feedback
          command: |
            asc testflight feedback list \
              --app "$ASC_APP_ID" \
              --paginate \
              --output json > feedback.json
      
      - store_artifacts:
          path: feedback.json

workflows:
  daily-monitoring:
    triggers:
      - schedule:
          cron: "0 9 * * *"  # Daily at 9 AM UTC
          filters:
            branches:
              only: main
    jobs:
      - monitor-crashes:
          context: app-store-connect
      
      - monitor-feedback:
          context: app-store-connect
```

## Authentication Setup

### CircleCI Contexts

1. Navigate to **Organization Settings > Contexts**
2. Create a new context: `app-store-connect`
3. Add environment variables:

| Variable              | Description                 |
| --------------------- | --------------------------- |
| `ASC_KEY_ID`          | App Store Connect Key ID    |
| `ASC_ISSUER_ID`       | App Store Connect Issuer ID |
| `ASC_PRIVATE_KEY_B64` | Base64-encoded private key  |
| `ASC_APP_ID`          | Your app ID (optional)      |

### Base64 Encoding

```bash theme={null} theme={null}
# Encode private key
base64 -i AuthKey_ABC123.p8 | tr -d '\n'

# Verify
echo "$ENCODED" | base64 -d | head -1
# Should show: -----BEGIN PRIVATE KEY-----
```

### Using Contexts in Workflows

```yaml theme={null} theme={null}
workflows:
  deploy:
    jobs:
      - deploy-job:
          context: app-store-connect  # References the context
```

### Project-Level Variables

Alternatively, set variables at the project level:

1. Go to **Project Settings > Environment Variables**
2. Add the same variables as above

## Advanced Patterns

### Matrix Builds

```yaml theme={null} theme={null}
version: 2.1

orbs:
  asc: rudrankriyam/asc@1.0

parameters:
  apps:
    type: string
    default: |
      [
        {"name": "MyApp", "id": "123456789", "scheme": "MyApp"},
        {"name": "MyAppPro", "id": "987654321", "scheme": "MyAppPro"}
      ]

jobs:
  deploy-app:
    parameters:
      app-name:
        type: string
      app-id:
        type: string
      scheme:
        type: string
    macos:
      xcode: 15.2.0
    steps:
      - checkout
      
      - run:
          name: Build << parameters.app-name >>
          command: |
            xcodebuild -scheme << parameters.scheme >> \
              -archivePath build/<< parameters.app-name >>.xcarchive \
              archive
            
            xcodebuild -exportArchive \
              -archivePath build/<< parameters.app-name >>.xcarchive \
              -exportPath build \
              -exportOptionsPlist ExportOptions.plist
      
      - asc/install
      
      - run:
          name: Upload << parameters.app-name >>
          command: |
            asc builds upload \
              --app "<< parameters.app-id >>" \
              --ipa build/<< parameters.app-name >>.ipa

workflows:
  deploy-all:
    jobs:
      - deploy-app:
          name: deploy-myapp
          app-name: MyApp
          app-id: "123456789"
          scheme: MyApp
          context: app-store-connect
      
      - deploy-app:
          name: deploy-myapp-pro
          app-name: MyAppPro
          app-id: "987654321"
          scheme: MyAppPro
          context: app-store-connect
```

### Conditional Execution

```yaml theme={null} theme={null}
jobs:
  conditional-deploy:
    docker:
      - image: cimg/base:stable
    steps:
      - checkout
      
      - asc/install
      
      - when:
          condition:
            equal: [ main, << pipeline.git.branch >> ]
          steps:
            - run:
                name: Deploy to Production
                command: |
                  asc publish appstore --app "$PROD_APP_ID" --ipa "build/MyApp.ipa" --version "$VERSION" --submit --confirm
      
      - when:
          condition:
            equal: [ develop, << pipeline.git.branch >> ]
          steps:
            - run:
                name: Deploy to Staging
                command: |
                  asc builds upload --app "$STAGING_APP_ID" --ipa "build/MyApp.ipa"
```

## Executors

### macOS Executor

For build operations:

```yaml theme={null} theme={null}
executors:
  macos-executor:
    macos:
      xcode: 15.2.0
    resource_class: macos.m1.medium.gen1
    environment:
      ASC_DEFAULT_OUTPUT: json
      ASC_TIMEOUT: 2m
```

### Docker Executor

For API-only operations:

```yaml theme={null} theme={null}
executors:
  docker-executor:
    docker:
      - image: cimg/base:stable
    environment:
      ASC_DEFAULT_OUTPUT: json
```

## Caching

Cache dependencies and build artifacts:

```yaml theme={null} theme={null}
jobs:
  build:
    steps:
      - checkout
      
      - restore_cache:
          keys:
            - v1-asc-{{ arch }}-{{ checksum "go.sum" }}
            - v1-asc-{{ arch }}
      
      - asc/install
      
      - save_cache:
          key: v1-asc-{{ arch }}-{{ checksum "go.sum" }}
          paths:
            - ~/.cache/asc
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Orb not found">
    * Verify orb is published: `circleci orb list rudrankriyam`
    * Check CircleCI version is 2.1+
    * Ensure organization allows third-party orbs
  </Accordion>

  <Accordion title="Authentication failed">
    * Verify context variables are set correctly
    * Check job references the correct context
    * Ensure private key is base64-encoded without newlines
    * Test credentials locally
  </Accordion>

  <Accordion title="Resource class unavailable">
    * Check available macOS resource classes for your plan
    * Use `macos.m1.medium.gen1` for M1 builds
    * Consider using `macos.x86.medium.gen2` for Intel
  </Accordion>

  <Accordion title="Build timeout">
    * Increase job timeout:
      ```yaml theme={null} theme={null}
      jobs:
        deploy:
          no_output_timeout: 30m
      ```
    * Set environment variables:
      ```yaml theme={null} theme={null}
      environment:
        ASC_UPLOAD_TIMEOUT: 15m
      ```
  </Accordion>
</AccordionGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Use contexts for secrets" icon="lock">
    Centralize credentials in contexts instead of project variables.
  </Card>

  <Card title="Cache dependencies" icon="database">
    Speed up builds with caching:

    ```yaml theme={null} theme={null}
    - restore_cache
    - save_cache
    ```
  </Card>

  <Card title="Pin orb versions" icon="tag">
    Use specific versions for stability:

    ```yaml theme={null} theme={null}
    orbs:
      asc: rudrankriyam/asc@1.0.0
    ```
  </Card>

  <Card title="Use approval jobs" icon="check-circle">
    Require manual approval for production:

    ```yaml theme={null} theme={null}
    - approve:
        type: approval
    ```
  </Card>
</CardGroup>

## Related Resources

* [CI/CD Overview](/cicd/overview)
* [Authentication Guide](/authentication)
* [Commands Reference](/commands/overview)
* [asc-orb Repository](https://github.com/rudrankriyam/asc-orb)
* [CircleCI Orbs Documentation](https://circleci.com/docs/orb-intro/)
