Keep each submodule's git config out of the build context (closes #75)
check / check (push) Successful in 28s

The canonical `.dockerignore` kept out `.git/config`, which can hold a credential, but not the `config` in each submodule's git directory under `.git/modules/`, nested again for a submodule's own submodules. It now also lists `.git/modules/**/config`, with one sentence in the comment above; `prompts/REPO_POLICIES.md` and both checklists say so in the same words.

The pattern stays under `.git/modules/` because `.git/**/config` would also drop a branch or tag named `config`, which `git describe` may need.

Known gap: a submodule whose name has a `config` path segment loses its whole git directory, so Go's version stamping fails the build loudly; tracked separately.

Model: opus-5-5
This commit was merged in pull request #85.
This commit is contained in:
2026-10-04 05:31:51 +02:00
parent dcc0ba0b66
commit 5de98c404e
5 changed files with 67 additions and 54 deletions
+19 -18
View File
@@ -1,6 +1,6 @@
---
title: New Repo Checklist
last_modified: 2026-10-03
last_modified: 2026-10-04
---
Use this checklist when creating a new repository from scratch. Follow the steps
@@ -68,23 +68,24 @@ Template files can be fetched from:
will run them in subdirectories, `services/api/.claude/` needs its own
anchored entry.
- If the image embeds a version in a binary: `.dockerignore` lets `.git`
into the build context. It keeps out `.git/config`, which `git describe`
does not need and which can hold a credential: a password in a remote URL,
or the token the CI checkout step stores there. The stage that compiles
has `git` (the Debian Go image has it; an alpine one needs
`apk add --no-cache git`) and takes the version from the `VERSION` build
argument when one is given, otherwise from `git describe --tags --always`.
That gives the tag on a tagged commit; on a later commit, the tag, the
number of commits since it and the short commit (`v1.2.3-4-gabc1234`); and
the short commit when no tag is reachable. The stage that compiles also
marks its working directory safe for git
(`git config --system --add safe.directory /src`): a context sent as a tar
stream keeps the sender's file owners, and git refuses a checkout owned by
another user, so the version would come out empty. `ARG VERSION` has no
default, and the build fails if the context carries `.git` and the version
still comes out empty, `dev` or `unknown`. A plain `docker build .` with
no build arguments must succeed; a Dockerfile that refuses an empty build
argument drops that refusal and keeps the argument.
into the build context. It keeps out `.git/config` and each submodule's
`config` under `.git/modules/` at any depth (`.git/modules/**/config`),
which `git describe` does not need and which can hold a credential: a
password in a remote URL, or the token the CI checkout step stores there.
The stage that compiles has `git` (the Debian Go image has it; an alpine
one needs `apk add --no-cache git`) and takes the version from the
`VERSION` build argument when one is given, otherwise from
`git describe --tags --always`. That gives the tag on a tagged commit; on
a later commit, the tag, the number of commits since it and the short
commit (`v1.2.3-4-gabc1234`); and the short commit when no tag is
reachable. The stage that compiles also marks its working directory safe
for git (`git config --system --add safe.directory /src`): a context sent
as a tar stream keeps the sender's file owners, and git refuses a checkout
owned by another user, so the version would come out empty. `ARG VERSION`
has no default, and the build fails if the context carries `.git` and the
version still comes out empty, `dev` or `unknown`. A plain
`docker build .` with no build arguments must succeed; a Dockerfile that
refuses an empty build argument drops that refusal and keeps the argument.
- The Dockerfile carries a `lint` phase and a `test` phase, each invoking
its tool directly rather than through `make` or `script/`, and the final
stage carries a `COPY --from=` of a harmless file from each so the image