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:
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 name | Value |
|---|---|
AUCERT_API_KEY | Your 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:
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:
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:
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
| Format | Flag | CI use case |
|---|---|---|
junit | --output junit | GitHub Actions test summary, Jenkins JUnit publisher, GitLab test reports |
json | --output json | Custom dashboards, Slack notifications, downstream processing |
html | --output html | Human-readable artifacts for nightly reports |
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
- CLI commands — Full command reference
- Configuration — Customize test behavior
- How to integrate with CI/CD — GitLab CI and Jenkins examples