CI
Nostr CI results are published as events, like everything else. Two things matter: finding the workflow, and reading the result correctly.
Where workflows live
.ngit/act/workflows/ngit-ci runs these workflows in Linux containers through act, using GitHub Actions-compatible syntax. A repository can also have .github/workflows/, but the two directories are independent. A check needed on both systems must exist in both directories.
Keep macOS and Windows jobs in .github/workflows/. ngit-ci refuses job-level reusable workflows written as jobs.<id>.uses; composite actions used from a step work on both systems.
To read the Nostr CI workflow as it existed at a given commit:
bash
git show <COMMIT>:.ngit/act/workflows/<WORKFLOW>.yamlCheck that its triggers actually cover the event you care about, and that its steps run the checks you think they do.
Install ngit in a workflow
Use the setup action when a job needs ngit or a nostr:// Git remote. It installs both ngit and git-remote-nostr from a checksum-pinned manifest:
yaml
- uses: danconwaydev/setup-ngit@v3
# Optional exact version
- uses: danconwaydev/setup-ngit@v3
with:
version: 3.0.0-rc.7This works in ngit-ci jobs and GitHub-hosted jobs. It is more efficient than compiling ngit from source or piping the website installer into a CI job.
Checking a commit
bash
ngit ci status <COMMIT-ISH>
ngit ci status <COMMIT-ISH> --offline # cache only, after the first queryThe target can be a commit-ish, a PR (#<prefix>, an nevent, or a full event ID), or nothing at all, in which case it means HEAD. Query the commit that introduced the change, not just the tip.
A PR reports only the runs for its latest revision; results from earlier revisions are never presented as current.
What the fields mean:
| Field | Meaning |
|---|---|
command_status | Did the query command succeed |
ci.state | Pending, running, or concluded |
ci.conclusion | Success, failure, cancelled, or other outcome |
ci.runs[].jobs | Which job passed or failed |
ci.runs[].workflow | Which workflow produced the run |
ci.runs[].integrity | Whether the commit is present locally and the workflow hash matches |
coverage | How completely the result covers the commit |
Partial coverage is not evidence of success.
Gating on a result
To make the command exit non-zero unless CI is green and meets a trust floor, request one JSON document and gate on trust:
bash
ngit ci status <COMMIT-ISH> \
--json \
--require-ci-trust maintainer-directedTwo floors are available:
| Level | Meaning |
|---|---|
maintainer-directed | The result traces back to a maintainer's instruction |
operationally-associated | A weaker association with the repository's operators |
The gate passes only if the result is a success and its weakest run meets the floor.
The same gate works on a merge, which is where it matters most:
Choose the target branch first
ngit pr merge merges into your current branch. Switch to the intended target explicitly before using it.
bash
git switch <TARGET-BRANCH>
ngit pr merge <ID> --require-ci-trust maintainer-directed
git push origin <TARGET-BRANCH>Without it, a failing, unfinished result, a signer with no known trust context, or an entirely absent CI result will not block the merge. A successful push does not enforce CI by itself.
Asking a coordinator to run CI
CI runs are performed by a coordinator you ask. A request is standing: it covers runs the coordinator starts after it, never earlier ones, and stays in force until you stop it.
bash
ngit ci request <COORDINATOR> # npub or hex
ngit ci stop <COORDINATOR>Requests are signed for one repository perspective: your own announcement if you've published one, otherwise the selected maintainer's. A coordinator's default policy accepts only a confirmed maintainer of that perspective, so ngit warns, but doesn't refuse, if you aren't one; an operator may have allowed your key explicitly.
To run a single workflow once, without a standing request:
bash
ngit ci trigger <COORDINATOR> --workflow .ngit/act/workflows/test.yaml
ngit ci trigger <COORDINATOR> <COMMIT-ISH> --workflow .ngit/act/workflows/test.yamlThe workflow is identified by the SHA-256 of the blob at the resolved commit, not your working tree, whose line endings and clean/smudge filters may hash differently from what the coordinator sees.
When no run appears
Report it as "no matching CI event found" rather than as a pass. Then check, in order:
- Did the workflow exist at that commit?
- Did its trigger match the event?
- Did the query refresh the repository relays, or was it
--offlineagainst a cold cache?
Only after all three should you conclude that CI genuinely did not run.
Run a coordinator yourself
The commands above are for contributors and maintainers. To operate the coordinator, see Self-host ngit-ci and its generated configuration reference.