build(security): add actionlint pre-commit hook for workflow files (#88) #91
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!91
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "88-actionlint-prehook"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #88. Sister to #89 (CI-side enforcement, still open).
What this does
Adds an
actionlintentry tolefthook.yml'spre-commit:block, mirroring the shape of the existinggitleakshook:globscopes the hook to workflow files only — commits that don't touch.forgejo/workflows/skip this hook entirely (gitleaks still runs).{staged_files}template limits the lint to just the matching staged files; editing one workflow doesn't re-lint the others.actionlintisn't onPATH, with abrew install actionlintpointer and a reference to README "Requirements".README updated alongside:
LEFTHOOK_EXCLUDE=actionlintskip pattern.Test plan
Verified locally with two scenarios:
git add README.md lefthook.ymlthenlefthook run pre-commitgit add .forgejo/workflows/broken.yml(with${{ github.no_such_context }}) thenlefthook run pre-commitproperty "no_such_context" is not defined in object type {action: string; ...}lefthook validatereports the config is well-formed.Coordination with #89
This PR enforces actionlint locally. Contributors without
actionlintinstalled, or usinggit commit --no-verify, can still push workflow regressions; #89 closes that gap by adding the same check to PR CI. Local hook first because it gives fast feedback without burning CI time; CI second to enforce the contract.Note: untracked private key in the repo root
Heads up —
forgejo-signing-key(private) andforgejo-signing-key.pubare sitting in the project root from the merge-commit-signing setup earlier. Not staged here, but worthshred -u forgejo-signing-key && rm forgejo-signing-key.pubonce they're copied to the Forgejo host. Untracked private keys at a repo root are one accidentalgit add .away from leaking.Mirrors the gitleaks hook's shape: - `glob: .forgejo/workflows/*.yml` scopes the hook so it only runs when workflow files are staged. - `{staged_files}` template limits the lint to just those files. - Fails closed if `actionlint` isn't on PATH, with a brew-install pointer. Tested locally: a deliberately broken workflow with `${{ github.no_such_context }}` fails the hook with a precise schema error citing line + column. A commit that doesn't touch any workflow file skips the hook entirely (gitleaks still runs). README "Requirements" picks up the new dependency alongside gitleaks; Setup explains both hooks and the `LEFTHOOK_EXCLUDE=actionlint` skip shape for the rare one-off bypass. Closes #88. CI-side enforcement tracked separately as #89. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>