Skip to content
NanoFlags
Start free

Tooling

CI and GitHub Actions

Check every commit against your saved scenarios, record the result against the commit, and fail the job when a scenario fails. Optionally upload where each flag is used in code.

What runs in CI

The GitHub Action is a composite action around the CLI:

  1. 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.
  2. 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.
  3. 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

KeyCanCannotUse in CI?
CI nf_ci_…Run scenarios, upload code references, export definitions, read the published revisionPublish or change configuration; fetch SDK bundlesYes: the only key for CI
Admin nf_adm_…Everything a CI key can, plus publish environments that do not require a reviewed changePublish environments that require approval; fetch SDK bundlesNo. The action refuses admin keys
Server nf_srv_… / client nf_pub_…Fetch bundles, live updates, send telemetryAny 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

.github/workflows/flags.yml
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 only
  • pull_request runs the check on the pull request's code without exposing secrets to forks; permissions: contents: read is all the action needs.
  • Use source: draft to check what you are about to publish, or source: revision to check what is published now.

Action inputs and output

InputDefaultDescription
keyrequiredNanoFlags CI key. Pass a secret.
base-urlCLI defaultEdge URL (https://edge.nanoflags.io).
sourcedraftdraft or revision (the published revision).
scan-refsfalsetrue also uploads code references.
refs-dir.Directory scanned for references.
clinpx --yes @nanoflags/cli@0Command 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, not pull_request_target. pull_request_target runs 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_KEY environment 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: draft the checksum is the draft's; for source: revision it 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: draft records 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.
A passing run shows that the saved scenarios evaluated as expected on that configuration. It does not prove that the change is correct for scenarios you did not write.

Other CI systems

Run the CLI directly with the CI key in NANOFLAGS_KEY:

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