GitHub Action Workflow
July 19, 2026 · View on GitHub
This document defines the official GitHub Actions integration surface for ota.
Use ota-run/action@v1 when your runner is GitHub Actions and you want ota to publish a
step summary, annotations, pull-request comments, and receipt artifacts without writing your own
JSON glue.
Purpose
The GitHub Action keeps the boundary thin and honest:
- ota still owns diagnosis and receipt truth
- GitHub Actions still owns workflow scheduling and permissions
- the action should reuse
ota annotations --format markdownfor summaries/comments,ota annotations --format githubfor line annotations, and upload the captured ota artifacts
It is not a second diagnosis engine.
The action repo lives at github.com/ota-run/action. This page mirrors the shipped action contract so users do not need to leave the ota docs to find the supported inputs, outputs, and default behavior.
Use when
Use ota-run/action@v1 when:
- a pull request needs a read-only readiness gate
- you want archived
ota receipt --jsonartifacts in Actions - you want GitHub annotations without writing
ota annotationsglue yourself - you want a sticky pull-request comment that tracks the latest repo readiness result
Use direct ota commands in workflow steps when:
- the workflow must run
ota up,ota run, or other mutating/setup commands - you need full control over task orchestration inside the job
When a job needs direct ota commands, prefer installing ota from repo-owned
agent.bootstrap.ota.source truth:
- uses: actions/checkout@v6
- uses: ota-run/setup@v1
with:
source: contract
When a workflow intentionally skips ota-run/setup@v1 but still wants the GitHub wrapper to
honor repo-owned bootstrap truth, ota-run/action@v1 can consume the same contract directly:
- uses: actions/checkout@v6
- uses: ota-run/action@v1
with:
command: receipt
source: contract
contract-path: ota.yaml
Quick start
name: readiness
on:
pull_request:
push:
permissions:
actions: read
contents: read
pull-requests: write
jobs:
readiness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Publish ota readiness
uses: ota-run/action@v1
with:
command: receipt
archive: true
fail-on-new-blockers: true
github-token: ${{ github.token }}
What the action does
Current v1 behavior:
- runs
ota receipt --json --archiveorota doctor --json - installs ota by default on every run unless
install: neveris set - supports both workflow-owned explicit install truth and contract-owned install truth through
source: explicit | contract - writes a GitHub step summary through
ota annotations --format markdown - emits GitHub annotations through
ota annotations --format github - optionally creates or updates a sticky pull-request comment
- uploads the captured JSON output and any archived receipt file as workflow artifacts
Canonical renderer reuse
The GitHub wrapper should not maintain its own summary or annotation phrasing. Reuse the CLI adapters directly:
ota annotations --mode doctor --format markdownfor repo doctor step summaries and PR commentsota annotations --mode workspace-doctor --format markdownfor workspace doctor summaries and PR commentsota annotations --mode receipt-diff --format markdownfor receipt baseline gate summaries and PR commentsota annotations --mode doctor --format githuborota annotations --mode workspace-doctor --format githubfor line annotations
That keeps local CLI output, CI summaries, and pull-request comments on one canonical rendering path instead of re-assembling headline, blocker, provenance, and next-step text inside the wrapper.
Choose the command
- use
command: receiptwhen you want an archive-friendly, read-only repo receipt artifact - use
command: doctorwhen you want the richer readiness verdict and primary-blocker surface
receipt is the better default for CI because it stays read-only, packages the current readiness
scan as a durable artifact, and keeps later automation pointed at the receipt surface.
Install behavior
The action supports:
install: auto(default) to reuse an existing ota binary in explicit mode or install the contract-declared source in contract modeinstall: alwaysto run the official installer on every runinstall: neverto fail closed unless ota is already available on the runnersource: explicitto keep workflow-owned install truth throughota-versionsource: contractto readagent.bootstrap.ota.sourcefromota.yamlcontract-pathto point at the targetota.yamlwhensource=contractota-versionto pin the installed ota release explicitly in explicit mode
The action currently supports Linux, macOS, and Windows GitHub Actions runners.
When source: contract is used, the action and ota-run/setup@v1 both consume the same bootstrap
mapping from agent.bootstrap.ota.source:
kind: version- install through the release lane
- shell mapping:
curl -fsSL https://dist.ota.run/install.sh | OTA_VERSION=<version> sh - PowerShell mapping:
$env:OTA_VERSION='<version>'; irm https://dist.ota.run/install.ps1 | iex
kind: git_rev- install through the git lane
- shell mapping:
curl -fsSL https://dist.ota.run/install.sh | OTA_GIT_REV=<rev> sh -s -- --from-git - PowerShell mapping:
$env:OTA_GIT_REV='<rev>'; & ([scriptblock]::Create((irm https://dist.ota.run/install.ps1))) -FromGit
kind: branch- install through the same git lane
- shell mapping:
curl -fsSL https://dist.ota.run/install.sh | OTA_GIT_BRANCH=<branch> sh -s -- --from-git - PowerShell mapping:
$env:OTA_GIT_BRANCH='<branch>'; & ([scriptblock]::Create((irm https://dist.ota.run/install.ps1))) -FromGit
Direct command jobs
ota-run/action@v1 is the reporting wrapper. When a later job needs direct ota up, ota run,
or ota proof commands, use the contract-owned installer action instead of duplicating OTA_VERSION,
OTA_GIT_REV, OTA_GIT_BRANCH, or --from-git choices in workflow YAML.
That setup mode reads agent.bootstrap.ota.source from the checked-out ota.yaml and runs the
matching official installer flow through the single public ota-run/setup surface.
Managed reusable projection
When a repo wants Ota to own its CI verification lane rather than only report on it, generate a dedicated reusable workflow and keep a small human-owned caller for scheduling and provider policy:
ota ci github render --workflow verify \
--target-os linux \
--output .github/workflows/ota-governance.yml
ota ci github check --workflow verify \
--target-os linux \
--output .github/workflows/ota-governance.yml \
--caller .github/workflows/ci.yml
ota ci github sync --workflow verify \
--target-os linux \
--output .github/workflows/ota-governance.yml \
--caller .github/workflows/ci.yml
ota ci projection --workflow verify --mode container --target-os linux --json
ota ci github render --workflow verify --mode container --target-os linux
The caller retains triggers, permissions, runners, secrets, concurrency, environments, and
deployment jobs. It must reference the generated workflow and its exact
ota_projection_identity and ota_target_os; it may pass ota_runner as provider-owned runner selection. sync
writes only the marked generated file, never the caller. This is one-way authority: existing
workflow files remain useful onboarding evidence, but reviewed
ota.yaml is the source of Ota-owned setup and verification truth.
The generated adapter verifies its identity with Ota itself, not a provider-shell primitive. The
caller keeps runner selection provider-owned, while ota_target_os binds the selected operating
system into the projection identity.
The generated lane runs contract validation, Doctor, safe-surface discovery, and an agent-mode dry
run. For a finite selected task, it runs that task directly through ota run --agent; ota run
owns the full dependency closure, so a separate mutating ota up would create redundant work and
cannot carry ephemeral container state into the task. Service-runtime and proof-required lanes
retain one authoritative runtime execution path. A proof claim never admits an otherwise unsafe
task.
The generated action revisions are immutable so render identity covers the adapter dependencies.
A distinct runtime workflow remains a distinct projection;
Ota does not infer that one workflow's proof is evidence for another.
Use --mode container to materialize a separate container projection when the selected contract lane
advertises container execution. Native and container lanes intentionally have different projection
identities; a caller must select the generated lane it intends to schedule.
ota doctor now flags workflow-owned ota install truth when the repo already declares
agent.bootstrap.ota.source. If a job keeps explicit ota-version, raw installer commands,
branch/revision env markers, or source-install helpers in workflow YAML, treat that as
install-governance drift and move the job back onto source: contract unless the lane is an
intentional unreleased pressure path.
Inputs
commandsupportsreceiptordoctor; default:receiptpathpasses the repo or contract target to ota; default:.working-directorycontrols where ota is invoked; default:.execution-modeselectsnativeorcontainer; default:nativememberpasses an optional monorepo member targetarchiveadds--archivewhencommand=receipt; default:trueannotateemits GitHub annotations from ota findings; default:truemax-annotationscaps emitted annotations; default:20comment-prcreates or updates the sticky pull-request comment; default:truecomment-pr-onlylimits comment behavior to pull-request events; default:trueartifact-namesets the uploaded artifact name; default:ota-readinessartifact-retention-dayssets optional artifact retention in daysfail-on-errorfails the action when ota reports a blocked outcome; default:truefail-on-ci-driftis an opt-incommand: doctorgate that fails only when Ota establishes contract-to-CI workflow drift throughgovernance.merge_gateor canonical CI drift findings; default:falseinstallcontrols installation behavior withauto,always, ornever; default:autosourcechoosesexplicitorcontract; default:explicitcontract-pathpoints atota.yamlor a repo directory containing it whensource=contract; default:ota.yamlota-versionpins installer-driven ota installation to a specific release such asv1.4.3whensource=explicitota-binoverrides the ota binary name or path after resolution; default:otaoutput-pathchooses where the captured ota JSON payload is written; default:.ota-action-output.jsongithub-tokensupplies the token used for sticky pull-request comment updates
Outputs
okreports whether ota returned an ok resultstatusexposes the derived action status:ready,risky, orblockedoutput-pathreturns the written path to the captured ota JSON outputarchive-pathreturns the archived receipt path whenreceipt --archiveproduced oneartifact-namereturns the uploaded artifact nameerror-countreturns the error count from the ota summarywarn-countreturns the warning count from the ota summaryinfo-countreturns the info count from the ota summaryci-drift-detectedreports whether the current Doctor output contains canonical contract-to-CI workflow driftprimary-summaryreturns the primary blocker or top finding summary
Job boundaries
When the action installs ota, it adds the install directory to PATH for later steps in the same
job.
That does not cross job boundaries.
If a later job needs to invoke ota directly, install ota again in that job or run
ota-run/action@v1 in that job too.
Pull-request comments
If comment-pr: true is set:
- the workflow should grant
actions: readso pull-requestreceiptruns can restore the latest successful baseline artifact named byartifact-name - the workflow should grant
pull-requests: write - the action updates one sticky comment instead of posting a new one each run
comment-pr-only: truekeeps comment behavior limited to pull-request events
What it does not replace
ota-run/action@v1 does not replace direct execution commands such as:
ota upota run <task>ota workspace upota workspace run <task>
Use the action for GitHub-native reporting around ota. Use direct commands when the workflow actually needs ota to prepare or execute repo work.
Recommended split
The clean GitHub Actions shape is:
- a read-only readiness job with
ota-run/action@v1 - a follow-on execution job that runs direct
otacommands only after readiness is clear
That keeps pull-request feedback compact while preserving a clear execution boundary for setup, task runs, and release steps.
Repo and examples
- use github.com/ota-run/action for source, release tags, and copyable workflow examples
- keep this page as the canonical product reference for when to use the action and what its contract surface is