Tooling
CI and GitHub Actions
On this page
What runs in CI
The GitHub Action is a composite action around the CLI:
nanoflags scenarios run --source <source> --commit <sha> --run-url <this run>: NanoFlags evaluates every scenario marked "include in CI", records the result against the commit, and the table is written to the job summary.- With
scan-refs: true:nanoflags refs scan <refs-dir> --repo <owner/name> --commit <sha>. A failed reference upload is a warning; it does not decide the check. - Exit code: 0 all scenarios passed · 1 a scenario failed · 2 key or usage problem · 3 NanoFlags unreachable.
CI run results are part of the Team plan and above (Plans and limits).
Prefer no workflow and no CI key? The GitHub App keeps code references up to date from your default branch, comments a flag summary on pull requests and adds a scenario check. Unlike the Action, its check results are not recorded as CI runs.
CI vs admin vs SDK keys
| Key | Can | Cannot | Use in CI? |
|---|---|---|---|
CI nf_ci_… | Run scenarios, upload code references, export definitions, read the published revision | Publish or change configuration; fetch SDK bundles | Yes: the only key for CI |
Admin nf_adm_… | Everything a CI key can, plus publish environments that do not require a reviewed change | Publish environments that require approval; fetch SDK bundles | No. The action refuses admin keys |
Server nf_srv_… / client nf_pub_… | Fetch bundles, live updates, send telemetry | Any CI or admin endpoint (403) | No |
Create the CI key under Settings → SDK & access keys for the environment whose scenarios you want to check, and store it as a repository or environment secret.
Workflow
name: Flags
on:
pull_request: # NOT pull_request_target
push:
branches: [main]
permissions:
contents: read
jobs:
scenarios:
runs-on: ubuntu-latest
# Fork pull requests get no secrets: skip instead of failing.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: motazalmaroai/nanoflags-sdk/integrations/github-action@main # pin to a commit SHA in production
with:
key: ${{ secrets.NANOFLAGS_CI_KEY }}
source: draft
scan-refs: ${{ github.ref == 'refs/heads/main' }} # references from the default branch onlypull_requestruns the check on the pull request's code without exposing secrets to forks;permissions: contents: readis all the action needs.- Use
source: draftto check what you are about to publish, orsource: revisionto check what is published now.
Action inputs and output
| Input | Default | Description |
|---|---|---|
key | required | NanoFlags CI key. Pass a secret. |
base-url | CLI default | Edge URL (https://edge.nanoflags.io). |
source | draft | draft or revision (the published revision). |
scan-refs | false | true also uploads code references. |
refs-dir | . | Directory scanned for references. |
cli | npx --yes @nanoflags/cli@0 | Command that runs the CLI. |
Output result: passed, failed, or error when the checks could not run.
The action runs npx --yes @nanoflags/cli@0 by default, published on npm from the public nanoflags-sdk repository with npm provenance.
Security checklist
- Use a CI key, never an admin key. A CI key cannot publish, so a leaked CI key cannot change what your users get.
- Use
pull_request, notpull_request_target.pull_request_targetruns with your secrets while the workflow can be made to check out and execute code from the pull request, handing the key to anyone who can open one. - Fork pull requests do not receive secrets. The key would be empty and the action would fail with "No key"; skip forks with the
if:shown above. - Keep
permissions: contents: read. The action does not comment, push or create releases. - The key reaches the CLI only through the
NANOFLAGS_KEYenvironment variable; no input is interpolated into shell source. GitHub masks secrets in logs. - Pin the action to a commit SHA.
Code references
With scan-refs: true the action runs refs scan and uploads, per reference, the flag key, the file path, the line number and that line of source (up to 240 characters), replacing the references stored earlier for the repository. Leave it off if source lines must not leave the repository. Upload references from the default branch only, so the stored set reflects what is merged.
Recorded runs
Every scenarios run is recorded in NanoFlags with its source, the configuration checksum, the commit and the run URL, and each scenario's actual value and pass/fail result.
- For
source: draftthe checksum is the draft's; forsource: revisionit is the published revision's. - If an environment has require scenarios enabled, a publish is only accepted when every scenario in scope passed on the exact draft being published. Running the action with
source: draftrecords those passes; editing the draft afterwards requires a new run. - For a change, runs recorded with a CI key count, and so do dashboard runs by someone other than the change author and the people who edited its draft. The author's own dashboard runs are kept as evidence but do not satisfy the check. Editing a scenario's flag, context or expected value creates a new version; runs of an earlier definition no longer count.
- A run answers HTTP 200 even when scenarios fail; the CLI decides the exit code from the individual results.
Other CI systems
Run the CLI directly with the CI key in NANOFLAGS_KEY:
export NANOFLAGS_KEY="$NANOFLAGS_CI_KEY" # from your CI secret store
nanoflags scenarios run --source draft --commit "$COMMIT_SHA" --run-url "$BUILD_URL"Over HTTP
The same operations are available on the CI API.