feat: auto-update kustomize image tag after build (#204) #113

Open
forgejo_admin wants to merge 2 commits from 204-auto-tag-update into main

Summary

Adds a post-build update-tag step to the Woodpecker pipeline that automatically updates the kustomize overlay image tag in pal-e-deployments after a successful build-and-push. This is the westside-app pilot for the pattern described in pal-e-platform#204.

Changes

  • .woodpecker.yaml -- added update-tag step after build-and-push that:
    • Clones pal-e-deployments from internal Forgejo URL
    • Updates newTag in overlays/westsidekingsandqueens/prod/kustomization.yaml to ${CI_COMMIT_SHA}
    • Commits and pushes the change (skips commit if tag unchanged)
    • Uses alpine/git image (same as clone step, known to work in CI)
    • Only runs on push/manual to main (same conditions as build-and-push)
    • Requires ci_forgejo_token Woodpecker secret with push access to pal-e-deployments

Test Plan

  • Create ci_forgejo_token Woodpecker secret for westside-app (manual step)
  • Push a no-op commit to westside-app main after merge
  • Verify pal-e-deployments gets a commit updating newTag in overlays/westsidekingsandqueens/prod/kustomization.yaml
  • Verify ArgoCD picks up the new tag and syncs (depends on pal-e-platform#203)

Review Checklist

  • Passed automated review-fix loop
  • No secrets committed
  • No unnecessary file changes
  • Commit messages are descriptive
  • Closes forgejo_admin/pal-e-platform#204 -- pilot implementation (westside-app only, does not fully resolve cross-repo rollout)
  • project-pal-e-platform -- the project this work belongs to
## Summary Adds a post-build `update-tag` step to the Woodpecker pipeline that automatically updates the kustomize overlay image tag in pal-e-deployments after a successful build-and-push. This is the westside-app pilot for the pattern described in pal-e-platform#204. ## Changes - `.woodpecker.yaml` -- added `update-tag` step after `build-and-push` that: - Clones pal-e-deployments from internal Forgejo URL - Updates `newTag` in `overlays/westsidekingsandqueens/prod/kustomization.yaml` to `${CI_COMMIT_SHA}` - Commits and pushes the change (skips commit if tag unchanged) - Uses `alpine/git` image (same as clone step, known to work in CI) - Only runs on push/manual to main (same conditions as build-and-push) - Requires `ci_forgejo_token` Woodpecker secret with push access to pal-e-deployments ## Test Plan - [ ] Create `ci_forgejo_token` Woodpecker secret for westside-app (manual step) - [ ] Push a no-op commit to westside-app main after merge - [ ] Verify pal-e-deployments gets a commit updating `newTag` in `overlays/westsidekingsandqueens/prod/kustomization.yaml` - [ ] Verify ArgoCD picks up the new tag and syncs (depends on pal-e-platform#203) ## Review Checklist - [ ] Passed automated review-fix loop - [ ] No secrets committed - [ ] No unnecessary file changes - [ ] Commit messages are descriptive ## Related Notes - Closes forgejo_admin/pal-e-platform#204 -- pilot implementation (westside-app only, does not fully resolve cross-repo rollout) - `project-pal-e-platform` -- the project this work belongs to
After build-and-push succeeds, the new update-tag step clones
pal-e-deployments, updates the newTag in the westsidekingsandqueens
kustomization overlay to the commit SHA, and pushes. This closes
the gap where image tags required manual PRs to deploy.

Requires a ci_forgejo_token Woodpecker secret with push access
to pal-e-deployments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

QA Review

Scope: 1 file changed, 16 additions, 0 deletions. Adds update-tag step to .woodpecker.yaml.

Checked

  • No existing steps modified -- validate and build-and-push are untouched
  • cd /tmp/deployments persistence -- Woodpecker concatenates commands into a single shell script, so cd persists across subsequent commands. Correct.
  • sed command -- properly quoted for YAML, uses | delimiter to avoid conflicts with path separators
  • Empty commit guard -- git diff --cached --quiet && echo "No tag change" || git commit ... prevents empty commits when tag is unchanged
  • Secret handling -- uses secrets: [ci_forgejo_token] (Woodpecker-native), token referenced via ${CI_FORGEJO_TOKEN} env var in push URL. No hardcoded credentials.
  • when conditions -- matches build-and-push exactly: event: [push, manual], branch: main
  • Image choice -- alpine/git matches clone step, known to work in CI
  • Internal URLs -- uses forgejo-http.forgejo.svc.cluster.local:80 (no hairpin)
  • Commit message format -- deploy: update westsidekingsandqueens image to ${CI_COMMIT_SHA} is clear and grep-friendly

Prerequisites (not blocking PR)

  • ci_forgejo_token Woodpecker secret must be created manually before this step will work
  • Token needs push access to forgejo_admin/pal-e-deployments

Nits

None.

VERDICT: APPROVE

## QA Review **Scope**: 1 file changed, 16 additions, 0 deletions. Adds `update-tag` step to `.woodpecker.yaml`. ### Checked - **No existing steps modified** -- validate and build-and-push are untouched - **`cd /tmp/deployments` persistence** -- Woodpecker concatenates commands into a single shell script, so `cd` persists across subsequent commands. Correct. - **`sed` command** -- properly quoted for YAML, uses `|` delimiter to avoid conflicts with path separators - **Empty commit guard** -- `git diff --cached --quiet && echo "No tag change" || git commit ...` prevents empty commits when tag is unchanged - **Secret handling** -- uses `secrets: [ci_forgejo_token]` (Woodpecker-native), token referenced via `${CI_FORGEJO_TOKEN}` env var in push URL. No hardcoded credentials. - **`when` conditions** -- matches build-and-push exactly: `event: [push, manual]`, `branch: main` - **Image choice** -- `alpine/git` matches clone step, known to work in CI - **Internal URLs** -- uses `forgejo-http.forgejo.svc.cluster.local:80` (no hairpin) - **Commit message format** -- `deploy: update westsidekingsandqueens image to ${CI_COMMIT_SHA}` is clear and grep-friendly ### Prerequisites (not blocking PR) - `ci_forgejo_token` Woodpecker secret must be created manually before this step will work - Token needs push access to `forgejo_admin/pal-e-deployments` ### Nits None. **VERDICT: APPROVE**
Author
Owner

PR #113 Review

DOMAIN REVIEW

Tech stack: Woodpecker CI pipeline (YAML), kustomize GitOps pattern, shell scripting.

This PR adds a post-build update-tag step to the Woodpecker pipeline that clones pal-e-deployments, updates the kustomize newTag via sed, commits, and pushes. The pattern is sound -- this is the standard "CI updates GitOps repo" approach for ArgoCD-driven deployments.

Pipeline structure review:

  • Image choice (alpine/git) is consistent with the existing clone step. Good.
  • when conditions (push/manual on main) match the build-and-push step. Good.
  • secrets: [ci_forgejo_token] correctly declares the secret dependency so Woodpecker masks it in logs.
  • The sed pattern (s|newTag: .*|newTag: ${CI_COMMIT_SHA}|) works correctly for the westsidekingsandqueens overlay, which has exactly one newTag on line 65 of /home/ldraney/pal-e-deployments/overlays/westsidekingsandqueens/prod/kustomization.yaml.
  • The git diff --cached --quiet && echo "No tag change" || git commit ... pattern correctly handles the idempotent case (no change = no commit). The subsequent git push with no new commits is harmless (prints "Everything up-to-date").
  • Commit message format (deploy: update westsidekingsandqueens image to ${CI_COMMIT_SHA}) is descriptive and traceable.

BLOCKERS

1. Unauthenticated clone of private repo will fail

The git clone command uses an unauthenticated URL:

git clone http://forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git /tmp/deployments

However, pal-e-deployments is a private repository ("private": true from Forgejo API). This clone will fail with a 401/403. The push URL correctly embeds the token (http://woodpecker:${CI_FORGEJO_TOKEN}@...), but the clone URL does not.

Fix: Use the authenticated URL for the clone as well:

git clone http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git /tmp/deployments

This is a blocker because the step will fail on every execution.

NITS

  1. sed replaces ALL newTag lines -- For the westsidekingsandqueens overlay this is safe (only one newTag entry). However, other overlays (e.g., pal-e-docs) have multiple newTag entries for different images. When this pattern is rolled out to other services, the sed command will need to be scoped to the correct image block. Worth noting for the rollout plan.

  2. git push runs even when no commit was made -- When the tag is unchanged, no commit is created but git push still executes (harmlessly). A slightly cleaner pattern would exit early:

    git diff --cached --quiet && { echo "No tag change"; exit 0; }
    

    This avoids the unnecessary push roundtrip. Non-blocking since the current behavior is correct.

  3. Token in git URL may leak on push failure -- If the git push fails (e.g., force-push protection, network issue), git may print the full URL including the embedded token in the error message. Woodpecker's secret masking mitigates this for CI logs, but consider using git remote set-url with a named remote instead of inline credentials for defense-in-depth:

    git remote set-url origin http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git
    git push origin main
    

    This is standard practice and also avoids duplicating the URL between clone and push.

SOP COMPLIANCE

  • Branch named after issue (204-auto-tag-update references pal-e-platform#204)
  • PR body has Summary, Test Plan, Related sections
  • PR body missing explicit ## Changes header (changes are described in Summary, but template expects a separate section)
  • Related section references project slug (project-pal-e-platform)
  • No secrets committed (token is a Woodpecker secret reference, not hardcoded)
  • No unnecessary file changes (single file, 16 lines added)
  • Commit message is descriptive

PROCESS OBSERVATIONS

  • Deployment Frequency (DORA): This PR directly enables automated deployments -- closing the last manual gap in the CI/CD pipeline. High positive impact on DF.
  • Change Failure Risk: The unauthenticated clone blocker means this step will fail silently after build-and-push succeeds. The build artifact will exist in Harbor but the kustomize tag will not be updated, requiring manual intervention -- exactly the problem this PR aims to solve.
  • Cross-repo dependency: This PR creates a runtime dependency between westside-app CI and the ci_forgejo_token Woodpecker secret. The Test Plan correctly calls out the manual secret creation step. Ensure the secret is created before merging to avoid a broken pipeline on the next push to main.
  • Pilot scope: PR body correctly scopes this as a westside-app pilot, not a full rollout. The sed nit above should be tracked for the rollout phase.

VERDICT: NOT APPROVED

One blocker: the git clone of private repo pal-e-deployments uses an unauthenticated URL and will fail. Add the token to the clone URL to match the push URL pattern.

## PR #113 Review ### DOMAIN REVIEW **Tech stack**: Woodpecker CI pipeline (YAML), kustomize GitOps pattern, shell scripting. This PR adds a post-build `update-tag` step to the Woodpecker pipeline that clones pal-e-deployments, updates the kustomize `newTag` via `sed`, commits, and pushes. The pattern is sound -- this is the standard "CI updates GitOps repo" approach for ArgoCD-driven deployments. **Pipeline structure review:** - Image choice (`alpine/git`) is consistent with the existing clone step. Good. - `when` conditions (push/manual on main) match the `build-and-push` step. Good. - `secrets: [ci_forgejo_token]` correctly declares the secret dependency so Woodpecker masks it in logs. - The `sed` pattern (`s|newTag: .*|newTag: ${CI_COMMIT_SHA}|`) works correctly for the westsidekingsandqueens overlay, which has exactly one `newTag` on line 65 of `/home/ldraney/pal-e-deployments/overlays/westsidekingsandqueens/prod/kustomization.yaml`. - The `git diff --cached --quiet && echo "No tag change" || git commit ...` pattern correctly handles the idempotent case (no change = no commit). The subsequent `git push` with no new commits is harmless (prints "Everything up-to-date"). - Commit message format (`deploy: update westsidekingsandqueens image to ${CI_COMMIT_SHA}`) is descriptive and traceable. ### BLOCKERS **1. Unauthenticated clone of private repo will fail** The `git clone` command uses an unauthenticated URL: ``` git clone http://forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git /tmp/deployments ``` However, `pal-e-deployments` is a **private** repository (`"private": true` from Forgejo API). This clone will fail with a 401/403. The push URL correctly embeds the token (`http://woodpecker:${CI_FORGEJO_TOKEN}@...`), but the clone URL does not. **Fix**: Use the authenticated URL for the clone as well: ``` git clone http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git /tmp/deployments ``` This is a blocker because the step will fail on every execution. ### NITS 1. **`sed` replaces ALL `newTag` lines** -- For the westsidekingsandqueens overlay this is safe (only one `newTag` entry). However, other overlays (e.g., pal-e-docs) have multiple `newTag` entries for different images. When this pattern is rolled out to other services, the `sed` command will need to be scoped to the correct image block. Worth noting for the rollout plan. 2. **`git push` runs even when no commit was made** -- When the tag is unchanged, no commit is created but `git push` still executes (harmlessly). A slightly cleaner pattern would exit early: ``` git diff --cached --quiet && { echo "No tag change"; exit 0; } ``` This avoids the unnecessary push roundtrip. Non-blocking since the current behavior is correct. 3. **Token in git URL may leak on push failure** -- If the `git push` fails (e.g., force-push protection, network issue), git may print the full URL including the embedded token in the error message. Woodpecker's secret masking mitigates this for CI logs, but consider using `git remote set-url` with a named remote instead of inline credentials for defense-in-depth: ``` git remote set-url origin http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git git push origin main ``` This is standard practice and also avoids duplicating the URL between clone and push. ### SOP COMPLIANCE - [x] Branch named after issue (`204-auto-tag-update` references pal-e-platform#204) - [x] PR body has Summary, Test Plan, Related sections - [ ] PR body missing explicit `## Changes` header (changes are described in Summary, but template expects a separate section) - [x] Related section references project slug (`project-pal-e-platform`) - [x] No secrets committed (token is a Woodpecker secret reference, not hardcoded) - [x] No unnecessary file changes (single file, 16 lines added) - [x] Commit message is descriptive ### PROCESS OBSERVATIONS - **Deployment Frequency (DORA)**: This PR directly enables automated deployments -- closing the last manual gap in the CI/CD pipeline. High positive impact on DF. - **Change Failure Risk**: The unauthenticated clone blocker means this step will fail silently after build-and-push succeeds. The build artifact will exist in Harbor but the kustomize tag will not be updated, requiring manual intervention -- exactly the problem this PR aims to solve. - **Cross-repo dependency**: This PR creates a runtime dependency between westside-app CI and the `ci_forgejo_token` Woodpecker secret. The Test Plan correctly calls out the manual secret creation step. Ensure the secret is created before merging to avoid a broken pipeline on the next push to main. - **Pilot scope**: PR body correctly scopes this as a westside-app pilot, not a full rollout. The `sed` nit above should be tracked for the rollout phase. ### VERDICT: NOT APPROVED One blocker: the `git clone` of private repo `pal-e-deployments` uses an unauthenticated URL and will fail. Add the token to the clone URL to match the push URL pattern.
Clone URL for pal-e-deployments needs CI_FORGEJO_TOKEN since the repo
is private. Matches the pattern already used in the push URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

PR #113 Re-Review

PREVIOUS BLOCKER STATUS

The previous review identified a blocker: unauthenticated git clone of the private pal-e-deployments repo would fail at runtime. Commit 99c3ae6 was pushed to fix this.

Verdict: RESOLVED. The update-tag step now uses CI_FORGEJO_TOKEN in both the git clone (line 53) and git push (line 60) URLs, and declares secrets: [ci_forgejo_token] (line 61) to inject the token. Woodpecker automatically masks declared secrets in log output, so the token embedded in the URLs will not leak.

DOMAIN REVIEW

Tech stack: Woodpecker CI pipeline YAML (CI/CD infrastructure).

  • Image choice: alpine/git matches the existing clone step -- consistent, minimal, known to work in this cluster.
  • Kustomize target path: Verified overlays/westsidekingsandqueens/prod/kustomization.yaml exists in pal-e-deployments and contains newTag: <sha> on line 65. The sed pattern 's|newTag: .*|newTag: ${CI_COMMIT_SHA}|' correctly matches and replaces.
  • Conditional commit: git diff --cached --quiet && echo "No tag change" || git commit -m ... properly handles idempotency (re-runs with same SHA will not create empty commits).
  • When conditions: event: [push, manual] + branch: main matches the build-and-push step -- the update-tag step only fires after a successful build.
  • Race condition: If two pushes to main overlap, the second git push would fail (non-fast-forward). The pipeline would fail and need re-trigger. This is acceptable for a pilot and matches standard GitOps CI patterns.
  • Secret management: Token is injected via Woodpecker's secrets directive, never hardcoded. The ci_forgejo_token secret must be created manually per the test plan.

BLOCKERS

None. The previous blocker (unauthenticated clone) is resolved.

NITS

  1. DRY: Forgejo internal URL repeated twice -- The URL http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git appears in both the clone and push commands (lines 53, 60). Consider extracting to an environment variable at the step level for maintainability when this pattern rolls out to other repos. Non-blocking for a pilot.

  2. No retry on push failure -- As noted in the domain review, concurrent pushes to main could cause a non-fast-forward rejection. A git pull --rebase && git push retry would make this more robust. Acceptable for pilot scope.

SOP COMPLIANCE

  • Branch named after issue (204-auto-tag-update references pal-e-platform#204)
  • PR body has Summary, Changes, Test Plan, Related sections
  • Related section references parent issue (pal-e-platform#204) and project (project-pal-e-platform)
  • No secrets committed (token injected via Woodpecker secrets mechanism)
  • No unnecessary file changes (single file changed: .woodpecker.yaml, +16 lines)
  • Commit messages are descriptive
  • Test plan is manual verification (appropriate for CI pipeline config -- no unit test framework for YAML pipelines)

PROCESS OBSERVATIONS

  • Deployment Frequency: This PR directly enables automated image tag updates, removing the manual deploy bottleneck. Positive DORA impact on deployment frequency.
  • Change Failure Risk: Low. The step is additive (appended after build-and-push), does not modify existing steps, and the conditional commit prevents empty commits.
  • Cross-repo pattern: This is the westside-app pilot. The PR body correctly notes it does not fully resolve #204 (rollout to other repos is separate work). Nit #1 (DRY URL) becomes more important when rolling out.
  • Dependency: Requires ci_forgejo_token Woodpecker secret to be created before merge. Test plan correctly captures this as a manual prerequisite.

VERDICT: APPROVED

## PR #113 Re-Review ### PREVIOUS BLOCKER STATUS The previous review identified a **blocker**: unauthenticated `git clone` of the private `pal-e-deployments` repo would fail at runtime. Commit `99c3ae6` was pushed to fix this. **Verdict: RESOLVED.** The `update-tag` step now uses `CI_FORGEJO_TOKEN` in both the `git clone` (line 53) and `git push` (line 60) URLs, and declares `secrets: [ci_forgejo_token]` (line 61) to inject the token. Woodpecker automatically masks declared secrets in log output, so the token embedded in the URLs will not leak. ### DOMAIN REVIEW **Tech stack**: Woodpecker CI pipeline YAML (CI/CD infrastructure). - **Image choice**: `alpine/git` matches the existing clone step -- consistent, minimal, known to work in this cluster. - **Kustomize target path**: Verified `overlays/westsidekingsandqueens/prod/kustomization.yaml` exists in `pal-e-deployments` and contains `newTag: <sha>` on line 65. The `sed` pattern `'s|newTag: .*|newTag: ${CI_COMMIT_SHA}|'` correctly matches and replaces. - **Conditional commit**: `git diff --cached --quiet && echo "No tag change" || git commit -m ...` properly handles idempotency (re-runs with same SHA will not create empty commits). - **When conditions**: `event: [push, manual]` + `branch: main` matches the `build-and-push` step -- the update-tag step only fires after a successful build. - **Race condition**: If two pushes to main overlap, the second `git push` would fail (non-fast-forward). The pipeline would fail and need re-trigger. This is acceptable for a pilot and matches standard GitOps CI patterns. - **Secret management**: Token is injected via Woodpecker's `secrets` directive, never hardcoded. The `ci_forgejo_token` secret must be created manually per the test plan. ### BLOCKERS None. The previous blocker (unauthenticated clone) is resolved. ### NITS 1. **DRY: Forgejo internal URL repeated twice** -- The URL `http://woodpecker:${CI_FORGEJO_TOKEN}@forgejo-http.forgejo.svc.cluster.local:80/forgejo_admin/pal-e-deployments.git` appears in both the clone and push commands (lines 53, 60). Consider extracting to an environment variable at the step level for maintainability when this pattern rolls out to other repos. Non-blocking for a pilot. 2. **No retry on push failure** -- As noted in the domain review, concurrent pushes to main could cause a non-fast-forward rejection. A `git pull --rebase && git push` retry would make this more robust. Acceptable for pilot scope. ### SOP COMPLIANCE - [x] Branch named after issue (`204-auto-tag-update` references pal-e-platform#204) - [x] PR body has Summary, Changes, Test Plan, Related sections - [x] Related section references parent issue (pal-e-platform#204) and project (`project-pal-e-platform`) - [x] No secrets committed (token injected via Woodpecker secrets mechanism) - [x] No unnecessary file changes (single file changed: `.woodpecker.yaml`, +16 lines) - [x] Commit messages are descriptive - [x] Test plan is manual verification (appropriate for CI pipeline config -- no unit test framework for YAML pipelines) ### PROCESS OBSERVATIONS - **Deployment Frequency**: This PR directly enables automated image tag updates, removing the manual deploy bottleneck. Positive DORA impact on deployment frequency. - **Change Failure Risk**: Low. The step is additive (appended after build-and-push), does not modify existing steps, and the conditional commit prevents empty commits. - **Cross-repo pattern**: This is the westside-app pilot. The PR body correctly notes it does not fully resolve #204 (rollout to other repos is separate work). Nit #1 (DRY URL) becomes more important when rolling out. - **Dependency**: Requires `ci_forgejo_token` Woodpecker secret to be created before merge. Test plan correctly captures this as a manual prerequisite. ### VERDICT: APPROVED
This pull request has changes conflicting with the target branch.
  • .woodpecker.yaml
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 204-auto-tag-update:204-auto-tag-update
git switch 204-auto-tag-update

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff 204-auto-tag-update
git switch 204-auto-tag-update
git rebase main
git switch main
git merge --ff-only 204-auto-tag-update
git switch 204-auto-tag-update
git rebase main
git switch main
git merge --no-ff 204-auto-tag-update
git switch main
git merge --squash 204-auto-tag-update
git switch main
git merge --ff-only 204-auto-tag-update
git switch main
git merge 204-auto-tag-update
git push origin main
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/westside-landing!113
No description provided.