@tapground/cli
v0.1.0
Published
Tapground CLI — run YAML mobile UI tests against the Tapground API from CI/CD pipelines.
Downloads
93
Readme
@tapground/cli
Run YAML mobile UI tests against the Tapground API from your CI/CD pipeline. AI-grounded, deterministic, JUnit-XML-friendly.
- run: tapground run "tests/**/*.yaml" \
--platform ios \
--app $TAPGROUND_APP_UUID \
--binary ./build/app.ipa \
--junit-xml results.xml
env:
TAPGROUND_API_KEY: ${{ secrets.TAPGROUND_API_KEY }}Install
# In CI: zero-install via npx
npx --yes @tapground/cli@latest run …
# Globally
npm i -g @tapground/cli
# As a devDependency (recommended for repos with package.json)
pnpm add -D @tapground/cli
pnpm exec tapground run …Requires Node.js 20+.
Quick start
- Get an API key from
Settings → API keysin the Tapground app (tg_live_…format). - Note your App UUID (
tapground apps list). - Add the key as a CI secret named
TAPGROUND_API_KEY. - Drop a step into your pipeline:
- run: tapground run "tests/**/*.yaml" \
--platform ios \
--app a1b2c3d4-… \
--binary ./build/app.ipa \
--junit-xml results.xml
env:
TAPGROUND_API_KEY: ${{ secrets.TAPGROUND_API_KEY }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: tapground-artifacts
path: tapground-artifacts/Commands
| Command | What it does |
| --------------------------- | ------------------------------------------------------- |
| tapground run [paths…] | Submit YAML files, poll, write JUnit, download artifacts |
| tapground apps list | List apps in your organization |
| tapground builds list | List builds for --app <uuid> |
| tapground version | Print CLI + Node versions; --server probes API too |
Run tapground <cmd> --help for the full flag surface.
tapground run — anatomy
Targeting (one of these is required)
| Flag | Description |
| ------------------- | ------------------------------------------------------------ |
| --app <uuid> + --binary <path> | Upload the binary as a fresh build, then run |
| --build <uuid> | Run against an existing build |
| --platform <ios\|android> | Required regardless of upload vs. build |
--binary and --build are mutually exclusive.
Discovery
Positional arguments accept files, directories, and glob patterns:
tapground run tests/login.yaml
tapground run tests/ # recurse for *.yaml + *.yml
tapground run "tests/**/*.yaml" # quote the glob
tapground run tests/auth/ tests/payments/ # mix*.yaml and *.yml. Hidden files (.foo.yaml) skipped. Default ignores:
node_modules, .git, dist, build, coverage, .next, .turbo,
.cache. Override with --ignore <glob> (repeatable) or tapground.yml.
Filter with --grep <substring>:
tapground run "tests/**/*.yaml" --grep loginEmpty match → exit 4 with a hint.
Build metadata (auto-derived from CI env)
| Flag | Default source |
| ------------------------- | -------------------------------------------------------- |
| --build-version | ${branch}-${shortSha} (GitHub / GitLab / Circle / Bitbucket) |
| --build-environment | ci |
| --external-id | gha-{repo}-{runId}-{attempt} etc., per CI provider |
| --device-type | server picks any compatible |
| --os-version | server picks any compatible |
Output + reporting
| Flag | Description |
| ---------------------------- | ------------------------------------------------------ |
| --junit-xml <path> | Opt-in JUnit XML report. Atomic write (temp + rename). |
| --artifacts <mode> | failed (default) / all / off |
| --artifacts-dir <path> | Default ./tapground-artifacts |
| --logs <mode> | failed (default) / all / off — embeds in JUnit <failure> body |
| --output <human\|json> | NDJSON event stream when json |
| --quiet / --verbose | Less / more progress detail |
| --no-groups | Disable GitHub Actions ::group:: markers (auto-on inside GH Actions) |
| --no-color | Disable ANSI colors (also honors NO_COLOR env) |
Concurrency + timeouts
| Flag | Default | Description |
| -------------------- | ------- | ------------------------------------------------------ |
| --max-concurrency | 8 | Cap on parallel submit + poll requests |
| --timeout | 30m | Total CLI runtime ceiling (e.g. 30m, 1h30m, 90s) |
Artifact downloads have a separate fixed pool of 3 (independent of --max-concurrency).
--dry-run
tapground run --dry-run "tests/**/*.yaml"Discovers + parses + validates YAML against the same schema the worker uses.
Surfaces typos as <path>:<key>: <message> and exits 4. No HTTP traffic.
tapground.yml — checked-in defaults
Place at the repo root (or any parent directory of cwd). Shape:
defaults:
app: a1b2c3d4-… # App UUID
platform: ios
buildEnvironment: ci
buildVersionFormat: "rc-{shortSha}-{runNumber}"
device:
type: "iPhone 15"
osVersion: "18.0"
junitXml: ./test-results/tapground.xml
artifacts: failed
artifactsDir: ./tapground-artifacts
logs: failed
timeout: 30m
maxConcurrency: 8
output: human
ignore:
- tests/manual/**
- "**/_drafts/**"Precedence: CLI flag > env var > tapground.yml > built-in default.
Override the file path with --config <path> or skip entirely with --no-config.
Build-version template placeholders: {sha}, {shortSha}, {branch},
{runNumber}, {timestamp}.
Environment variables
| Variable | Purpose |
| ---------------------------- | --------------------------------------------------------- |
| TAPGROUND_API_KEY | Required. API key (tg_live_…) |
| TAPGROUND_API_URL | API origin override. Default https://api.tapground.com |
| TAPGROUND_APP_URL | App origin override (used for run URLs in JUnit body) |
| TAPGROUND_APP | Default --app value |
| TAPGROUND_BUILD | Default --build value |
| TAPGROUND_BUILD_VERSION | Default --build-version |
| TAPGROUND_BUILD_ENVIRONMENT| Default --build-environment |
| TAPGROUND_EXTERNAL_ID | Default --external-id |
| TAPGROUND_PLATFORM | Default --platform |
| TAPGROUND_DEVICE_TYPE | Default --device-type |
| TAPGROUND_OS_VERSION | Default --os-version |
| TAPGROUND_TIMEOUT | Default --timeout |
| TAPGROUND_MAX_CONCURRENCY | Default --max-concurrency |
| TAPGROUND_JUNIT_XML | Default --junit-xml |
| TAPGROUND_ARTIFACTS | Default --artifacts |
| TAPGROUND_ARTIFACTS_DIR | Default --artifacts-dir |
| TAPGROUND_LOGS | Default --logs |
| TAPGROUND_OUTPUT | Default --output |
| TAPGROUND_QUIET | 1 enables --quiet |
| TAPGROUND_VERBOSE | 1 enables --verbose |
| TAPGROUND_GREP | Default --grep |
| NO_COLOR | Disable ANSI colors |
| FORCE_COLOR | Re-enable colors when not a TTY |
CI provider env vars (GITHUB_ACTIONS, GITLAB_CI, CIRCLECI,
BITBUCKET_BUILD_NUMBER, CI) are auto-detected to derive externalId
and buildVersion defaults.
Exit codes
| Code | Meaning |
| ---- | -------------------------------------------------------- |
| 0 | All tests passed |
| 1 | At least one test failed (passed=false from server) |
| 2 | Suite completed with infra errors but no test failures |
| 3 | Suite incomplete (CLI --timeout exceeded, fatal error) |
| 4 | Usage error (bad flags, parse error, missing required input) |
| 130 | Cancelled via Ctrl+C (SIGINT). POSIX 128 + 2. |
| 143 | Cancelled via SIGTERM (e.g. CI workflow cancelled). 128 + 15. |
Priority when multiple categories apply: 4 > OS-signal > 3 > 1 > 2 > 0.
CI integration patterns
GitHub Actions
- uses: actions/setup-node@v4
with: { node-version: 20, cache: 'npm' }
- run: npx --yes @tapground/cli@latest run "tests/**/*.yaml" \
--platform ios \
--app ${{ vars.TAPGROUND_APP_UUID }} \
--binary ./build/app.ipa \
--junit-xml results.xml
env:
TAPGROUND_API_KEY: ${{ secrets.TAPGROUND_API_KEY }}
- uses: dorny/test-reporter@v1
if: always()
with:
name: Tapground
path: results.xml
reporter: jest-junit
- uses: actions/upload-artifact@v4
if: failure()
with:
name: tapground-artifacts
path: tapground-artifacts/The CLI emits ::group::tests/<file>.yaml — PASS|FAIL markers automatically
when GITHUB_ACTIONS=true so per-test progress is collapsible in the run log.
GitLab CI
test_ios:
image: node:20
script:
- npx --yes @tapground/cli@latest run "tests/**/*.yaml"
--platform ios
--app "$TAPGROUND_APP_UUID"
--binary ./build/app.ipa
--junit-xml results.xml
artifacts:
when: always
paths:
- tapground-artifacts/
reports:
junit: results.xmlTroubleshooting
"no test files matched" — quote your glob so the shell doesn't expand it
into nothing: "tests/**/*.yaml". Paths are resolved relative to cwd.
"--platform is required" — every tapground run needs --platform ios
or --platform android. The CLI doesn't auto-detect from the binary
extension (intentional — explicit > magic).
HTTP 401 — verify TAPGROUND_API_KEY is set and matches a non-revoked
key. Auth errors exit 4 (usage), not 2 (infra), so you don't infinite-loop
in a retry CI.
Custom API origin — point at a self-hosted or staging instance with
TAPGROUND_API_URL=https://api.staging.example.com. Run URLs in JUnit
bodies derive from TAPGROUND_APP_URL (or api.* → app.* substitution).
Compat matrix
| @tapground/cli | API version |
| ---------------- | ----------- |
| 0.1.x | ≥ 0.1 |
Pre-1.0: minor versions may include breaking changes. Pin tightly in CI
(@tapground/cli@^0.1.0) and review the CHANGELOG before
upgrading.
License
MIT. See LICENSE in the repo root.
