Skip to content

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>.yaml

Check 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.7

This 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 query

The 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:

FieldMeaning
command_statusDid the query command succeed
ci.statePending, running, or concluded
ci.conclusionSuccess, failure, cancelled, or other outcome
ci.runs[].jobsWhich job passed or failed
ci.runs[].workflowWhich workflow produced the run
ci.runs[].integrityWhether the commit is present locally and the workflow hash matches
coverageHow 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-directed

Two floors are available:

LevelMeaning
maintainer-directedThe result traces back to a maintainer's instruction
operationally-associatedA 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.yaml

The 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:

  1. Did the workflow exist at that commit?
  2. Did its trigger match the event?
  3. Did the query refresh the repository relays, or was it --offline against 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.

Next

Git collaboration, without the platform.