selo CLI as your terminal, in three modes: a free preflight, a paid test, and an offline verify of a signed verdict. A FAIL, an INCONCLUSIVE, an unconfirmed payment, an expired authorization or a missing report fails the job, and the promote job never runs.
Reference the action
The action lives in the Selo repository at.github/actions/release-gate:
npx --yes pnpm@10.33.0 install --frozen-lockfile --filter "@selo/cli...", and runs packages/cli/bin/selo.js. Relative paths such as selo/contract.json resolve from your workspace.
The three modes
- preflight
- test
- verify
Free. Needs no wallet and spends nothing. It checks the authorization, your endpoint’s 402, the network, the asset and the price.
Inputs
Every input except
mode maps to the CLI flag of the same name; approve-mainnet: "true" adds --approve-mainnet. See GitHub Action reference and selo test.
Set up a gated release
1
Create a dedicated payer wallet
An Algorand account opted in to USDC (ASA
31566704), funded with only what a few release tests cost. A release test costs Selo’s price, 1.00 USDC. Selo pays your endpoint’s own price from its wallet.2
Authorize the staging route
Run
selo auth create for the exact staging URL and method, serve the printed line at https://<staging origin>/.well-known/selo-verification.txt, then run selo auth verify. An authorization lasts 24 hours after verification, so authorize again before a release window. See Authorize your endpoint.3
Add the configuration
In Settings → Environments, create
selo-paid-release, add required reviewers, limit it to the main branch, and add the secret there.4
Commit the contract, the body and the keys
The promote job verifies the signed attestation against the committed keys, so it promotes only a PASS that Selo signed for this commit, URL and method.
5
Add the workflow
Copy the workflow below and replace the build and deploy scripts with your own.
A complete workflow
This isexamples/github-actions/release-gate.yml from the Selo repository. ./scripts/build-and-test.sh and ./scripts/deploy.sh stand for your own build and deploy steps.
.github/workflows/release-gate.yml
The job summary of
paid-gate shows the verdict, each check, the job id and both transaction ids, because the CLI appends a Markdown table to GITHUB_STEP_SUMMARY.
How the wallet stays safe
The paid job runs only after review
The paid job runs only after review
paid-gate runs only on a push to main or a manual dispatch, inside the protected selo-paid-release environment, so it waits for a reviewer. The mnemonic is an environment secret, available only to jobs in that environment.No pull_request_target
No pull_request_target
Pull requests, including those from forks, never reach the paid job. Do not add
pull_request_target to this workflow: it runs with access to your repository’s secrets on behalf of pull request events, and the paid job must never run for code you have not reviewed.Inputs reach the script through the environment
Inputs reach the script through the environment
The action never interpolates an input into its shell script. Every input is passed as an environment variable (
SELO_MODE, SELO_URL, SELO_RELEASE and so on), and the script reads those variables, so a value that contains shell syntax is treated as data, not as code.Spending is capped and checked before signing
Spending is capped and checked before signing
max-usdc caps what one run may pay Selo. The CLI refuses a 402 on another network, a different payee, or a Mainnet payment without approve-mainnet, all before signing. Selo, in turn, spends at most 0.50 USDC on your endpoint per job.A paid run is never cancelled or repeated on its own
A paid run is never cancelled or repeated on its own
cancel-in-progress: false keeps a newer push from cancelling a paid run in flight. The CLI never retries a payment. If the outcome is unconfirmed it exits 2 with a warning. Do not re-run the job blindly: the run state lives in the runner’s workspace, which a re-run does not keep, so a re-run starts a new paid test. Check the payer account for the expected transaction id printed in the log first. See Recover an interrupted run.Nothing secret is published
Nothing secret is published
Logs, the job summary and the uploaded
selo-gate.json and selo-attestation.json contain no mnemonic, no signed payment and no private report token. Do not upload the .selo/ directory: it holds the private report link.Proof: a blocked and a promoted release
The Selo repository runs theRelease gate demo workflow (.github/workflows/release-gate-demo.yml). You choose a release of the demo merchant, broken-v1 or fixed-v2, and it verifies the signed Mainnet attestation of that release against the pinned key before a promote job may run. Its two jobs:
.github/workflows/release-gate-demo.yml
The attestations it verified come from the paid Mainnet runs described in Proof on Algorand Mainnet.
Troubleshooting
Next
Verify a signed verdict
What verify mode checks, and how to check it yourself.
GitHub Action reference
Every input and output in one place.