Commit Graph
8 Commits
Author SHA1 Message Date
mathiasandClaude Opus 5 73c4f1c1de ci(deploy): refuse to patch a manifest with an empty IMAGE_TAG (infra#311)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Skipped
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
On 2026-08-25 a deploy job ran with an empty IMAGE_TAG, wrote
`image: localhost:5000/gitea-mcp:` into the infra repo and pushed it.
That is invalid YAML, so Flux failed the ENTIRE apps Kustomization --
every app stopped reconciling for about an hour, including three
unrelated deploys queued behind it.

This job's existing check could not catch it. It greps for
`image: <repo>:${IMAGE_TAG}` after the sed, and with IMAGE_TAG empty that
pattern matches the corrupted line itself, so the verification passes
because of the bug rather than despite it.

Asserting the input up front is the fix: an empty tag now fails the job
before anything is written, let alone committed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-25 17:25:24 +02:00
mathiasandClaude Opus 5 ba4adebd8d ci: re-sync build-image.sh — adds TARGET and BUILD_SECRETS (infra#309)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Skipped
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
Canonical gained two inputs so the repos still to migrate can adopt
without forking the script again: TARGET for multi-stage builds (cad,
agentsquad) and BUILD_SECRETS for buildkit secret mounts (agentsquad).

BUILD_SECRETS takes the SPEC only (`id=NAME,src=PATH`) -- the caller
writes the secret to PATH itself, so no secret value ever reaches this
script's argv or the CI log.

Unused here; this repo's copy just stays byte-identical, which is the
whole point. Written by `task ci:sync`, not by hand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011PL5XcG68SvQqz3vGVbWbf
2026-08-25 11:27:06 +02:00
mathias 650644ebe3 ci(cd): call the shared build-image script instead of inlining it (infra#309)
CD / Detect unsubstituted template (push) Successful in 1s
CD / Lint / Test / Vet (push) Skipped
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
Same change as template-go-agent. A template that carries the build LOGIC
manufactures a private fork of it in every generated repo; one that
carries a CALL manufactures nothing. That distinction is what made
infra#241 a nine-repo sprint plus two rediscoveries in the templates.

Invoked as `bash .gitea/build-image.sh` -- files written through the
Gitea API land 0644, and CI that depends on a file mode is a trap for
every repo generated from here.
2026-08-25 08:53:23 +00:00
mathias ef4e47bf00 ci: carry the shared build-image script (infra#309)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Skipped
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
Byte-identical copy of mathias/infra's ci-templates/build-image.sh, so
repos generated from this template inherit a managed copy of one file
rather than a private fork of the build logic.
2026-08-25 08:52:53 +00:00
mathias bada904c8d ci: build with buildctl instead of buildah (infra#241)
CD / Detect unsubstituted template (push) Successful in 0s
CD / Lint / Test / Vet (push) Skipped
CD / Build & Import (push) Skipped
CD / Deploy via GitOps (push) Skipped
Rootless buildah in gitea-runner's hardened securityContext (capabilities:
drop [ALL], allowPrivilegeEscalation: false) cannot remap the UID/GID range
newuidmap/newgidmap need on a fresh base-image pull, and the pod has no OCI
runtime at all. buildctl talks to the host's buildkitd over a socket, so the
privileged layer extraction happens on the host and the pod's securityContext
stops being in the picture. Same pattern as mathias/infra's segment-embedder.yml.

A template is the highest-leverage place to fix this: every repo generated from
here inherits its CI, so a buildah-based template does not merely carry the bug,
it manufactures new instances. The failure is latent — warm base-image layers
mask it — so a generated repo builds fine until its first genuinely cold pull,
which is precisely the situation a new repo is in.

Verification is PARTIAL here, and the limit is worth stating rather than
implying a green build. Running the exact command against this repo's real
context reaches step 8 and fails inside the Dockerfile:

    RUN templ generate && go build ... -o /out/app ./cmd/__PROJECT_NAME__
    error: failed to solve: ... exit code: 1

That failure is the template's own placeholder path, which cannot resolve on the
raw template — the same reason the guard job gates check/build/deploy off here
(is_template detects __MODULE_PATH__ in go.mod). What it does prove is that
buildctl resolved the frontend, the context and the Dockerfile and began
executing stages; every part of the buildctl integration worked, and only the
template's unsubstituted content did not.

template-go-agent's Dockerfile has no placeholder in its build path, so there the
same command produced a complete 6.8MB OCI archive. The first generated repo from
this template is where this one gets its end-to-end proof.

skopeo copy replaces `buildah push` — buildctl has no registry-push equivalent —
and runs twice to preserve the :sha and :latest tags.
2026-08-21 18:30:53 +02:00
mathiasandClaude Opus 4.8 8a22a28ab4 fix(template): parameterize scaffold with __PROJECT_NAME__/__MODULE_PATH__ (gitea-mcp#44)
CD / Lint / Test / Vet (push) Failing after 6s
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
template-go-web was seeded from the real `hostexecutor` project and never
parameterized: go.mod hardcoded `module gitea.d-ma.be/mathias/hostexecutor` and
`hostexecutor` appeared throughout (cmd dir, Dockerfile, Taskfile, CI, context
docs). create_project_from_template therefore substituted nothing and returned
a "no placeholders" partial_failure on the zero-config default path.

Replaced the full module path with __MODULE_PATH__ and the bare project name
with __PROJECT_NAME__ (incl. renaming cmd/hostexecutor → cmd/__PROJECT_NAME__),
matching the substitution the tool performs. Also drops the stale gitea.d-ma.be
host (the placeholder resolves to git.d-ma.be/<owner>/<name>).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 23:33:46 +02:00
mathias b2a87520b2 chore: drop environment: staging (no-op for solo homelab)
CD / Lint / Test / Vet (push) Failing after 3s
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
2026-05-05 08:51:20 +02:00
mathias a25120cd1d feat: initial template (Go + Templ + HTMX + CDN Tailwind)
CD / Lint / Test / Vet (push) Failing after 5s
CD / Build & Import (push) Has been skipped
CD / Deploy via GitOps (push) Has been skipped
2026-05-05 08:19:04 +02:00