> ## Documentation Index
> Fetch the complete documentation index at: https://docs.autosana.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Github Action for App Uploads

> Automatically upload mobile builds or register web apps with Autosana

Integrate Autosana into your CI/CD pipeline with our GitHub Action to automatically upload and test your builds with every commit. Supports iOS, Android, and web platforms.

<Frame>
  <img src="https://mintcdn.com/autosana/uDsFIKjlKiNoma8I/images/github-action-example.png?fit=max&auto=format&n=uDsFIKjlKiNoma8I&q=85&s=18c183667c3c8c384af482404418faa1" alt="Autosana GitHub Action uploading a build" width="1852" height="90" data-path="images/github-action-example.png" />
</Frame>

<Tip>
  Add our [MCP Server](/mcp-setup) to help with setting up your CI/CD pipeline.
</Tip>

## Step 1: Choose Your Platform

Select your platform to see the relevant setup instructions:

<CardGroup cols={3}>
  <Card title="iOS / Android" icon="mobile" href="#mobile-setup">
    Mobile app builds (Expo, Fastlane, native)
  </Card>

  <Card title="Web" icon="globe" href="#web-setup">
    Web apps (Vercel, Netlify, custom deployments, etc.)
  </Card>
</CardGroup>

***

## Mobile Setup

### Choose Your Build Tool

<CardGroup cols={3}>
  <Card title="Expo EAS" icon="code" href="#expo-eas-ios">
    React Native with Expo's build service
  </Card>

  <Card title="Fastlane" icon="mobile" href="#fastlane-ios">
    Native iOS/Android builds with Fastlane
  </Card>

  <Card title="Other" icon="wrench" href="#native-ios">
    Gradle, Flutter, or custom builds
  </Card>
</CardGroup>

***

## Step 2: Set Secrets

Go to your repository **Settings → Secrets → Actions** and add these secrets. See the [GitHub Secrets docs](https://docs.github.com/en/actions/security-guides/encrypted-secrets) for help.

### Required for All

<ParamField path="AUTOSANA_KEY" type="string" required>
  Your Autosana API key for uploading builds. Get it from the welcome quickstart or [Settings → Integrations](https://autosana.ai/settings?tab=integrations).
</ParamField>

### Required for Expo EAS

<ParamField path="EXPO_TOKEN" type="string">
  Your Expo access token for EAS builds. Get it from [Expo account settings](https://expo.dev/accounts/\[account]/settings/access-tokens).
</ParamField>

***

## Step 3: Set up your Github Workflow with the Autosana Github Action

Create a `.github/workflows/autosana-ios.yml` and/or `.github/workflows/autosana-android.yml` file in your repository. Examples are provided below to get started.

<Note>
  For more specific build instructions by framework, check out our [App Build Guide](/app-build-guide) for detailed instructions on creating builds for iOS and Android.
</Note>

Add this step to your existing GitHub workflow after your build step:

```yaml theme={null}
- name: Upload to Autosana
  uses: autosana/autosana-ci@main
  with:
    api-key: ${{ secrets.AUTOSANA_KEY }}
    bundle-id: com.your.app  # Replace with your app's bundle ID
    platform: ios  # or 'android'
    build-path: ./path/to/your/build.app  # iOS: .app or .zip | Android: .apk
    # environment: staging  # Optional: separate apps by environment
    # variables: TEST_ACCOUNT=qa-smoke,CHECKOUT_VARIANT=control  # Optional: attach build variables
    # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
    # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
```

<Note>
  **Required Parameters:**

  * `api-key`: Your Autosana API key (from secrets)
  * `bundle-id`: Your app's bundle ID (e.g., `com.company.app`)
  * `platform`: Either `ios` or `android`
  * `build-path`: Path to your build artifact

  **Optional Parameters:**

  * `name`: Display name for your app (e.g., "My iOS App"). Updates existing app name if different.
  * `environment`: Name of the environment to associate this app with (e.g., `staging`, `production`). See [Using Environments](#using-environments-to-separate-builds) below.
  * `variables`: Key-value variables to attach to the uploaded build. Available in flow instructions via `${env:KEY}`. Use `KEY1=VALUE1,KEY2=VALUE2`. See [Build Variables](/variables#build-variables).
  * `suite-ids`: Comma-separated suite UUIDs to run after upload (e.g., `uuid1,uuid2`).
  * `flow-ids`: Comma-separated flow UUIDs to run after upload (e.g., `uuid1,uuid2`).
</Note>

### Github Action Workflow Examples

<Tabs>
  <Tab title="Expo EAS (iOS)">
    ### Configure eas.json

    Add this profile to your `eas.json` for iOS simulator builds:

    ```json eas.json theme={null}
    {
      "build": {
        "preview-simulator": {
          "distribution": "internal",
          "ios": {
            "simulator": true
          }
        }
      }
    }
    ```

    ### GitHub Workflow

    <Warning>
      **Important:** Replace `YOUR_BUNDLE_ID` with your app's bundle ID.
    </Warning>

    ```yaml .github/workflows/autosana-eas-ios.yml theme={null}
    name: EAS iOS Simulator Build + Autosana

    on:
      # Triggers on pushes to main branch (including merges)
      push:
        branches:
          - main
      # Allows for manual triggering of the workflow from the GitHub UI.
      workflow_dispatch:

    jobs:
      build-and-test:
        runs-on: ubuntu-latest

        steps:
          # Step 1: Check out the repository's code
          - name: Checkout repository
            uses: actions/checkout@v4

          # Step 2: Set up Node.js
          - name: Set up Node.js
            uses: actions/setup-node@v4
            with:
              node-version: '18'
              cache: 'npm'

          # Step 3: Set up Expo and EAS
          - name: Set up Expo and EAS
            uses: expo/expo-github-action@v8
            with:
              eas-version: latest
              token: ${{ secrets.EXPO_TOKEN }}

          # Step 4: Install project dependencies
          - name: Install dependencies
            run: npm install

          # Step 5: Run the EAS Build for an iOS Simulator
          - name: Run iOS Simulator Build
            run: eas build --platform ios --profile preview-simulator --non-interactive --wait --json > build-info.json

          # Step 6: Download the .app artifact from the completed EAS build
          - name: Download zipped .app from EAS
            run: |
              BUILD_URL=$(jq -r '.[0].artifacts.buildUrl' build-info.json)
              echo "Downloading zipped .app from $BUILD_URL"
              curl -L "$BUILD_URL" -o app.zip

          # Step 7: Run the Autosana CI action for testing
          - name: Run Autosana CI
            uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: YOUR_BUNDLE_ID # TODO: Make sure this matches your app's bundle ID
              platform: ios
              build-path: app.zip
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>

  <Tab title="Expo EAS (Android)">
    ### Configure eas.json

    Add this profile to your `eas.json` for Android emulator builds:

    ```json eas.json theme={null}
    {
      "build": {
        "preview": {
          "distribution": "internal",
          "android": {
            "buildType": "apk"
          }
        }
      }
    }
    ```

    ### GitHub Workflow

    <Warning>
      **Important:** Replace `YOUR_BUNDLE_ID` with your app's bundle ID.
    </Warning>

    ```yaml .github/workflows/autosana-eas-android.yml theme={null}
    name: EAS Android Build + Autosana

    on:
      push:
        branches:
          - main
      workflow_dispatch:

    jobs:
      build-and-test:
        runs-on: ubuntu-latest

        steps:
          - name: Checkout repository
            uses: actions/checkout@v4

          - name: Set up Node.js
            uses: actions/setup-node@v4
            with:
              node-version: '18'
              cache: 'npm'

          - name: Set up Expo and EAS
            uses: expo/expo-github-action@v8
            with:
              eas-version: latest
              token: ${{ secrets.EXPO_TOKEN }}

          - name: Install dependencies
            run: npm install

          - name: Run Android Build
            run: eas build --platform android --profile preview --non-interactive --wait --json > build-info.json

          - name: Download APK from EAS
            run: |
              BUILD_URL=$(jq -r '.[0].artifacts.buildUrl' build-info.json)
              echo "Downloading APK from $BUILD_URL"
              curl -L "$BUILD_URL" -o app.apk

          - name: Run Autosana CI
            uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: YOUR_BUNDLE_ID # TODO: Replace with your bundle ID
              platform: android
              build-path: app.apk
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>

  <Tab title="Fastlane (iOS)">
    <Warning>
      **Important:** Replace `com.example.app` with your app's bundle ID.
    </Warning>

    ```yaml .github/workflows/autosana-fastlane-ios.yml theme={null}
    name: Fastlane iOS + Autosana

    on:
      push:
        branches: [ main ]

    jobs:
      build-and-test:
        runs-on: macos-latest

        steps:
          - uses: actions/checkout@v4

          - name: Set up Ruby
            uses: ruby/setup-ruby@v1
            with:
              ruby-version: '3.0'
              bundler-cache: true

          - name: Build with Fastlane
            run: bundle exec fastlane ios build_for_testing

          - uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: com.example.app # TODO: Replace with your bundle ID
              platform: ios
              build-path: ./build/MyApp.app
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>

  <Tab title="Fastlane (Android)">
    <Warning>
      **Important:** Replace `com.example.app` with your app's bundle ID.
    </Warning>

    ```yaml .github/workflows/autosana-fastlane-android.yml theme={null}
    name: Fastlane Android + Autosana

    on:
      push:
        branches: [ main ]

    jobs:
      build-and-test:
        runs-on: ubuntu-latest

        steps:
          - uses: actions/checkout@v4

          - name: Set up JDK
            uses: actions/setup-java@v3
            with:
              java-version: '11'
              distribution: 'temurin'

          - name: Set up Ruby
            uses: ruby/setup-ruby@v1
            with:
              ruby-version: '3.0'
              bundler-cache: true

          - name: Build with Fastlane
            run: bundle exec fastlane android build

          - uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: com.example.app # TODO: Replace with your bundle ID
              platform: android
              build-path: ./app/build/outputs/apk/release/app-release.apk
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>

  <Tab title="Native iOS">
    <Warning>
      **Important:**

      * Replace `com.example.app` with your app's bundle ID
      * Replace the build command with your specific build process
      * Update the build path to match your build output
    </Warning>

    ```yaml .github/workflows/autosana-custom-ios.yml theme={null}
    name: Build and Upload to Autosana (iOS)

    on:
      push:
        branches: [ main ]

    jobs:
      build-and-upload:
        runs-on: macos-latest  # iOS builds require macOS
        steps:
          - uses: actions/checkout@v4

          # TODO: Build your iOS app
          # Examples:
          # - xcodebuild -workspace App.xcworkspace -scheme App -configuration Release
          # - flutter build ios --release --no-codesign
          # - react-native run-ios --configuration Release

          - uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: com.example.app # TODO: Replace with your app's bundle ID
              platform: ios
              build-path: build/ios/iphoneos/MyApp.app # TODO: Update path
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>

  <Tab title="Native Android">
    <Warning>
      **Important:**

      * Replace `com.example.app` with your app's bundle ID
      * Replace the build command with your specific build process
      * Update the build path to match your build output
    </Warning>

    ```yaml .github/workflows/autosana-custom-android.yml theme={null}
    name: Build and Upload to Autosana (Android)

    on:
      push:
        branches: [ main ]

    jobs:
      build-and-upload:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4

          # TODO: Build your Android app
          # Examples:
          # - ./gradlew assembleRelease
          # - flutter build apk --release
          # - react-native run-android --variant=release

          - uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              bundle-id: com.example.app # TODO: Replace with your app's bundle ID
              platform: android
              build-path: app/build/outputs/apk/release/app-release.apk # TODO: Update path
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>
</Tabs>

***

## Web Setup

For web applications, you can register a URL (such as a preview deployment) for testing. This is useful for testing Vercel, Netlify, or other preview deployments on every PR.

### Parameters

<Note>
  **Required Parameters for Web:**

  * `api-key`: Your Autosana API key (from secrets)
  * `platform`: Must be `web`
  * `app-id`: A unique identifier for your web app (lowercase, alphanumeric with hyphens, e.g., `my-web-app`)
  * `url`: The URL to test (e.g., your preview deployment URL)

  **Optional Parameters:**

  * `name`: Display name for your web app (e.g., "My Web App"). Updates existing app name if different.
  * `environment`: Name of the environment to associate this app with (e.g., `staging`, `production`). See [Using Environments](#using-environments-to-separate-builds) below.
  * `variables`: Key-value variables to attach to the registered build. Available in flow instructions via `${env:KEY}`. Use `KEY1=VALUE1,KEY2=VALUE2`. See [Build Variables](/variables#build-variables).
  * `suite-ids`: Comma-separated suite UUIDs to run after upload (e.g., `uuid1,uuid2`).
  * `flow-ids`: Comma-separated flow UUIDs to run after upload (e.g., `uuid1,uuid2`).
</Note>

### Basic Usage

```yaml theme={null}
- name: Register Web App with Autosana
  uses: autosana/autosana-ci@main
  with:
    api-key: ${{ secrets.AUTOSANA_KEY }}
    platform: web
    app-id: my-web-app
    url: https://my-app-preview.vercel.app
    name: My Web App  # Optional: display name for the app
    # variables: DEPLOY_URL=${{ steps.deploy.outputs.url }},LOGIN_VARIANT=passwordless  # Optional: attach build variables
    # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
    # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
```

### Web Workflow Examples

<Tabs>
  <Tab title="Vercel">
    For Vercel deployments using the GitHub integration (OAuth), use the `wait-for-vercel-preview` action to get the preview URL:

    ```yaml .github/workflows/autosana-web-vercel.yml theme={null}
    name: Web App Testing with Autosana

    on:
      pull_request:
        branches: [ main ]

    jobs:
      test-preview:
        runs-on: ubuntu-latest
        permissions:
          contents: read
          pull-requests: read
          deployments: read

        steps:
          - name: Wait for Vercel Preview
            uses: patrickedqvist/wait-for-vercel-preview@v1.3.2
            id: vercel
            with:
              token: ${{ secrets.GITHUB_TOKEN }}
              max_timeout: 600

          - name: Register with Autosana
            uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              platform: web
              app-id: my-web-app  # Choose a unique identifier for your app
              url: ${{ steps.vercel.outputs.url }}
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```

    <Note>
      The `wait-for-vercel-preview` action requires the `permissions` block shown above to access deployment information. Without these permissions, you may see "Resource not accessible by integration" errors.
    </Note>

    <Note>
      The `app-id` must be lowercase alphanumeric with hyphens only (e.g., `my-web-app`, `staging`, `preview-app-123`). This identifier is used to track your web app across deployments.
    </Note>
  </Tab>

  <Tab title="Custom / Static URL">
    If you have a static staging URL or custom deployment:

    ```yaml .github/workflows/autosana-web-custom.yml theme={null}
    name: Web App Testing with Autosana

    on:
      push:
        branches: [ main ]

    jobs:
      test:
        runs-on: ubuntu-latest

        steps:
          - name: Register with Autosana
            uses: autosana/autosana-ci@main
            with:
              api-key: ${{ secrets.AUTOSANA_KEY }}
              platform: web
              app-id: my-staging-app
              url: https://staging.myapp.com
              # suite-ids: uuid1,uuid2  # Optional: trigger suites after upload
              # flow-ids: uuid1,uuid2  # Optional: or specify individual flows
    ```
  </Tab>
</Tabs>

***

## Step 4: What Happens Next?

Once you've set up our CI/CD integration:

<Steps>
  <Step title="Run flows directly (optional)">
    Add `suite-ids` or `flow-ids` to your action config to trigger flows immediately after upload. The action will wait for all flows to complete and report results inline — failing the job if any flows fail.
  </Step>

  <Step title="Configure automations">
    Alternatively (or additionally), set when flows run in your [Automations](https://autosana.ai/automations) page to run flows on a schedule or trigger.
  </Step>

  <Step title="View test results">
    Check your test runs in the [Runs](https://autosana.ai/runs) page.
  </Step>
</Steps>

***

## Need Help Setting Up?

If you're using Claude Code or another AI agent, you can add our MCP server to help automate the setup process. The MCP server can:

* Set up your CI/CD pipeline automatically
* Build your app for iOS or Android
* Find your app's bundle ID
* And more!

Learn more at our [MCP Server documentation](https://docs.autosana.ai/mcp-setup).

### Instructions for AI Agents Using the Autosana MCP (humans, you can ignore this!)

<Note>
  If you are an AI agent (such as Claude Code, Cline, or Cursor) using the Autosana MCP server to help set up CI/CD workflows, use the following prompt to guide your workflow generation.
</Note>

```
Scan the repo to understand the project and how it is built. You should determine things like:
1. The project type (react-native, flutter, android-native, ios-native, etc)
2. Supported platforms (android, ios, or both)
3. Existing Github workflow files, if any
4. The correct build commands and configurations, indicated by the presence of Fastlane, EAS, etc... It can also help to look for .md files that explain the build process.
5. Available environments (development, staging, production, etc) and how they are configured

Create a plan for how to build the app. Then, generate a complete autosana-ios.yml and autosana-android.yml (whatever platforms are applicable) file, in .github/workflows. Use the best approach for the project (Fastlane, EAS, native, etc).

Unless specified otherwise by the user, the file(s) should start with the following:
name: Autosana (platform) App Upload
on:
  workflow_dispatch:
  push:
    branches:
      - (primary branch)
  pull_request:
    branches:
      - (primary branch)

The file MUST contain the following Autosana Github Actions script at the end:
- uses: autosana/autosana-ci@main
  with:
    api-key: ${{ secrets.AUTOSANA_KEY }}
    bundle-id: com.example.app # TODO: Replace with your bundle ID
    platform: ios/android
    build-path: ./build/MyApp.app # TODO: Replace with your build path

Important requirements:
- For Android, the APK must include the `x86_64` architecture; a universal APK is recommended
- For iOS, always build for simulator, not physical device
- Include actual paths based on common conventions for the detected framework
- Prefer the staging environment, if available (and not specified otherwise by the user)
- For EAS iOS builds, you can use a linux runner if doing cloud builds

Finally, once implemented, thoroughly review the script(s) to ensure it is correct before it's run.
It is critical that the script(s) will run successfully.
```

***

## Helpful Resources

<CardGroup cols={3}>
  <Card title="App Build Guide" icon="hammer" href="/app-build-guide">
    Learn how to build your app for our cloud
  </Card>

  <Card title="GitHub Action" icon="github" href="https://github.com/Autosana/autosana-ci">
    View the source code and documentation for our GitHub Action
  </Card>

  <Card title="Get Your API Key" icon="key" href="https://autosana.ai/settings?tab=integrations">
    Copy your API key from Settings → Integrations
  </Card>
</CardGroup>
