Skip to content

Infra: Build the pre-commit gate: eight toolchains, no root manifest, and staged-content correctness #472

Description

@Emmy123222

Summary

This repository has no git hooks of any kind. .husky/ does not exist, no package.json declares husky, lint-staged or commitlint, core.hooksPath is unset, and .git/hooks/ contains nothing but samples. Every check runs only after a push, so a contributor learns about a formatting failure or a broken import from a red CI run minutes later.

Installing husky is trivial. Making a pre-commit gate that is correct and fast in this repository is not, because there is no root manifest to hang it off and eight independent toolchains to route to.

Evidence

$ ls .husky                  → does not exist
$ git config core.hooksPath  → unset
$ ls .git/hooks | grep -v sample → (nothing)
$ ls package.json            → no root manifest

npm workspaces : backend  frontend  mobile  extension  shared
other          : contracts/Cargo.toml   scheduler/go.mod
config/YAML    : k8s/  helm/  .github/workflows/

Each npm workspace has its own lockfile and its own scripts; mobile and extension do not even share a test runner (jest vs vitest). There is no single command that lints "the repo".

Why this is hard

Staged content, not working-tree content. A file can be staged with further unstaged edits on top. Linting the working tree passes or fails on code that is not being committed, and auto-fixing it silently destroys unstaged work. The gate has to operate on the staged blobs, and restore the working tree exactly on every exit path including a crash or a SIGINT.

Routing. Staged paths must map to the right toolchain, and only the affected ones should run. Touching contracts/ must not run tsc; touching one workspace must not lint the other four. The mapping has to cope with files that belong to no toolchain and files that belong to two (shared/ is consumed by both frontend and mobile).

Missing toolchains. Most contributors will not have Rust and Go installed. The gate must degrade to a clear skip with a reason, never a confusing failure, and CI must still enforce what was skipped locally.

Speed. A pre-commit hook that takes 40 seconds gets bypassed with --no-verify and then it protects nothing. There is a real performance budget here and it drives the design: parallelism, per-toolchain incremental scoping, and caching.

Divergence. If the hook and CI implement the same checks twice they will drift apart. One of them will pass while the other fails, and contributors will stop trusting the hook.

Suggested approach

Add husky and a small root manifest that exists only to host developer tooling — it must not become a place where runtime dependencies accumulate, so document that boundary and consider enforcing it.

Write a router that takes the staged path list and produces a plan: which toolchains to invoke, with which file subsets, in what order, and what may run concurrently. Express the mapping in config rather than code so adding a workspace is a config edit.

Extract staged content safely. git stash --keep-index is the well-known approach and it is also the one that loses work when the hook dies partway; whichever mechanism is chosen, prove recovery under an interrupt.

Expose the same plan to CI so the hook and the workflow run one implementation. A --all mode that ignores staging is what CI invokes.

Acceptance criteria

  • Committing a change in one workspace runs only that workspace's checks, proven by a test.
  • Checks read staged content: a file staged clean with a broken unstaged edit on top commits successfully, and the unstaged edit survives untouched.
  • The working tree is restored on success, on failure, and on SIGINT during a check — each covered by a test.
  • A missing Rust or Go toolchain produces a named skip, not a failure, and the skip is listed in the hook's output.
  • The gate completes within a documented budget on a representative commit; the measurement is reproducible and recorded.
  • CI and the hook invoke the same planner, so a check cannot exist in one and not the other.
  • --no-verify usage is documented, and there is a policy decision recorded on whether CI re-runs everything regardless.
  • Fresh-clone bootstrap works on Linux, macOS and Windows, including CRLF checkouts.

Scope

Roughly 3,000–5,000 lines: the planner and its config schema, one adapter per toolchain, staged-content extraction with crash-safe restore, a concurrency scheduler, a reporter, and the fixture repositories and tests needed to prove the staging and interrupt behaviour.

Relevant files

  • .husky/ (new)
  • package.json (new, tooling-only root manifest)
  • scripts/ (planner and toolchain adapters)
  • .github/workflows/ci.yml

Part of a set of five issues covering git-hook tooling. husky itself is a thin hook runner — its own configuration is a handful of lines. The engineering lives in the tooling a hook invokes, which is what these issues specify.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: infraK8s, Helm, CI/CD, deploymentcomplexity: highSubstantial design/implementation work, not a quick fix

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions