Skip to content

feat(cli): add --fail-on grade option for configurable CI gate threshold#73

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/nice-mendel-mmzyu8
Open

feat(cli): add --fail-on grade option for configurable CI gate threshold#73
dmchaledev wants to merge 1 commit into
mainfrom
claude/nice-mendel-mmzyu8

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Summary

  • Adds --fail-on <grade> CLI option so teams can set their own CI gate threshold instead of the hardcoded D/F default
  • Fixes URL positional-argument detection to use a Set of known flag values (more robust than the previous string-equality check against timeoutMs)
  • Updates --help output and examples to document the new flag

Motivation

The CLI's exit-code gate is its primary CI use case (per README):

security-headers https://staging.example.com || echo "Gate failed"

But the failure threshold was hardcoded to D or F (cli.ts line 95):

if (report.grade === 'D' || report.grade === 'F') process.exit(1);

Teams that have already achieved a B or C grade and want to enforce "must not regress below B" have no way to do that today. With this change:

# Fail the pipeline if the site drops below a B
security-headers https://staging.example.com --fail-on B

# Useful in a GitHub Actions step
- run: npx @hailbytes/security-headers ${{ env.SITE_URL }} --fail-on C

The default behavior (exit 1 on D or F) is unchanged for backward compatibility.

How it works

Grades are ordered best-to-worst as ['A+', 'A', 'B', 'C', 'D', 'F']. The CLI exits 1 when GRADE_ORDER.indexOf(report.grade) >= GRADE_ORDER.indexOf(threshold). An invalid grade value produces a clear error message and exits 1 immediately.

Test plan

  • npm run typecheck passes
  • All 85 existing tests pass (npm test)
  • --fail-on B exits 1 for a C-grade report and exits 0 for a B-grade report (manually verified via analyzeHeaders)
  • Invalid --fail-on X prints an error and exits 1
  • Default behavior (no --fail-on) unchanged: exits 1 only on D/F

🤖 Generated with Claude Code

https://claude.ai/code/session_01TLaWreutDFMwM1cLViGzty


Generated by Claude Code

The exit-code gate was hardcoded to D/F grades, making it impossible for
teams to enforce stricter standards (e.g. "fail on C or worse") or opt
into a softer threshold via a single flag.

--fail-on accepts any valid grade (A+, A, B, C, D, F) and exits 1 when
the report grade is at or below that level. Default behavior (fail on D)
is unchanged.

Also fixes URL positional-argument detection to use a Set of known flag
values rather than a string-equality check against the timeout number,
which was fragile when --timeout and --fail-on were both present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TLaWreutDFMwM1cLViGzty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants