This is my regression. Commit 66dfd56b, merged via #442, left an unquoted YAML scalar containing ": ", so Woodpecker cannot compile the config:
yaml: construct errors: line 152: cannot unmarshal
'map[echo "PIN THIS:gitea.renner.uno/gitea_admin/z2m-seed@$DIGEST"]'
of type map[string]interface {} into a string value
A compile error rejects the entire pipeline set, not just build-ci-images. So every pipeline on master has errored since that merge. From the pipeline history:
Note 3052 and 3053 are not mine — an unrelated merge and the alert-monitor cron were both collateral. Alert monitoring has been down since.
Fix
Quote the command as a single YAML scalar.
Why my pre-merge validation missed it
I validated with yq '.' >/dev/null, which passed — because the unquoted form is valid YAML. It just parses as a map rather than a string. Parsing successfully is not the same as matching the schema.
woodpecker lint catches it instantly:
$ woodpecker lint .woodpecker/build-ci-images.yml # before
cannot unmarshal 'map[echo "PIN THIS:...' into a string value
$ woodpecker lint .woodpecker/build-ci-images.yml # after
✅ Config is valid
That tool existed the whole time and I didn't use it. The failure mode and the "lint, don't just parse" instruction are now recorded in a comment at that line so this isn't reintroduced.
Verification
All 17 .woodpecker/*.yml files linted. Everything valid except pre-existing Additional property timeout is not allowed warnings in four deploy-* files — untouched here, and warnings rather than errors.
Once this merges, the build-z2m-seed step should run for the first time and print the PIN THIS: digest needed for step 2 of the apk add removal.
## ⚠️ URGENT — restores CI for the entire repo
**This is my regression.** Commit `66dfd56b`, merged via #442, left an unquoted YAML scalar containing `": "`, so Woodpecker cannot compile the config:
```
yaml: construct errors: line 152: cannot unmarshal
'map[echo "PIN THIS:gitea.renner.uno/gitea_admin/z2m-seed@$DIGEST"]'
of type map[string]interface {} into a string value
```
A compile error rejects the **entire pipeline set**, not just `build-ci-images`. So every pipeline on master has errored since that merge. From the pipeline history:
| pipeline | event | status |
|---|---|---|
| 3047 | pull_request | success (last good) |
| **3048** | push `z2m-seed-drop-apk` | **error — first failure, my commit** |
| 3049 | pull_request | error |
| 3050 | pull_request_closed | error |
| 3051 | push (merge of #442) | error |
| 3052 | push (merge of **#440**, unrelated) | error |
| 3053 | cron **alert-monitor** | error |
Note 3052 and 3053 are not mine — an unrelated merge and the alert-monitor cron were both collateral. Alert monitoring has been down since.
## Fix
Quote the command as a single YAML scalar.
## Why my pre-merge validation missed it
I validated with `yq '.' >/dev/null`, which **passed** — because the unquoted form *is* valid YAML. It just parses as a **map** rather than a string. Parsing successfully is not the same as matching the schema.
`woodpecker lint` catches it instantly:
```
$ woodpecker lint .woodpecker/build-ci-images.yml # before
cannot unmarshal 'map[echo "PIN THIS:...' into a string value
$ woodpecker lint .woodpecker/build-ci-images.yml # after
✅ Config is valid
```
That tool existed the whole time and I didn't use it. The failure mode and the "lint, don't just parse" instruction are now recorded in a comment at that line so this isn't reintroduced.
## Verification
All 17 `.woodpecker/*.yml` files linted. Everything valid except pre-existing `Additional property timeout is not allowed` warnings in four `deploy-*` files — untouched here, and warnings rather than errors.
Once this merges, the `build-z2m-seed` step should run for the first time and print the `PIN THIS:` digest needed for step 2 of the `apk add` removal.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
URGENT: this restores CI for the WHOLE repo. My commit 66dfd56b (merged
via #442) left an unquoted YAML scalar containing ": ", so Woodpecker
failed to compile the config:
yaml: construct errors: line 152: cannot unmarshal
'map[echo "PIN THIS:gitea.renner.uno/gitea_admin/z2m-seed@$DIGEST"]'
of type map[string]interface {} into a string value
Because a compile error rejects the entire pipeline set, every pipeline on
master has errored since that merge — not only build-ci-images. Confirmed
from pipeline history: 3048 (the push that introduced it) is the first
failure, and 3049-3053 follow, including an unrelated merge (#440) and the
alert-monitor cron.
Fixed by quoting the command as a single YAML scalar.
Why my pre-merge validation missed it: I checked with `yq '.' >/dev/null`,
which passed because the unquoted form IS valid YAML — it just parses as a
map instead of a string. Parsing successfully is not the same as matching
the schema. `woodpecker lint` catches it immediately and is now noted in a
comment at the line, along with the specific failure mode, so the trap is
not reinstated.
All 17 .woodpecker/*.yml files now lint clean apart from pre-existing
"Additional property timeout is not allowed" warnings in four deploy-*
files, which are untouched by this change and are warnings rather than
errors.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
🤖Automated review — model claude-haiku-4-5-20251001 (complexity: trivial), commit f7d79e6c7077b75a8211c50b77e5a8850ac7495f.
Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.
Summary
This PR fixes a critical YAML parsing regression in .woodpecker/build-ci-images.yml that broke the entire pipeline set. The issue: an unquoted scalar containing ": " was incorrectly parsed as a YAML map instead of a string. The fix correctly wraps the command in single quotes as a literal YAML scalar, and includes a detailed comment explaining the issue and validation approach to prevent reintroduction.
🔴 Blocking
None. The fix is correct and addresses the root cause.
The change correctly uses single quotes to enforce YAML string parsing. Single quotes in YAML are literal, but the YAML parser strips these quotes before passing the command to the shell, so $DIGEST will still be expanded at shell execution time (inside the double quotes in the echo command). This is correct behavior, but it relies on understanding that YAML quote removal happens before shell execution. The comment documents this well, so no change needed — just noting it's not immediately obvious.
🟢 Nits
The verbose comment (7 lines for a 1-line change) is justified here given the severity of the regression and the need to document the validation caveat. No changes needed.
Tests
No tests needed for this change — it's a CI configuration file, not application code. The PR body correctly notes that woodpecker lint was run to validate all 17 Woodpecker config files in the repo.
Recommendation
Looks reasonable — no blocking issues; this fixes a critical production outage affecting the entire pipeline set.
🤖 **Automated review** — model `claude-haiku-4-5-20251001` (complexity: trivial), commit `f7d79e6c7077b75a8211c50b77e5a8850ac7495f`.
> Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review.
---
## Summary
This PR fixes a critical YAML parsing regression in `.woodpecker/build-ci-images.yml` that broke the entire pipeline set. The issue: an unquoted scalar containing `": "` was incorrectly parsed as a YAML map instead of a string. The fix correctly wraps the command in single quotes as a literal YAML scalar, and includes a detailed comment explaining the issue and validation approach to prevent reintroduction.
## 🔴 Blocking
None. The fix is correct and addresses the root cause.
## 🟡 Suggestions
**Variable expansion verification** — `.woodpecker/build-ci-images.yml:179`
The change correctly uses single quotes to enforce YAML string parsing. Single quotes in YAML are literal, but the YAML parser strips these quotes before passing the command to the shell, so `$DIGEST` will still be expanded at shell execution time (inside the double quotes in the echo command). This is correct behavior, but it relies on understanding that YAML quote removal happens before shell execution. The comment documents this well, so no change needed — just noting it's not immediately obvious.
## 🟢 Nits
The verbose comment (7 lines for a 1-line change) is justified here given the severity of the regression and the need to document the validation caveat. No changes needed.
## Tests
No tests needed for this change — it's a CI configuration file, not application code. The PR body correctly notes that `woodpecker lint` was run to validate all 17 Woodpecker config files in the repo.
## Recommendation
Looks reasonable — no blocking issues; this fixes a critical production outage affecting the entire pipeline set.
<!-- pr-review:sha=f7d79e6c7077b75a8211c50b77e5a8850ac7495f -->
Review is clean — no blocking issues, and I agree no code change is needed. But the 🟡 about single-quote stripping vs. shell expansion is worth settling by execution rather than reasoning, since misreading exactly that kind of layering is what caused this outage in the first place.
The push to this branch touched .woodpecker/build-ci-images.yml, which is in build-z2m-seed's when.path, so the step actually ran in pipeline 3054:
So three things are confirmed empirically rather than inferred:
$DIGEST does expand — your 🟡, verified. YAML strips the single quotes, the shell sees the double-quoted echo.
The config compiles — pipelines 3054 (push) and 3055 (pull_request) both succeeded, where 3048-3053 all errored.
The dedupe works — exactly one line, not the two the #442 review predicted.
Side effect worth flagging: because that step triggers on event: push with no branch restriction, the image was built and pushed to the registry from this branch, before merge. That is pre-existing pipeline behaviour rather than anything this PR changes, but it means z2m-seed already exists in the registry.
Useful consequence: the digest above is what step 2 of the apk add removal needs, so that follow-up is unblocked and needs no separate registry query.
On the 🟢 — agreed the 7-line comment is disproportionate to a 1-line change in the abstract, but the whole repo's CI was down because yq accepting the file was mistaken for the file being valid. That distinction is worth the lines.
Review is clean — no blocking issues, and I agree no code change is needed. But the 🟡 about single-quote stripping vs. shell expansion is worth settling by execution rather than reasoning, since misreading exactly that kind of layering is what caused this outage in the first place.
The push to this branch touched `.woodpecker/build-ci-images.yml`, which is in `build-z2m-seed`'s `when.path`, so the step actually ran in pipeline 3054:
```
+ DIGEST=$(cut -d@ -f2 /kaniko/z2m-seed.digest | sort -u | head -1)
+ echo "PIN THIS: gitea.renner.uno/gitea_admin/z2m-seed@$DIGEST"
PIN THIS: gitea.renner.uno/gitea_admin/z2m-seed@sha256:9a11b837010a53e481870612022ea5c7b9aba34f238377838305786e58eb061b
```
So three things are confirmed empirically rather than inferred:
1. **`$DIGEST` does expand** — your 🟡, verified. YAML strips the single quotes, the shell sees the double-quoted `echo`.
2. **The config compiles** — pipelines 3054 (push) and 3055 (pull_request) both succeeded, where 3048-3053 all errored.
3. **The dedupe works** — exactly one line, not the two the #442 review predicted.
Side effect worth flagging: because that step triggers on `event: push` with no branch restriction, the image was built and pushed to the registry **from this branch**, before merge. That is pre-existing pipeline behaviour rather than anything this PR changes, but it means `z2m-seed` already exists in the registry.
Useful consequence: the digest above is what step 2 of the `apk add` removal needs, so that follow-up is unblocked and needs no separate registry query.
On the 🟢 — agreed the 7-line comment is disproportionate to a 1-line change in the abstract, but the whole repo's CI was down because `yq` accepting the file was mistaken for the file being valid. That distinction is worth the lines.
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.
⚠️ URGENT — restores CI for the entire repo
This is my regression. Commit
66dfd56b, merged via #442, left an unquoted YAML scalar containing": ", so Woodpecker cannot compile the config:A compile error rejects the entire pipeline set, not just
build-ci-images. So every pipeline on master has errored since that merge. From the pipeline history:z2m-seed-drop-apkNote 3052 and 3053 are not mine — an unrelated merge and the alert-monitor cron were both collateral. Alert monitoring has been down since.
Fix
Quote the command as a single YAML scalar.
Why my pre-merge validation missed it
I validated with
yq '.' >/dev/null, which passed — because the unquoted form is valid YAML. It just parses as a map rather than a string. Parsing successfully is not the same as matching the schema.woodpecker lintcatches it instantly:That tool existed the whole time and I didn't use it. The failure mode and the "lint, don't just parse" instruction are now recorded in a comment at that line so this isn't reintroduced.
Verification
All 17
.woodpecker/*.ymlfiles linted. Everything valid except pre-existingAdditional property timeout is not allowedwarnings in fourdeploy-*files — untouched here, and warnings rather than errors.Once this merges, the
build-z2m-seedstep should run for the first time and print thePIN THIS:digest needed for step 2 of theapk addremoval.🤖 Generated with Claude Code
🤖 Automated review — model
claude-haiku-4-5-20251001(complexity: trivial), commitf7d79e6c7077b75a8211c50b77e5a8850ac7495f.Summary
This PR fixes a critical YAML parsing regression in
.woodpecker/build-ci-images.ymlthat broke the entire pipeline set. The issue: an unquoted scalar containing": "was incorrectly parsed as a YAML map instead of a string. The fix correctly wraps the command in single quotes as a literal YAML scalar, and includes a detailed comment explaining the issue and validation approach to prevent reintroduction.🔴 Blocking
None. The fix is correct and addresses the root cause.
🟡 Suggestions
Variable expansion verification —
.woodpecker/build-ci-images.yml:179The change correctly uses single quotes to enforce YAML string parsing. Single quotes in YAML are literal, but the YAML parser strips these quotes before passing the command to the shell, so
$DIGESTwill still be expanded at shell execution time (inside the double quotes in the echo command). This is correct behavior, but it relies on understanding that YAML quote removal happens before shell execution. The comment documents this well, so no change needed — just noting it's not immediately obvious.🟢 Nits
The verbose comment (7 lines for a 1-line change) is justified here given the severity of the regression and the need to document the validation caveat. No changes needed.
Tests
No tests needed for this change — it's a CI configuration file, not application code. The PR body correctly notes that
woodpecker lintwas run to validate all 17 Woodpecker config files in the repo.Recommendation
Looks reasonable — no blocking issues; this fixes a critical production outage affecting the entire pipeline set.
Review is clean — no blocking issues, and I agree no code change is needed. But the 🟡 about single-quote stripping vs. shell expansion is worth settling by execution rather than reasoning, since misreading exactly that kind of layering is what caused this outage in the first place.
The push to this branch touched
.woodpecker/build-ci-images.yml, which is inbuild-z2m-seed'swhen.path, so the step actually ran in pipeline 3054:So three things are confirmed empirically rather than inferred:
$DIGESTdoes expand — your 🟡, verified. YAML strips the single quotes, the shell sees the double-quotedecho.Side effect worth flagging: because that step triggers on
event: pushwith no branch restriction, the image was built and pushed to the registry from this branch, before merge. That is pre-existing pipeline behaviour rather than anything this PR changes, but it meansz2m-seedalready exists in the registry.Useful consequence: the digest above is what step 2 of the
apk addremoval needs, so that follow-up is unblocked and needs no separate registry query.On the 🟢 — agreed the 7-line comment is disproportionate to a 1-line change in the abstract, but the whole repo's CI was down because
yqaccepting the file was mistaken for the file being valid. That distinction is worth the lines.