Symptom (mathias/openbanking-api, born 2026-09-03 via gitea-mcp create_project_from_template): run 5277 reported success, but jobs Lint / Test / Vet, Build & Import, Deploy via GitOps were all skipped. No image ever reached the registry; the pod sat in ImagePullBackOff.
Cause:.gitea/workflows/cd.yml guard step reads
if grep -q '__MODULE_PATH__' go.mod; then
Both scaffolders (gitea-mcp's create_project_from_template and local-dev's scripts/new-project.sh) substitute __MODULE_PATH__ in every file, so the generated repo's guard becomes grep -q 'git.d-ma.be/mathias/<name>' go.mod — which matches forever. The comment above the step describes exactly this failure (harg-bygglov-go#8), but the placeholder in the grep is itself substituted.
Fix in the template: split the token so the shell string is unchanged but the substitution engine has nothing to match:
if grep -q '__MODULE''_PATH__' go.mod; then
Same for any other guard that greps __PROJECT_NAME__. Verified in openbanking-api commit "ci: make the template guard immune to placeholder substitution".
Also: audit repos generated since the guard was introduced — any of them with an all-skipped green run has never actually been built by CI.
**Risk:** LOW (CI config)
**Symptom** (mathias/openbanking-api, born 2026-09-03 via gitea-mcp `create_project_from_template`): run 5277 reported `success`, but jobs `Lint / Test / Vet`, `Build & Import`, `Deploy via GitOps` were all `skipped`. No image ever reached the registry; the pod sat in ImagePullBackOff.
**Cause:** `.gitea/workflows/cd.yml` guard step reads
```
if grep -q '__MODULE_PATH__' go.mod; then
```
Both scaffolders (gitea-mcp's create_project_from_template and local-dev's `scripts/new-project.sh`) substitute `__MODULE_PATH__` in **every** file, so the generated repo's guard becomes `grep -q 'git.d-ma.be/mathias/<name>' go.mod` — which matches forever. The comment above the step describes exactly this failure (harg-bygglov-go#8), but the placeholder in the grep is itself substituted.
**Fix in the template:** split the token so the shell string is unchanged but the substitution engine has nothing to match:
```
if grep -q '__MODULE''_PATH__' go.mod; then
```
Same for any other guard that greps `__PROJECT_NAME__`. Verified in openbanking-api commit "ci: make the template guard immune to placeholder substitution".
**Also:** audit repos generated since the guard was introduced — any of them with an all-skipped green run has never actually been built by CI.
Fixed in b9bbbae (PR #11, v0.2.0), verified 2026-09-17. Auto-closed by the merge; evidence here.
Same root cause as #9 and fixed by the same commit — an explicitly tied pair rather than two separate fixes.
Your diagnosis was exact, including the detail that made this one worse than the first: the broken line sat directly under a comment describing the failure mode. That is the part that decided the shape of the fix. A guard living inline in a workflow step can only be reviewed by reading, so the comment was doing the job a test should have been doing — and a comment cannot fail.
So the detection moved to scripts/is-template.sh with scripts/tests/is-template_test.sh, which substitutes a copy of the guard and asserts it still answers correctly. Both shipped versions fail that test.
One deviation from your proposed fix. You suggested splitting the token so the substitution engine has nothing to match:
if grep -q '__MODULE''_PATH__' go.mod; then
That works, but it is invisible: it reads like a typo and the next person tidying the file closes the bug again. Shipped the regex form instead — it matches the shape of a placeholder, so there is no complete token to rewrite, and it additionally catches leftovers the scaffolders know nothing about. A half-substituted tree is not a working repo either.
Verified against a fully substituted child rather than by inspection:
guard in child -> false (CI runs)
guard in template -> true (template still skips its own build)
suite, both states -> 8 passed, 0 failed
Your closing note — audit repos generated since the guard was introduced — is not covered by this and is the part with live consequences: any of them showing an all-skipped green run has never been built by CI. openbanking-api is known; the rest are not. Not filed as its own issue yet because the right scope is an estate-wide sweep rather than a template change, and that belongs with whoever picks up the next backlog pass.
**Fixed in `b9bbbae` (PR #11, v0.2.0), verified 2026-09-17.** Auto-closed by the merge; evidence here.
Same root cause as #9 and fixed by the same commit — an explicitly tied pair rather than two separate fixes.
Your diagnosis was exact, including the detail that made this one worse than the first: the broken line sat **directly under a comment describing the failure mode**. That is the part that decided the shape of the fix. A guard living inline in a workflow step can only be reviewed by reading, so the comment was doing the job a test should have been doing — and a comment cannot fail.
So the detection moved to `scripts/is-template.sh` with `scripts/tests/is-template_test.sh`, which substitutes a copy of the guard and asserts it still answers correctly. Both shipped versions fail that test.
**One deviation from your proposed fix.** You suggested splitting the token so the substitution engine has nothing to match:
```
if grep -q '__MODULE''_PATH__' go.mod; then
```
That works, but it is invisible: it reads like a typo and the next person tidying the file closes the bug again. Shipped the regex form instead — it matches the *shape* of a placeholder, so there is no complete token to rewrite, and it additionally catches leftovers the scaffolders know nothing about. A half-substituted tree is not a working repo either.
Verified against a fully substituted child rather than by inspection:
```
guard in child -> false (CI runs)
guard in template -> true (template still skips its own build)
suite, both states -> 8 passed, 0 failed
```
Your closing note — **audit repos generated since the guard was introduced** — is not covered by this and is the part with live consequences: any of them showing an all-skipped green run has never been built by CI. `openbanking-api` is known; the rest are not. Not filed as its own issue yet because the right scope is an estate-wide sweep rather than a template change, and that belongs with whoever picks up the next backlog pass.
---
_Created via git-mcp on behalf of @mathias_
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Risk: LOW (CI config)
Symptom (mathias/openbanking-api, born 2026-09-03 via gitea-mcp
create_project_from_template): run 5277 reportedsuccess, but jobsLint / Test / Vet,Build & Import,Deploy via GitOpswere allskipped. No image ever reached the registry; the pod sat in ImagePullBackOff.Cause:
.gitea/workflows/cd.ymlguard step readsBoth scaffolders (gitea-mcp's create_project_from_template and local-dev's
scripts/new-project.sh) substitute__MODULE_PATH__in every file, so the generated repo's guard becomesgrep -q 'git.d-ma.be/mathias/<name>' go.mod— which matches forever. The comment above the step describes exactly this failure (harg-bygglov-go#8), but the placeholder in the grep is itself substituted.Fix in the template: split the token so the shell string is unchanged but the substitution engine has nothing to match:
Same for any other guard that greps
__PROJECT_NAME__. Verified in openbanking-api commit "ci: make the template guard immune to placeholder substitution".Also: audit repos generated since the guard was introduced — any of them with an all-skipped green run has never actually been built by CI.
Fixed in
b9bbbae(PR #11, v0.2.0), verified 2026-09-17. Auto-closed by the merge; evidence here.Same root cause as #9 and fixed by the same commit — an explicitly tied pair rather than two separate fixes.
Your diagnosis was exact, including the detail that made this one worse than the first: the broken line sat directly under a comment describing the failure mode. That is the part that decided the shape of the fix. A guard living inline in a workflow step can only be reviewed by reading, so the comment was doing the job a test should have been doing — and a comment cannot fail.
So the detection moved to
scripts/is-template.shwithscripts/tests/is-template_test.sh, which substitutes a copy of the guard and asserts it still answers correctly. Both shipped versions fail that test.One deviation from your proposed fix. You suggested splitting the token so the substitution engine has nothing to match:
That works, but it is invisible: it reads like a typo and the next person tidying the file closes the bug again. Shipped the regex form instead — it matches the shape of a placeholder, so there is no complete token to rewrite, and it additionally catches leftovers the scaffolders know nothing about. A half-substituted tree is not a working repo either.
Verified against a fully substituted child rather than by inspection:
Your closing note — audit repos generated since the guard was introduced — is not covered by this and is the part with live consequences: any of them showing an all-skipped green run has never been built by CI.
openbanking-apiis known; the rest are not. Not filed as its own issue yet because the right scope is an estate-wide sweep rather than a template change, and that belongs with whoever picks up the next backlog pass.Created via git-mcp on behalf of @mathias