Run TOVIO in CI
The CI bridge, and the shape of a pipeline that uses it.
Written By Dustin
Last updated 27 minutes ago
The CI bridge (@tovio/ci-bridge) is a zero-dependency Node wrapper around the TOVIO CLI for GitHub Actions and Spacelift. It owns no storage, sync, Git translation, authentication, policy, or cryptography — it validates a small operation contract and starts tovio with an exact argument vector.
A closed operation set
checkout, sync, git-bridge, health, and status. That is the whole surface. There is no arbitrary-command input, and the child is started with no shell, so a workflow value can never be assembled into a command line.
Two actions, not one
Installing a verified release and running an operation are deliberately separate actions. The operation wrapper never downloads a binary; a sibling setup action does.
- name: Install a verified TOVIO release id: tovio uses: Tovio-VCS/tovio/packages/tovio-ci-bridge/setup@<full-commit-sha> with: version: 1.0.0 env: GH_TOKEN: ${{ github.token }}- name: Checkout uses: Tovio-VCS/tovio/packages/tovio-ci-bridge@<same-full-commit-sha> with: operation: checkout tovio-path: ${{ steps.tovio.outputs.tovio-path }} remote: https://forge.example.test repository-id: <64 hex chars> destination: ${{ github.workspace }}Pin both to the same full immutable commit SHA. The version is an exact semantic version — never latest and never a mutable channel.
What "verified" means
The setup action bounds both HTTPS downloads, verifies the archive against its .sha256 sidecar, requires gh attestation verify provenance naming the repository's exact release workflow and the matching immutable refs/tags/v<version>, rejects self-hosted attestation signers, accepts only the release packager's exact regular-file member set, extracts without a shell, smokes both binaries, and removes the temporary install in an always-run post step. Any of those failing is TVO-CI-009, and no unverified binary path is ever exposed to a later step. Releases additionally publish a signed SPDX SBOM attestation per artifact.
Bounds you get for free
Every invocation has an explicit timeout — 15 minutes by default, 1 second to 60 minutes allowed — and expiry terminates the exact child process tree rather than leaving the wrapper waiting. While running it emits a heartbeat at least every 30 seconds that contains no arguments, remote URLs, paths, or inherited environment values.
Partial checkouts
For a large repository, sparse, blobless, blob-limit, depth, and no-attachments are exposed as inputs and the wrapper enforces the CLI's mutual-exclusion rules before starting anything. A sparse or blobless checkout is usually much faster and enough for CI.
Gating on the result
healthis a diagnostic, not a gate. It reports whether the lane is clean, landable, and how stale — and it exits0even when the lane tip carries unresolved conflicts, because a conflict is data rather than an error. Do not wire it up as a pass/fail step and assume it will stop anything.
The gate is tovio build-check: exit 0 if and only if the lane tip has no unresolved conflict objects, non-zero listing the offending paths. It does not compile or test anything — run your own build in its own step.
build-check is not one of the bridge's five operations, so call the installed binary directly:
- name: Conflict-free gate working-directory: ${{ github.workspace }} run: ${{ steps.tovio.outputs.tovio-path }} build-checktovio fsck is the other useful CI gate: it re-hashes every object and verifies references and the audit chain. Add --strict to promote suspected key-material warnings to failures.
Spacelift
The same executable runs from a bounded lifecycle hook:
before_init: - tovio-ci-bridge sync - tovio-ci-bridge healthA source-built multi-architecture runner image is published per release tag. Pin its immutable digest rather than a mutable tag. The image contains no worker key, repository session, or cloud credential — your secret store mounts those at runtime.
Status
The bridge is built and is the v1 CI story: you bring your own runner. It is not declared production-complete until signed-binary installation, clean hosted-runner and private-worker exercises, marketplace and registry publication, live OIDC-scoped ephemeral enrollment, revocation and protected-path tests, and an independent supply-chain review are all recorded as evidence. Hosted agent and CI end-to-end remains an open gate.