Skip to content

Enterprise · Code references

Code references

Your CI tells FluxGate where each flag appears in code, so cleanup starts from a list of files and lines instead of a search.

Video coming soon

Code references

Before you start

  • Your install has the Business or Enterprise edition (entitlement code_references). Reading and deleting stored references works in every edition.
  • You can create a system client in the team that owns the flags System admin or as a Team Admin.
  • Your repositories build in GitHub Actions or GitLab CI, or another CI that can run a Linux or macOS binary.

Why code references

Flags pile up. A release flag reaches 100 %, and the if stays in the code for months. Each forgotten flag is a branch nobody tests, a key someone can still flip by mistake, and a line of targeting rules that edges keep in memory. To clean up, you need two facts side by side for every flag:

  1. Is it still evaluated? FluxGate already records this on each flag: when it was last evaluated, and how often in the last 7, 30 and 90 days.
  2. Where is it in the code? Code references add this answer.

With both, FluxGate can tell you which flags are safe to archive, which ones need a code change first, and which ones still matter.

How it works

  1. A scanner, the fluxgate code-refs scan command, runs in your CI on every push to the default branch.
  2. It asks FluxGate for the team's flag keys, archived flags included, and for the keys deleted in the last 90 days.
  3. It walks the checkout, finds every use of those keys, and classifies each one as an SDK call, a literal or an alias of a constant.
  4. It uploads one scan per repository and branch: file paths, line numbers, the kind of each match and a few redacted lines around it. It never sends whole files.
  5. FluxGate replaces that branch's earlier scan with the new one, and shows the result on the feature page, in the feature list, in Settings, Code references, and in the cleanup report.

The scan finds the repository, branch and commit from the CI variables of GitHub and GitLab, or from the checkout's .git folder. The repository name is the remote without scheme, credentials, port or .git: https://x-access-token:...@github.com/juniper-market/storefront.git becomes github.com/juniper-market/storefront. For github.com and gitlab.com the scan also sets a link template, so each line on the feature page links to the file.

What you see in FluxGate

On each flag

The flag page has a Code references card. It says, for example, "Referenced in 5 files in 2 repositories", lists each repository with its branch, commit and scan age, and each match with its kind. Show context opens the redacted lines around the match. Each path links to the line in your Git host.

Code references card on the express-checkout feature page: referenced in 5 files in 2 repositories; checkout-service with an SDK call in PaymentService.java line 15 and its context; storefront with a test literal, two alias references to EXPRESS_CHECKOUT, and literals in ExpressCheckout.tsx and keys.ts (opens full size in a new tab)
The Code references card of express-checkout. The Default branches and All branches buttons switch between the default branch of each repository and every scanned branch.

Code references on the feature page explains every part of the card, the repository settings and the feature list filter.

For the whole team

Settings, Code references lists the scanned repositories, their default branch, link template, last scan and coverage. Features, Cleanup report turns evaluations, references and coverage into one recommendation per flag: see The cleanup report.

Set it up

  1. Open System Clients under Connect and click Create System Client. Name it ci-code-refs.
  2. Under Token Scope, select Evaluate and Code references write, and clear the other scopes. Evaluate lets the scanner list the team's flag keys. Code references write lets it upload scans and delete scans of deleted branches. Neither is enough alone.
  3. Create the client and copy its token. It is shown once.
  4. Add the FluxGate CI template to each repository: GitHub Actions or GitLab CI.
  5. Push to the default branch. The job downloads the fluxgate CLI, checks it against SHA256SUMS, scans and uploads.
  6. Open a flag in FluxGate. The Code references card lists where the flag is used.
Create System Client form for ci-code-refs with the description GitHub Actions and GitLab CI code reference scans; in Token Scope, Evaluate and Code references write are selected (opens full size in a new tab)
The system client for CI scans needs exactly two scopes: Evaluate and Code references write.

Code references write is not a default scope, so select it on purpose. A token with only Evaluate cannot read stored code lines; reading them needs Code references write or Admin read.

Each upload replaces the earlier scan of that repository and branch. A repository whose default branch was not scanned for 7 days (the backend's coverage_days) shows Not scanned recently, so you know when the list may be out of date.

Try a scan by hand

Download the fluxgate CLI from Download binaries, then run it in a checkout with the system client token:

bash
export FLUXGATE_URL=https://flags.junipermarket.example/api/v1
export FLUXGATE_TOKEN=<ci-code-refs token>
fluxgate code-refs scan --dry-run

--dry-run prints what would be uploaded. Without it, the scan uploads and prints the server's answer:

json
{
  "branch": "main",
  "deletedKeys": ["beta-coupons"],
  "featuresReferenced": 5,
  "refCount": 12,
  "repositoryId": "c55b312e-aec2-432c-bba5-1afa9f5e419d",
  "unknownKeys": ["beta-coupons"]
}
  • refCount: references stored for this branch. featuresReferenced: flags of the team that the branch references.
  • unknownKeys: keys found in the code that name no flag of the team. A deleted flag's key is one of them.
  • deletedKeys: keys of flags deleted from the team in the last 90 days that the code still uses. The scan also prints 1 references to 1 deleted flags: beta-coupons.

fluxgate code-refs repos lists the repositories that were scanned, their branches and when each was last scanned.

All scan options

text
fluxgate code-refs scan [--dir .] [--repo NAME] [--branch NAME] [--commit SHA]
                        [--default-branch NAME] [--browse-url TEMPLATE]
                        [--context-lines 0..5] [--redact REGEX]... [--exclude GLOB]...
                        [--config .fluxgate/code-refs.toml] [--dry-run] [--strict]

The scan takes the repository, branch and commit from the flags first, then from CI variables (GITHUB_SERVER_URL and GITHUB_REPOSITORY, GITHUB_REF_NAME, GITHUB_SHA; CI_SERVER_HOST and CI_PROJECT_PATH, CI_COMMIT_REF_NAME, CI_COMMIT_SHA, CI_DEFAULT_BRANCH), then from the checkout's .git folder. For a host other than github.com or gitlab.com, pass a link template, for example --browse-url "https://git.junipermarket.example/shop/storefront/src/{commit}/{path}#L{line}". The template must use http or https and contain {path}; it may also use {commit}, {branch} and {line}.

What is stored

Per scan: repository name, link template, branch, commit, file path, line, match kind, test mark, the redacted context lines, who uploaded the scan, and counts. Not stored: file contents beyond the context lines, git history, author names.

On a self-hosted install, nothing leaves your network: the scanner talks only to your FluxGate backend. On a hosted install, paths and context lines leave your network; send no code at all with --context-lines 0, or set max_context_lines = 0 on the backend. See What the scanner finds.

Backend settings

Optional [code_refs] section in the backend config.toml:

KeyDefaultMeaning
max_context_lines2Lines kept above and below a match, at most 5. 0 stores no code
max_upload_bytes10485760 (10 MiB)Size limit of an upload, after gzip decoding. Larger uploads get 413 payload_too_large
max_refs_per_upload50000References in one upload
coverage_days7A repository whose default branch was not scanned for this many days counts as not covered
branch_retention_days30A daily job deletes scans of non-default branches older than this

After a downgrade

WhatAfter a downgrade to FreeIn ReadOnly
UploadsRefused with 403 license_required. The scanner prints a warning and exits 0, so CI keeps passing (--strict exits 4)Refused with 403 license_read_only, same scanner behavior
Stored referencesReadable on the feature page, with their scan ageReadable
CoverageRepositories stop being covered after coverage_days, so the cleanup report says Unknown instead of ArchiveSame
Deleting repositories and branchesAllowedRefused, like other team writes
Repository settings403 license_required403 license_read_only
Cleanup report, deleted keys, removal checklistWorkWork

Next

See everything the feature page shows: Code references on the feature page.