Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions docs/plans/2026-05-31-cigen-jenkins-circleci-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,23 @@ audit + rollback notes apply (see Rollback).
to v0.1.6 + workflow consumers to v0.67.0 and rebuild. Version-skew audit at
finish: plugin's workflow pin must equal the freshly tagged v0.68.0 (no lag).

## Backport (2026-05-31, post-execution — manifest scope unchanged)

Three existence-check discoveries at execution (all the `Existence /
runtime-validity` class from autodev #55; no manifest scope change):
- **Scenario id 97 → 100.** Plan guessed "next free id 97"; 97–99 were already
taken. Used actual next-free 100.
- **Scenario config `app.yaml` → `deploy.yaml`.** The scenarios CI strict-`wfctl
validate`s every `config/app.yaml`; an infra/cigen-input config has no app
entry point and fails. Renamed to `config/deploy.yaml` (matches `wfctl ci
generate -c deploy.yaml`; excluded from the app-validate glob, like scenarios
88/93). The local run.sh only ran `ci generate` (cigen analyze, no entry-point
requirement), so it didn't catch this.
- **Plugin version 0.2.0 → 0.3.0.** Plan's Task 7 read plugin.json (0.1.6) and
bumped to 0.2.0, but `v0.2.0` was already a released tag (PR #18; plugin.json
had drifted below it). Bumped to v0.3.0 (PR #22). Lesson: check `git
ls-remote --tags`, not just the version file, before choosing a release version.

## Follow-ups (out of scope for #804)

- **GitLab plan-guard + scoped-secret parity:** `render_gitlab.go` lacks both the
Expand Down
2 changes: 1 addition & 1 deletion docs/plans/2026-05-31-cigen-jenkins-circleci.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
| 2 | feat: route jenkins/circleci through cigen, retire template generators (#804) | Task 5, Task 6, Task 7 | workflow-plugin-ci-generator: feat/cigen-jenkins-circleci-804 |
| 3 | test(scenario-97): config-derived jenkins/circleci CI generation proof (#804) | Task 8, Task 9 | workflow-scenarios: feat/cigen-jenkins-circleci-proof-804 |

**Status:** Locked 2026-05-31T22:52:06Z
**Status:** Complete 2026-05-31T23:56:30Z

---

Expand Down
1 change: 0 additions & 1 deletion docs/plans/2026-05-31-cigen-jenkins-circleci.md.scope-lock

This file was deleted.

83 changes: 83 additions & 0 deletions docs/retros/2026-05-31-cigen-jenkins-circleci-retro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Retro: cigen config-derived Jenkins + CircleCI (#804)

**Issue:** https://github.com/GoCodeAlone/workflow/issues/804
**Merged:** 2026-05-31
**PRs:** workflow #810 (v0.68.0) · workflow-plugin-ci-generator #21 + #22 (v0.3.0) · workflow-scenarios #47 (scenario 100)
**Design:** docs/plans/2026-05-31-cigen-jenkins-circleci-design.md (adversarial PASS @ cycle 3)
**Plan:** docs/plans/2026-05-31-cigen-jenkins-circleci.md (plan-phase PASS @ cycle 2; alignment PASS; scope locked)
**ADR:** decisions/0044-cigen-renderers-omit-legacy-build-deploy-stages.md

## What shipped

`cigen.RenderJenkins` + `cigen.RenderCircleCI` (config-derived emitters from the
existing CIPlan, mirroring the GHA job set) wired into `wfctl ci generate`
(4 platforms) and the ci-generator plugin (all 4 routed through cigen; the entire
`internal/platforms` template package retired). Proof: workflow-scenarios
scenario 100 runs the real `wfctl ci generate` and asserts config-derived output
(22/22). v0.68.0 / plugin v0.3.0.

## Adversarial-review findings, scored

| Phase | Finding | Sev | Outcome |
|---|---|---|---|
| design c1 | "mirror GitLab" wrong — GitLab lacks plan-guard/scoped-secrets | Critical | Resolved upfront — GHA named authoritative; GitLab gap recorded as follow-up |
| design c1 | Jenkins declarative multi-phase structure undefined | Important | Resolved upfront — concrete `when`/per-stage-`environment{}` sketch added |
| design c1 | proof didn't cover plugin path (acceptance #2) | Important | Resolved upfront — PR2 integration test designated |
| design c1 | Jenkins `credentials('NAME')` operator burden | Important | Resolved upfront — required-credentials header comment |
| design c2 | Jenkins `when{changeRequest()}` only works in a Multibranch job | Critical | Resolved upfront — Multibranch header comment + accepted consequence |
| design c2 | generator_test/integration_test file split + helper deletions | Important×2 | Resolved upfront — precise test-rewrite spec |
| plan c1 | Jenkins credentials test sort-fragility | Critical | Resolved upfront — per-credential assertions added |
| plan c1 | Task 6/7 broken-CI window | Critical | Resolved upfront — "no push until Task 7 green" note |
| plan c1 | release→module-proxy timing before `go get @v0.68.0` | Important | **Prescient** — the I4 poll-gate is exactly what unblocked PR2 (module resolved ~30s post-tag) |
| plan c1 | test-quality gaps (CircleCI secret, Task3 trivial, testdata richness) | Important×3 | Resolved upfront |

Design converged in 3 cycles, plan in 2. Every code PR's two-stage review caught
a real issue (below).

## Gate misses

Two real misses slipped to CI/runtime — both **existence-check** misses, the exact
class autodev #55 (shipped earlier this same session) targets:

| Issue | Gate that missed | Why it slipped | Fix |
|---|---|---|---|
| Scenario `config/app.yaml` failed the scenarios-CI strict `wfctl validate` (no entry point) | plan / local run.sh | The local proof ran only `ci generate` (cigen analyze — no entry-point requirement), never `wfctl validate`; the repo CI validates **every** `config/app.yaml` | Renamed to `config/deploy.yaml` (infra config, correctly excluded from the app-validate glob) |
| plugin `v0.2.0` already released (PR #18) — bump collided with an existing tag | plan (Task 7 guessed `0.1.6→0.2.0` from plugin.json) | Plan read the version *file* (0.1.6) but never checked existing *tags*; plugin.json had drifted below the released tag | Bumped to `v0.3.0` (PR #22) |

Both are the **Existence / runtime-validity** bug-class verbatim: assert the
artifact you mutate/emit actually validates against the real consumer, and that
the tag/artifact you create does not already exist. The class was added to
`adversarial-design-review` in #55 the same day but was **not yet active** for
this design's reviews (it merged into the skill in parallel). Had it been live,
both misses were one `wfctl validate` / one `git ls-remote --tags` at design time.

## What worked

- **The I4 release-availability poll-gate was prescient** — the plan-phase
adversarial review flagged the tag→module-proxy race; the bash poll-loop
([[feedback_ci_wait_use_bash_poll_loop]]) confirmed v0.68.0 on the proxy in
~30s and unblocked PR2 cleanly. No "version not found" failure.
- **Two-stage code review earned its keep on every PR**: PR1 → `jenkinsCredentialUnion`
used by the circleci renderer (renamed `secretUnion`); PR2 → `minEngineVersion`
still 0.67.0 (a 0.67.0 consumer would fail plugin load) + stale doc comment.
- **Demonstration-fidelity**: scenario 100 ran the real `wfctl ci generate`
(22 assertions), not a reimplementation; honest evidence committed.
- **Cross-repo sequencing held**: PR1 merge → tag → module proxy → PR2 dep bump →
PR3, with no premature step.

## Plugin-level follow-ups (autodev)

The two gate misses are a **trend with the autodev #55 retro's own evidence**
(required_secrets sweep + smart-CI gen). Recommendation already shipped: the
`Existence / runtime-validity` bug-class (autodev v6.2.2). This retro is the third
data point — when that class is live in the skill, a design that (a) generates a
config a CI consumer will `validate`, or (b) creates a version tag, must show the
`validate`/`ls-remote` check at design time. No new plugin change needed; the
existing class covers both. (If a *fourth* occurrence appears with the class
live and still missed, escalate to a hard pre-flight in `finishing-a-development-branch`.)

## Project guidance updates

| File | Change | Reason |
|---|---|---|
| (none) | no change | No durable cross-design lesson beyond what ADR 0044 + the #55 bug-class already capture. GitLab plan-guard/scoped-secret parity is filed as a code follow-up, not guidance. |
Loading