Skip to main content

GitHub Actions

Add Aucert to your GitHub Actions workflow to run AI-powered mobile tests on every pull request.

Basic workflow

This workflow runs Aucert tests on every pull request targeting main:

.github/workflows/aucert.yml
name: Aucert Tests
on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- name: Build app
run: ./gradlew assembleDebug

- name: Install Aucert CLI
run: npm install -g @aucert/cli

- name: Run Aucert tests
env:
AUCERT_API_KEY: ${{ secrets.AUCERT_API_KEY }}
run: aucert run --output junit

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: aucert-results
path: ./aucert-results/

- name: Publish test summary
if: always()
uses: dorny/test-reporter@v1
with:
name: Aucert test results
path: ./aucert-results/*.xml
reporter: java-junit

Setup

1. Store your API key

Go to SettingsSecrets and variablesActionsNew repository secret:

Secret nameValue
AUCERT_API_KEYYour API key from the Aucert dashboard

2. Commit your config

Ensure aucert.config.yaml is committed to your repository. The CI workflow uses the same config as local development.

3. Add the workflow

Copy the workflow YAML above to .github/workflows/aucert.yml and push.

Advanced workflows

Scoped testing by changed files

Run only relevant test scopes based on which files changed in the PR:

.github/workflows/aucert-scoped.yml
name: Aucert (scoped)
on:
pull_request:
branches: [main]

jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
scope: ${{ steps.scope.outputs.value }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Determine test scope
id: scope
run: |
CHANGED=$(git diff --name-only origin/main...HEAD)
if echo "$CHANGED" | grep -q "navigation\|NavGraph\|AndroidManifest"; then
echo "value=navigation,user-flows" >> "$GITHUB_OUTPUT"
elif echo "$CHANGED" | grep -q "res/layout\|Composable"; then
echo "value=user-flows" >> "$GITHUB_OUTPUT"
else
echo "value=regression" >> "$GITHUB_OUTPUT"
fi

test:
needs: detect-changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build app
run: ./gradlew assembleDebug

- name: Install Aucert CLI
run: npm install -g @aucert/cli

- name: Run scoped tests
env:
AUCERT_API_KEY: ${{ secrets.AUCERT_API_KEY }}
AUCERT_SCOPE: ${{ needs.detect-changes.outputs.scope }}
run: aucert run --output junit

- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: aucert-results
path: ./aucert-results/

Scheduled regression testing

Run full regression tests nightly, independent of PRs:

.github/workflows/aucert-nightly.yml
name: Aucert nightly regression
on:
schedule:
- cron: '0 2 * * *' # 2:00 AM UTC daily
workflow_dispatch: # Manual trigger

jobs:
regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build app
run: ./gradlew assembleDebug

- name: Install Aucert CLI
run: npm install -g @aucert/cli

- name: Run full regression
env:
AUCERT_API_KEY: ${{ secrets.AUCERT_API_KEY }}
run: aucert run --scope regression --output html

- name: Upload HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: aucert-nightly-report
path: ./aucert-results/*.html
retention-days: 30

Matrix testing (multiple build variants)

Test debug and release builds in parallel:

.github/workflows/aucert-matrix.yml
name: Aucert (matrix)
on:
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
variant: [debug, release]
steps:
- uses: actions/checkout@v4

- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17

- name: Build ${{ matrix.variant }}
run: ./gradlew assemble${{ matrix.variant == 'debug' && 'Debug' || 'Release' }}

- name: Install Aucert CLI
run: npm install -g @aucert/cli

- name: Run tests (${{ matrix.variant }})
env:
AUCERT_API_KEY: ${{ secrets.AUCERT_API_KEY }}
AUCERT_APP_APK: ./app/build/outputs/apk/${{ matrix.variant }}/app-${{ matrix.variant }}.apk
run: aucert run --output junit

- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: aucert-results-${{ matrix.variant }}
path: ./aucert-results/

Output formats for CI

FormatFlagCI use case
junit--output junitGitHub Actions test summary, Jenkins JUnit publisher, GitLab test reports
json--output jsonCustom dashboards, Slack notifications, downstream processing
html--output htmlHuman-readable artifacts for nightly reports
tip

Use --output junit for PR workflows so test results appear directly in the GitHub Actions Summary tab. Use --output html for scheduled runs where you want a browsable report.

Caching

Speed up workflows by caching the Aucert CLI installation:

- name: Cache Aucert CLI
uses: actions/cache@v4
with:
path: ~/.npm
key: aucert-cli-${{ hashFiles('**/package.json') }}

- name: Install Aucert CLI
run: npm install -g @aucert/cli

Troubleshooting

Tests fail with "Authentication error"

Verify your secret is set correctly:

- name: Debug auth
run: |
if [ -z "$AUCERT_API_KEY" ]; then
echo "ERROR: AUCERT_API_KEY is not set"
exit 1
fi
echo "API key is set (length: ${#AUCERT_API_KEY})"
env:
AUCERT_API_KEY: ${{ secrets.AUCERT_API_KEY }}

Common causes:

  • Secret name is misspelled (check case: AUCERT_API_KEY)
  • Secret is set at the wrong scope (repository vs organization vs environment)
  • Secret was rotated but the GitHub secret wasn't updated
APK not found in CI

The build step must complete before aucert run. Verify:

ls -la ./app/build/outputs/apk/debug/

If the path differs from your local build, set AUCERT_APP_APK explicitly:

env:
AUCERT_APP_APK: ./app/build/outputs/apk/debug/app-debug.apk
Workflow takes too long

Reduce test scope for PR workflows and reserve full runs for nightly:

# PR: fast feedback
run: aucert run --scope navigation --max-tests 20

# Nightly: comprehensive
run: aucert run --scope all

What's next