On this page
ADR-0049: Every project is its own repository
Status: Accepted (WP-83). Specified in plan 14; implemented in projects/*/, templates/project-template/, scripts/export-project.sh, scripts/check-project-trees.py, scripts/check-template-drift.sh, mk/projects.mk and .github/workflows/projects.yml.
Context
ADR-0046 and plan 13 say that a
project lives in a repository of its own, connected through the GitHub App. The
first-party projects did not: the base image, nginx, Valkey and PostgreSQL were
directories of the platform repository with no .github/ and no schema copy. Their
scripts found the manifest schema by walking up into the platform repository, the
platform's workflows built, released (projects-release.yml, tags
<project>/v<version>-r<revision>) and rescanned (projects-rescan.yml) them, their
signing identity was the platform repository's, and the rule engine carried an
exemption (hosted_ci) so that their missing CI did not fail the scan. The platform
held them to a weaker standard than any maintainer's project, and none of them could
be handed to a maintainer as it was.
Decision
- A project is a complete repository. Nothing in it refers to a file outside it, and nothing outside it is needed to validate, build, test, scan, release or onboard it. The platform repository builds the platform; it does not build, release or rescan projects.
- The four first-party projects are projects like any other: repositories
commonlayer-org/base,commonlayer-org/nginx,commonlayer-org/valkey,commonlayer-org/postgresql. Until they exist their trees are kept underprojects/<name>/, each exactly the content its repository will have: the template's.github/(workflows,CODEOWNERS, Dependabot, pull request template), a copy of the schema, the shared scripts, tag patternv{version}-r{revision}, registry sourceghcr.io/commonlayer-org/<project>and signing identityhttps://github.com/commonlayer-org/<project>/.github/workflows/*@refs/tags/v*. - Every tree carries the template's workflows unchanged. Differences between projects
are expressed in
commonlayer.yaml(several charts, several version lines, no chart) and in hooks of the shared scripts undertests/; a workflow file may differ only when that is impossible, and is then listed in the project'sdocs/MAINTENANCE.mdand in the drift check's exceptions. Today none differs. - The base image is another project's release, used by digest. Before a base release
exists a build takes
BASE_IMAGE, or builds the base project's repository with the project's ownscripts/base-image.sh --build <checkout>; in CI the repository variableCL_BASE_REPOSITORYnames it. Releases always need the digest. - The schema is the project's copy (or
CL_SCHEMA); the search through parent directories is removed from the sharedscripts/lib.sh. - While the trees are here, the platform proves that each one stands alone: the
projectsworkflow exports each changed tree to a directory outside the checkout as a git repository (scripts/export-project.sh) and runs the project's own targets there;scripts/check-project-trees.pyfails on any path that leaves a tree or names the platform repository's layout; the drift check covers.github/and the schema copy.
Alternatives rejected
- Keep the projects in the platform repository and give them a
.github/that is never used. The trees would look standalone without being tested as such, and the platform's own workflows would still be what releases them. - One repository for all first-party projects. It would need project-prefixed tags and a signing identity shared by unrelated projects, exactly what the rule engine rejects for a maintainer's repository; and a maintainer could not be given one project without the others.
- Forked workflow files per project (PostgreSQL's several charts and majors, the base without a chart). Every difference would have to be kept in step with the template by hand and would be a scan finding; the manifest and the script hooks already express them.
- A git submodule or subtree per project. It keeps the projects inside the platform repository's history and tooling, which is what this decision removes.
Consequences
- Creating the four repositories and pushing the exported trees is the owner's step
(plan 14 §4). Until then nothing is released, and the trees, the
projectsworkflow,mk/projects.mkand the platform's local base fallback stay in this repository; they are removed afterwards. - Each project repository needs, once: the variable
CL_BASE_REPOSITORYuntil the base digest is set, theCODEOWNERSteam, code scanning, the GitHub App. - A release tag now names a version without a project prefix (
v1.30.6-r1), and the signatures of a project name its own repository. Nothing had been released under the old identity, so no published signature changes meaning. - Every project's
validate.ymlbuilds each supported version line in its own job and rebuilds weekly; the platform's weekly base rebuild is gone. These workflows have only been linted (actionlint) and their targets run locally in exported trees; they have not run on a runner. - The rule engine checks every tree with every rule, CI rules included; the
hosted_ciexemption is removed (backend part of WP-83).