Skip to main content

GitHub Actions

actions/checkout matters here: grantiva ci run derives the project slug from the origin git remote (owner/repo) and the branch from GITHUB_HEAD_REF or GITHUB_REF_NAME, falling back to git rev-parse. Without the checkout there is no remote to read. grantiva doctor exits non-zero when a required check fails — Xcode missing, an unreadable toolchain — and stays quiet about the optional ones, so it is safe as a preflight step. Results are posted as a GitHub Check Run when the GitHub App is configured for your organization.

Environment variables

Output and exit codes

0 if every screen passes, 1 if any fails. The results are uploaded either way — a visual regression is a verdict, not a crash. Progress narration goes to stderr and results go to stdout, so a pipeline can parse the result without filtering:
Add --verbose when a job fails for a reason the summary does not explain: it logs every subprocess Grantiva runs — the exact xcodebuild and simctl invocations — and their exit status.

Pre-built binaries

Grantiva can consume pre-built .app bundles or .ipa archives instead of building from source. This decouples the build from the test.
When --app-file is provided:
  • The xcodebuild step is skipped entirely
  • The binary is validated to be a simulator build, not a device build
  • The bundle ID is derived from the binary’s Info.plist if not specified
  • .ipa files are extracted automatically (the .app from Payload/)
  • scheme is not required in grantiva.yml

Split build and test

Separate the build and the test into different jobs. That lets you cache build artifacts, reuse them across test runs, and run visual regression on several device configurations in parallel.
Use --derived-data-path to isolate Xcode products per job when you do build inside the test job — it overrides any -derivedDataPath in build_settings.

Functional flows in CI

grantiva run needs no authentication, so it works in pipelines that do not use visual regression at all.
Upload the report directory as an artifact on failure:

Backgrounded runs

With --keep-alive the session outlives the flows, so process exit is not a completion signal. Wait on --ready-file instead:
The file is deleted at startup and always written, including on a setup failure that never reaches the runner — so that loop, which has no timeout of its own, cannot wedge the job.

Parallel runs on one machine

Runs on different simulator UDIDs execute in parallel. At most four Grantiva-booted simulators are admitted at once; a fifth boot waits up to ten minutes and then fails, naming the sessions holding capacity.
On a self-hosted runner, end the job with grantiva simulator cleanup to delete Grantiva-created simulators that are shut down and no longer in an active session. See Simulator management for capacity limits, leases, and reclaiming a device a killed job left behind.

Approving new baselines

When UI changes are intentional, approve the new screenshots locally:
From a pipeline, review the uploaded run instead:
See VRT review for the full review loop.

Results

grantiva ci run prints a run summary: the run ID and status, the branch and commit, the trigger, the screen counts (total, passed, failed, new), the duration, and the dashboard URL. Per-screen detail — status, pixel diff percentage, perceptual distance, and the diff image path — lives in the dashboard, and locally in grantiva diff compare.