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 Settings → Secrets and variables → Actions → New 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​