lint: per-surface architecture — CI action wrappers, language-only hook, VS Code docker :latest - #276
Merged
Conversation
Local lint parity so a commit never surprises the maintainer with a CI-only failure (the gap that let a mis-ended codecov.yml slip to CI): - catalog/snippets/husky/pre-commit runs editorconfig-checker (line endings), actionlint, markdownlint, and cspell via Docker - images present-only so it never false-blocks; CI enforces regardless. - vscode-tasks.json gains a language-agnostic Lint group that mirrors CI and warms the hook's images. - AGENTS.md codifies the three-surface parity (CI / husky / VS Code) and adds the editorconfig-checker + cspell invocations. - Pin the LF husky snippet in .editorconfig and .gitattributes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a Husky pre-commit snippet and VS Code lint tasks to keep local linting aligned with the repo's CI lint job, and documents the intended three-surface lint parity in AGENTS.md.
Changes:
- Add a reference
catalog/snippets/husky/pre-commithook that runs the CI-equivalent Docker linters when images are already present locally. - Add a language-agnostic VS Code "Lint" task set in
catalog/snippets/configs/vscode-tasks.jsonto run (and warm) the same linters. - Pin the new shebang snippet to LF via
.editorconfigand.gitattributes, and document the parity + local invocations inAGENTS.md.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| catalog/snippets/husky/README.md | Documents the Husky snippet purpose and LF pinning guidance. |
| catalog/snippets/husky/pre-commit | Implements the reference pre-commit hook that runs Docker-based linting with skip behavior when unavailable. |
| catalog/snippets/configs/vscode-tasks.json | Adds VS Code tasks to run the same lint suite locally and warm images for the hook. |
| AGENTS.md | Updates governance docs to codify CI/hook/VS Code lint parity and adds local invocations for the new linters. |
| .gitattributes | Pins the new extensionless pre-commit snippet to LF to prevent shebang breakage. |
| .editorconfig | Pins the new extensionless pre-commit snippet to LF for editors. |
…g + linkless README Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…blings) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…to README+HISTORY, reword Match CI exactly: editorconfig-checker uses the same pinned digest CI runs; cspell checks README.md + HISTORY.md like the CI step (not all Markdown). Reword to 'fleet-standard lint set' - a repo's CI may run a subset. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…match template CI) The template's CI lint runs all four linters as digest-pinned docker images over all Markdown; the hook and VS Code tasks now match exactly. Guard dotnet husky run so a non-.NET or dotnet-less environment doesn't block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match the summary-plus-bullets style used in the workflow headers instead of the prose blob, and drop the codecov.yml example from the line-endings comment (the comment already states the what). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dependabot does not update image digests in workflow run: steps (only uses: refs and Dockerfile FROM), so pinning these four linters is a manual chore that drifts from the always-latest editor extensions. Run them at :latest across CI, the hook, and the VS Code tasks so the surfaces stay in lockstep, and catch a new linter rule early rather than never. - test-pull-request.yml, husky/pre-commit, vscode-tasks.json: pin -> :latest. - husky/pre-commit: also run markdownlint/cspell when cspell.json or .markdownlint-cli2.jsonc is staged, so a lint-config-only change is checked locally instead of surfacing as a CI-only failure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…VS Code docker Move to the tool that fits each surface instead of one Docker invocation on all three. Resolves the growing complexity of the hook's Docker lint logic. - CI (test-pull-request.yml): markdownlint, cspell, and actionlint run as pinned action wrappers (Dependabot bumps the SHA); editorconfig-checker stays Docker :latest since it has no action. This is the authoritative, reproducible gate. - Hook (husky/pre-commit): language formatting and style only (CSharpier + dotnet format, or ruff). No Docker, no doc linters, so it stays fast and simple. - VS Code tasks: the full doc-lint set via Docker :latest, on demand. - AGENTS.md and the husky README: document the per-surface split. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The hook no longer runs the Docker linters, so the tasks are the local doc-lint surface, not an image-warmer for the hook. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…on markdownlint example - editorconfig-checker/action-editorconfig-checker exists and is maintained, so CI runs all four linters as pinned action wrappers (my earlier no-action claim was wrong). - husky/pre-commit: header comment back to one line. - AGENTS.md: add --workdir to the markdownlint example for consistency with the others. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- husky/pre-commit: use an if block instead of 'command -v dotnet && ...'. As the last line, the && form propagated command -v's non-zero exit and aborted the commit when dotnet was absent. The if form exits 0 when dotnet is missing and still propagates a real dotnet husky run failure. - vscode-tasks.json: rephrase the Lint-group comment so neither line wraps mid-sentence. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The snippet is copied into repos that do not ship task-runner.json until Husky.Net creates it, so name the tool rather than the implementation file. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adopts one lint architecture across the fleet, using the tool that fits each surface instead of the same Docker invocation on all three (which made the hook script complex).
CI (authoritative, reproducible) —
test-pull-request.ymlDavidAnson/markdownlint-cli2-action,streetsidesoftware/cspell-action,raven-actions/actionlint), which Dependabot bumps. editorconfig-checker also runs via its action wrapper (all four CI linters are pinned actions).Git hook (fast, native) —
catalog/snippets/husky/pre-commitdotnet format, or ruff). No Docker, no doc linters. The snippet drops from ~40 lines to ~9.VS Code tasks (on-demand local full lint) —
catalog/snippets/configs/vscode-tasks.json:latest.Docs — AGENTS.md lint section + husky README rewritten to describe the per-surface split.
Rationale: Dependabot cannot bump image digests in workflow
run:steps, so docker-run linters can't be kept current automatically — action wrappers can, so CI uses them. The hook is kept to fast native language checks; the heavier doc linters move to CI (enforced) and VS Code tasks (opt-in local). Utilities already follows the CI-actions + language-hook shape.All linters pass locally (markdownlint, cspell, actionlint, editorconfig-checker).
🤖 Generated with Claude Code