Skip to content

feat(remediation): add auto-remediation for actions-pinned, npm-ci-required, harden-runner-required, readme-exists - #16

Merged
franzramadhan merged 4 commits into
mainfrom
feat/auto-remediation/1
Aug 5, 2026
Merged

feat(remediation): add auto-remediation for actions-pinned, npm-ci-required, harden-runner-required, readme-exists#16
franzramadhan merged 4 commits into
mainfrom
feat/auto-remediation/1

Conversation

@franzramadhan

Copy link
Copy Markdown
Contributor

Summary

Compliance findings are useful but still require a human to go make the fix in every repo. For rules where the fix is a mechanical, deterministic file edit, git-cascade can now open (and keep upserting) a pull request that applies it automatically instead of only reporting the finding.

  • New remediation: config block (enabled master switch + auto_remediation default) and a per-rule auto_remediation override (rule-level always wins over the block default).
  • New internal/remediation package mirrors the existing Checker registry pattern: each fixable rule registers a Remediator; the engine dispatches failing results to it and opens/updates a PR via new internal/github git-write helpers (branch create, blob/tree/commit, PR upsert — never a direct commit to the default branch).
  • Remediation requires its own --remediate-* / GIT_CASCADE_REMEDIATE_* credentials with no fallback to scan/notify tokens, since it writes directly to scanned repositories.
  • Four rules implemented: actions-pinned (pin tag → resolved SHA), npm-ci-required (lock bare npm/pnpm/yarn installs, skipping compound commands and dependency-adding installs it can't rewrite safely), harden-runner-required (insert step-security/harden-runner as each job's first step), readme-exists (add a minimal README.md stub).
  • Shared detection logic extracted from the affected checkers (FindUnpinnedActions, FindNodeInstallViolations, FindJobsMissingHardenRunner) so checker and remediator never drift — existing checker tests pass unchanged, confirming no behavior change.
  • README and example configs updated with the new config block, CLI flags/env vars, required permissions, and a table of implemented vs. high-confidence-but-unimplemented vs. excluded-as-too-risky rules.

Test plan

  • go build ./...
  • go vet ./...
  • go test -race -coverprofile=coverage.out -covermode=atomic ./... (matches CI)
  • New tests cover: config precedence/parsing, all internal/github/write.go git operations (branch create/no-op, commit create/no-op, PR create/upsert/labeling), and each of the four fixers end-to-end (happy path + a safe-skip case each)

🤖 Generated with Claude Code

franzramadhan and others added 2 commits August 4, 2026 12:16
…quired, harden-runner-required, and readme-exists

Compliance findings are useful but still require a human to go make the
fix in every repo. For rules where the fix is a mechanical, deterministic
file edit, git-cascade can now open (and keep upserting) a pull request
that applies it automatically instead of only reporting the finding.

- New `remediation:` config block (global enable + default) and per-rule
  `auto_remediation` override (rule-level always wins).
- New internal/remediation package mirrors the existing Checker registry
  pattern: each fixable rule registers a Remediator; the engine dispatches
  failing results to it and opens/updates a PR via new internal/github
  git-write helpers (branch, blob/tree/commit, PR upsert).
- Remediation requires its own --remediate-*/GIT_CASCADE_REMEDIATE_* creds
  with no fallback to scan/notify tokens, since it writes to scanned repos.
- Shared detection logic extracted from the affected checkers
  (FindUnpinnedActions, FindNodeInstallViolations,
  FindJobsMissingHardenRunner) so checker and remediator never drift.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.27273% with 78 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.16%. Comparing base (15c7e99) to head (71f3e00).

Files with missing lines Patch % Lines
cmd/git-cascade/cmd/scan.go 51.21% 20 Missing ⚠️
internal/remediation/fixes/actions_pinned.go 73.33% 8 Missing and 8 partials ⚠️
internal/remediation/fixes/npm_ci_required.go 78.57% 9 Missing and 6 partials ⚠️
...ternal/remediation/fixes/harden_runner_required.go 81.35% 5 Missing and 6 partials ⚠️
internal/remediation/engine.go 82.75% 5 Missing and 5 partials ⚠️
internal/compliance/checks/actions_pinned.go 80.95% 2 Missing and 2 partials ⚠️
internal/compliance/configloader.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #16      +/-   ##
==========================================
+ Coverage   75.42%   76.16%   +0.73%     
==========================================
  Files          34       41       +7     
  Lines        2739     3151     +412     
==========================================
+ Hits         2066     2400     +334     
- Misses        564      616      +52     
- Partials      109      135      +26     
Flag Coverage Δ
unittests 76.16% <82.27%> (+0.73%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

franzramadhan and others added 2 commits August 4, 2026 12:24
…fault

remediation.enabled (master switch) and remediation.auto_remediation
(default value applied when a rule doesn't set its own) overlapped
awkwardly and were easy to confuse. Collapse to a single enabled gate;
each rule now opts in individually via its own auto_remediation field
(defaults false), so a newly registered fixer never goes live silently
just because remediation as a whole was already turned on.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add tests for resolveRemediateCredentials (was 0%), the full
remediateOne happy/error paths (branch create, commit, PR open) via a
fake GitHub server, error branches in internal/github/write.go
(non-404 GetRef, CreateRef/CreateTree/CreateCommit/UpdateRef/List/
Create/label failures), and a direct in-package test for
FindNodeInstallViolations so it counts toward the checks package's
own coverage instead of only the fixes package's.

Project coverage 73.6% -> 76.3% (above main's pre-PR 75.4% baseline).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@franzramadhan
franzramadhan requested a review from pyshx August 4, 2026 13:53
@franzramadhan
franzramadhan merged commit bddbe1a into main Aug 5, 2026
1 check passed
@franzramadhan
franzramadhan deleted the feat/auto-remediation/1 branch August 5, 2026 13:44
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