Repository navigation
v3.27.0: every CI gate can fail the job, baseline staleness in CI, gate results in MCP
·
646 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Features
- An armed gate reports its result in the JSON output. A run that arms a gate gets
gate_outcomes, an object keyed by gate name. Each entry hasstatus(pass,warn,failorskipped) andenforced. Where a comparison happened, you also getobserved,thresholdandthreshold_label. Only the gates the run armed appear in the object. Adead-coderun can exit 1 on the default severity rules with no object at all. The key set is open, and a gate name you do not recognise means "some gate". (#2680, #2681, #2683, #2685) - The JSON output reports a stale baseline, and CI can fail on it. 3.26.0 printed the stale-baseline warning and
--fail-on-stale-baselineon stderr only, and--quietremoves that output. The GitHub Action and the GitLab template both run with--quiet.dead-code/check, the bare run,dupesandhealthreport onebaseline_stalenessobject, in grouped output too. It holds the entry counts,change_scoped, the warning result andgate_trips. Both integrations show a stale baseline as a warning and in the job summary. On a pull request the main run covers changed files only. The integrations therefore re-read the baseline once over the whole project. That re-read took 0.11s with a cache and 0.24s with type-aware analysis on an 870-file TypeScript project. Whether a stale baseline fails the job depends on the newfail-on-stale-baselineinput and theFALLOW_FAIL_ON_STALE_BASELINEvariable. The pull-request comment and the merge-request note do not include the warning yet. Thanks @cloud-walker for the report, which traced the gap through the action scripts. (#2673) min-scoreis an Action input and a GitLab variable. Before this release you could set it only throughargs:/FALLOW_ARGS.--min-scoreimplies--score, so the integrations add--complexitywhen no health section input is set. That keeps the annotations, the SARIF upload and the pull-request comment populated. The CLI turns its own findings rule off for such a run, and the integrations do the same, which leaves the decision to the score.min-scoreandmin-severityapply tocommand: healthand exit 2 elsewhere. (#2682)- A run that analyzed no source file reports it. The run prints a warning and passes by default.
fail-on-empty-analysis: true(FALLOW_FAIL_ON_EMPTY_ANALYSISon GitLab) makes it fail. The JSON output has ano-source-files-analyzeddiagnostic and the newworkspace_diagnostics[].degrades_analysisfield. When findings cover less than the whole project, the integrations print one combined warning with the diagnostic kinds and their counts. (#2686) - An MCP tool result reports what each gate concluded. The tools run the CLI with
--quietand turn exit 1 into a successful result, which hid every gate result from the agent. The rootwarningsarray reports a stale baseline together with the re-save remedy. It also lists every gate that concludedfailorwarn, with its numbers. A run that covered less than the whole project gets one entry too. The subprocess, Code Mode and typed routes all do this.find_dupeswith athresholdtakes the route that can evaluate it. A response with nothing to report is unchanged. (#2676) fallow report --fromshows the gate results in CI. It prints them as a notice annotation and as a line in the job summary, the pull-request comment and the merge-request note. The line is informational and never fails a step. (#2684)
Changed
security-gatefails the job independently offail-on-issues. In both integrations the security branch sat inside thefail-on-issuesconditional, andfail-on-issues: falsemeant that branch never ran.- The Action's inline
Check thresholdstep is gone. Its logic moved into the analyze step, and thegates-failedoutput names the gates that decided the result. - In combined mode the duplication threshold does not fail the run, and the JSON output has
enforced: falsefor it. Standalonedupesexits 1 as before. The default GitLab job forwards the threshold in combined mode, and that pipeline prints a warning with the reason. --fail-on-stale-baselinechanges one field in the output. That field isgate_outcomes["stale-baseline"].enforced. Nothing inbaseline_stalenessdepends on the flag, not evengate_trips.health --report-onlysetsenforced: falseon every gate it evaluated.- One stale baseline can produce two lines for a pull request. The Action's warning comes from its whole-project re-read. The gate line from
fallow reportdescribes the scoped run, where the gate fails nothing. - No
schema_versionin the JSON output changed.gate_outcomesandworkspace_diagnostics[].degrades_analysisare additive and optional.
Bug fixes
fail-on-regression,threshold,min-severityand the security gate fail the job. All four were documented as gates. Each one reported its result on stderr, which--quietremoves. Both integrations also drop the exit code when stdout parses as JSON. The integrations readgate_outcomesinstead. A gate fails the build when itsstatusisfailandenforcedis true, and only when the input that owns it was set. A flag passed throughargs:prints a warning and cannot overridefail-on-issues: false. (#2680, #2681, #2683, #2685)- Every failing gate is reported before the step exits. Both integrations stopped at the first failure, and a run with a tripped gate and findings reported one of the two. They print every reason, write the outputs and artifacts, and exit once. The security gate keeps exit 8, which outranks the generic 1.
- The duplication
thresholdapplies to the bare command on GitHub. The Action forwarded it oncommand: dupesonly.
Upgrade notes
- If you set
fail-on-regression,threshold,min-severityor a security gate and relied on the job passing, expect failures. Withsecurity-gateandfail-on-issues: false, unsetsecurity-gateto keep the old behaviour. - Remove
--fail-on-stale-baselinefromargs/FALLOW_ARGS, delete any separate unscoped gate step added as a workaround, and set thefail-on-stale-baselineinput. fail-on-stale-baselinewith nobaselineset, or onfixorsecurity, exits 2.- Do not point
baselineandsave-baselineat the same file. The run saves before it compares, and such a baseline can never have a stale entry. The integrations warn about it. - If a workflow references the
Check thresholdstep by name (continue-on-error,steps.*.outcome), point it at the analyze step and thegates-failedoutput. - With a pinned fallow older than 3.27.0, the integrations use the fields that version writes. A gate with no field in that version passes, and the integrations print one warning.
- If you import
npm/fallow/typesin TypeScript,HealthBaselineStalenessis nowBaselineStaleness. The old name remains as a deprecated alias.
Full Changelog: v3.26.0...v3.27.0