Language Profiles
A profile is the only part of the template that knows what language a project is written in.
Everything else — governance, security policy, documentation, release pipeline, and the meaning of
make verify — is shared.
The lang-* contract
make/quality.mk, make/common.mk, and make/release.mk orchestrate; the profile implements. A
profile must define all nine targets, even if some are no-ops:
| Target | Must do | Called by |
|---|---|---|
lang-setup |
Create the environment, install dev dependencies | make setup |
lang-lint |
Lint, format-check, and type-check first-party source | make lint |
lang-format |
Auto-format and auto-fix | make format |
lang-test |
Fast unit tests, no privileges required | make test |
lang-test-integration |
Integration tests | make integration-test |
lang-fuzz |
Property-based / fuzz tests | make fuzz |
lang-audit |
Dependency vulnerability scan | make audit |
lang-build |
Produce artifacts into $(DIST_DIR) |
make build |
lang-clean |
Remove language-specific caches and artifacts | make clean |
make check-profiles verifies this contract for every profile in the repository, so a profile
cannot silently drift out of compliance.
Variables available to a profile fragment, set by the generated Makefile: PROJECT_NAME,
PROJECT_SHORT, PROJECT_SLUG, PROJECT_PKG, PROJECT_DIST, GITHUB_OWNER, VERSION,
SRC_DIRS, TEST_DIRS, SCRIPT_DIRS, and DIST_DIR.
What ships in each profile
python
pyproject.tomlwith hatchling, Ruff (includingflake8-banditsecurity rules), mypy, coverage, pytest markers, andbump-my-versionwired to every file that carries the version string.- Package skeleton with a thin CLI orchestrator, a smoke test suite, and Hypothesis fuzz targets.
fuzzing/conftest.pyregisteringdev/ci/ci-deepHypothesis profiles, so pull requests stay fast while the weekly scheduled run explores 10,000 examples.- CI: Ruff, mypy, ShellCheck, a 3.10–3.13 test matrix,
pip-audit, and a wheel smoke-install in a clean virtualenv — which catches packaging mistakes that an editable install hides.
node
- Strict
tsconfig.jsonwith every soundness flag enabled, plus a separate build config so tests are type-checked but not shipped. - Flat ESLint config using type-aware
strictTypeCheckedrules, with type-aware linting disabled for plain-JS config files. - Prettier scoped to source: Markdown is governed by
.markdownlint.yaml, and workflows are left alone. - Vitest with coverage; CI runs a Node 20/22 matrix and
npm audit.
rust
Cargo.tomlwithunsafe_code = "forbid",missing_docs, Clippypedantic, and warnings onunwrap/expect/panicin the crate lint table, plusoverflow-checks = truein the release profile — an integer overflow in production is a correctness bug, not a performance question.- Library plus binary layout, with proptest property tests.
- CI runs fmt, Clippy with
-D warnings, a stable/beta/MSRV matrix, andrustsec/audit-check.
generic
Every lang-* target is a documented no-op that announces itself. Use it for polyglot repositories
or as the starting point for a new profile.
Adding a profile
- Edit
template/go/profile.env— language name, Shields logo slug, minimum version, CodeQL language id, Dependabot ecosystem, linter name, andSKELETON_PATHS(the source and test directories that form the runnable example, skipped as a unit when the target already has its own source there). - Rename
make/generic.mktomake/go.mkand implement the nine targets. - Replace
.github/workflows/ci.ymlwith a real pipeline, and add the toolchain setup step torelease.yml. - Write
.gitignore.appendfor the language's build output. - Add a minimal source skeleton and a smoke test — a profile whose
make testfinds no tests is a profile that ships a green pipeline proving nothing. - Run
make check-profiles, then generate a scratch project and actually runmake lint test buildinside it.
Step 6 is not optional. Every profile in this repository was found to have at least one real bug
that only surfaced by running the generated project: a fuzz suite that collected zero tests, a Rust
crate name that did not match its package name, a TypeScript rootDir that excluded the tests it
was asked to check.