Skip to main content

ADR-0015: Bootstrap dev environment and pre-commit hooks

  • Status: Accepted
  • Date: 2026-06-21
  • Deciders: Michel Gillet

Context

A2C-governed repositories must version shared pre-commit configuration (ADR-0001) and include mandatory a2c-pre-commit-hooks with check-changelog (ADR-0003). The method repository a2c-workflow dogfoods a fuller baseline: file-hygiene hooks, tab removal for Markdown/YAML, and gitlint on the commit-msg stage — installed locally via scripts/setup-dev.sh / scripts/setup-dev.ps1 after editable install and pre-commit install.

Until this ADR, a2c bootstrap for consumer repositories only scaffolded a minimal .pre-commit-config.yaml containing check-changelog. Operators still had to:

  • Manually extend the config with standard hygiene hooks and gitlint
  • pip install pre-commit (often globally or ad hoc)
  • Run pre-commit install and pre-commit install --hook-type commit-msg

That gap caused “hooks not installed”, “gitlint missing”, and inconsistent rails across newly adopted repos — especially for teams that expect a2c bootstrap to be a one-shot adoption step comparable to superbuild / method-repo onboarding.

Consumer repositories are not always Python products, but pre-commit and gitlint run in isolated hook environments; they only require a host Python interpreter to bootstrap a local .venv/ for the hook manager.

Decision

1. Standard consumer .pre-commit-config.yaml

a2c bootstrap writes a stack-agnostic .pre-commit-config.yaml aligned with the method repository baseline:

BlockPurpose
a2c-pre-commit-hooks @ tagcheck-changelog, check-web-sources
pre-commit-hookscase/merge conflict, YAML, EOF, mixed line endings, trailing whitespace
Lucas-C/pre-commit-hooksremove-tabs on *.md, *.mdc, *.yaml
gitlintConventional Commits on commit-msg stage

Ruff and other language-specific linters remain stack hooks — add via profiles or project ADRs, not the default bootstrap template.

Pin a2c-pre-commit-hooks by release tag (currently v0.3.0, same as method repo).

2. Automatic dev environment setup during bootstrap

After scaffolding config files, a2c bootstrap runs setup_dev_environment() (a2c_core.services.dev_setup):

  1. .venv/ — create at repository root when no active VIRTUAL_ENV and no existing .venv/
  2. pip install pre-commit>=4.0 into that venv (or active venv when bootstrap runs inside one)
  3. pre-commit install and pre-commit install --hook-type commit-msg when .git/ exists

Failures are warnings, not bootstrap hard failures — adoption still completes when Python is missing, venv creation fails, or the target is not yet a git repository.

3. Re-run scripts and gitignore

Bootstrap also scaffolds:

ArtifactRole
.gitignoreIgnores .venv/ (and common editor noise)
scripts/setup-dev.shRe-run venv + hook install (Unix / Git Bash)
scripts/setup-dev.ps1Re-run venv + hook install (Windows)

Clone workflows re-run scripts/setup-dev instead of remembering pip/pre-commit commands.

4. Relationship to method repository

ContextSetup path
a2c-workflow (method repo)scripts/setup-dev.* + editable product install — unchanged
Consumer repoa2c bootstrap auto-setup + scripts/setup-dev.* for re-runs

Consumer bootstrap does not install a2c-core editable unless the project is a Python product that chooses to do so separately.

5. Prerequisites and limits

  • Python 3.11+ on PATH (or active venv) for automatic hook install
  • Git repository for hook registration — git init before bootstrap, or run scripts/setup-dev after init
  • Hook environments download on first commit (pre-commit default); bootstrap only registers hooks
  • Private a2c-pre-commit-hooks access follows the same GitLab auth model as CI (ADR-0003)

Consequences

Positive

  • One-shot a2c bootstrap delivers the same pre-commit baseline operators expect from the method repo
  • gitlint is present by default — no separate install step
  • Local .venv/ isolates pre-commit from system Python
  • scripts/setup-dev gives a documented recovery path after clone

Negative

  • Bootstrap requires network for pip install pre-commit and later for first hook env creation
  • Non-git directories get config but not registered hooks until git init + scripts/setup-dev
  • Repositories bootstrapped before this ADR need a one-time config refresh and scripts/setup-dev (or re-bootstrap of config files)
  • Stack-specific hooks (Ruff, mypy) are still the project’s responsibility

References