Skip to content

Commit 892cf3f

Browse files
ci(release): bump checkout v4→v6 + setup-python v5→v6 (Node 20 deprecation)
Closes side-finding #1 from the 2026-05-13 Sigstore E2E dry-run: both v4 of actions/checkout and v5 of actions/setup-python depend on Node 20, which GitHub deprecates 2026-09-16. v6 of both actions runs on Node 24. Scope is intentionally surgical: - release.yml only (the workflow §8 explicitly called out) - cosign-installer@v3 deliberately left untouched — that action is signing-critical and the 2026-05-13 §8 verification is keyed to its behavior. Bumping it would invalidate the static verification artifact and require re-running the §8 dry-run on a fresh throwaway tag. Verified bumps are safe for our usage: - checkout v4→v6: only breaking change is runner-version requirement (≥v2.327.1); GitHub-hosted runners already satisfy this. v6's credential-storage-in-$RUNNER_TEMP change only affects Docker container actions, which we don't use. - setup-python v5→v6: sole breaking change is the Node 24 bump itself. Our `python-version: "3.11"` usage is unaffected. 13 other workflows (a11y-audit.yml, appinspect.yml, appinspect-api.yml, ci.yml, codeql.yml, docs.yml, e2e-full.yml, e2e-smoke.yml, integration-tests.yml, pip-audit.yml, scorecard.yml, secret-scan.yml, semgrep.yml, validate-and-package.yml, zap-baseline.yml) ALSO pin Node-20-era versions and need a separate sweep before 2026-09-16. Out of scope for this commit; full rationale in DECISION_LOG 2026-05-20 row. YAML parses clean. doc-drift OK against build 663.
1 parent ceb9d00 commit 892cf3f

2 files changed

Lines changed: 12 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,19 @@ jobs:
2323
contents: write
2424
id-token: write
2525
steps:
26-
- uses: actions/checkout@v4
26+
# actions/checkout@v6 + setup-python@v6 close §8 side-finding #1
27+
# from the 2026-05-13 Sigstore dry-run: the previous v4/v5 pins
28+
# depended on Node 20, which GitHub deprecates 2026-09-16. v6 of
29+
# both actions moves to Node 24. No flag changes for our usage
30+
# (default checkout, python-version=3.11). cosign-installer@v3
31+
# is intentionally left untouched — that action is signing-
32+
# critical and the 2026-05-13 §8 verification is keyed to its
33+
# behavior. v3→v4 would require re-doing the §8 dry-run on a
34+
# fresh throwaway tag, scheduled for a dedicated cycle.
35+
- uses: actions/checkout@v6
2736

2837
- name: Set up Python
29-
uses: actions/setup-python@v5
38+
uses: actions/setup-python@v6
3039
with:
3140
python-version: "3.11"
3241

docs/DECISION_LOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ When making a tech choice with multiple valid options, record it here BEFORE dep
3434
| 2026-05-01 | **Kill `.btn-success` taxonomy too; collapse all green buttons to Splunk-bundled `.btn-primary` (build 635).** | (a) Keep `.btn-success` as a parallel rule with our own muted shade; (b) override Splunk's `.btn-primary` to our muted shade so all greens match; (c) migrate every `.btn-success` callsite to `.btn-primary` and delete the rule. | The build-634 desaturation pass kept `.btn-success` muted (`#388e3c`) while `.btn-primary` rendered Splunk's vivid `#1a8929`. User-facing result: "+ Add Row" / "+ Add Column" (btn-primary) and Save Changes / Approve (btn-success) had two slightly-different greens side-by-side on the same toolbar — visible inconsistency that the user flagged. (a) Maintaining a parallel rule has the same long-term liability as `.wl-btn` did (see 2026-05-01 prior entry). (b) Overriding Splunk's bundled `.btn-primary` is risky — it could affect Splunk-native UI elsewhere on the dashboard (Edit / Export / Cancel buttons in Splunk modals). (c) is the same playbook as the wl-btn migration: 5 callsites in 4 files, single-line search-and-replace per file, zero handler changes (handlers find by `#id`, not class). | Low — re-add the `.btn.btn-success` rule to `whitelist_manager.css` and revert the 5 callsite edits. The `.btn.btn-danger` and `.btn.btn-warning` muted rules (also build 634) are unaffected — those colours have no Splunk bundled equivalent so we keep owning them. **Maintenance rule (search-and-replace as a workflow)**: when removing a parallel CSS taxonomy, the operation is a class-rename via grep, NOT a refactor. The pattern: (1) `grep btn-success` for every callsite, (2) Edit each callsite's class string in place, (3) delete the now-orphan CSS rule, (4) verify no callsites remain. Components-based apps would centralize this in one template; vanilla-JS Splunk apps render HTML strings inline per module, so consistency relies on grep + discipline. When facing a similar audit (ANY parallel-CSS-system removal), reach for the search-and-replace workflow first; resist the urge to "abstract" or "centralize" because there is no shared template layer to put the abstraction in. |
3535
| 2026-04-29 | **Declare security-hardening track CLOSED at build 629 (round 9).** No further proactive hardening rounds. Future inbound work that does NOT match a re-opening signal (CVE, production incident, external audit finding, Q3 routine surfacing major-version compat work, or methodology shift to a fresh fuzz surface) is feature work, not hardening work. | (a) Continue with rounds 10+ at the same cadence; (b) move to a 6-month re-audit cycle with no per-round structure; (c) formal closure with explicit re-open criteria. | 9 rounds covered every reasonable security gap. Round 8 fuzz found 0 bugs; round 9 was pure housekeeping with no `app.conf [install] build` bump — the natural diminishing-returns signal. CI gates (4 Semgrep rules + doc-drift + quarterly pip-audit + unit tests on every PR), live FIM monitoring (15s + ~2s paths + dual-store baseline), recurring audits (Q3 2026 version-pinning routine), and Sigstore signing of releases now make the system self-sustaining without further rounds. Continuing past clear diminishing returns risks (a) hardening fatigue masking real signal, (b) churn-without-substance erosion of the changelog's signal-to-noise, (c) future contributors expecting a "round N" cadence and queuing low-value work to fit. Closing prevents this. | Low — any re-opening signal (CVE, incident, audit finding, methodology shift, major-version compat) immediately re-opens with a new round entry. Closing is a status declaration, not an architectural change. The closing summary at the top of `CHANGELOG.md` is the canonical artifact; future contributors read it before queuing security work. **Maintenance rule**: do NOT propose "round 10" by default. The next round must be triggered by an inbound signal, not by schedule. |
3636
| 2026-05-19 | **Fix `_execute_replay_revert_csv` by delegation to canonical `revert_csv_pipeline` (build 663)**, mirroring the pattern used by `create_rule`/`delete_rule`/`delete_csv` handlers. Add `"revert"` as an alias for `"revert_csv"` in `REPLAY_HANDLERS` so the dispatch table matches the handler's stored `action_type` literal. | (a) Delete `_execute_replay_revert_csv` and the dispatch entry entirely, since `wl_handler.py:6761` short-circuits revert approvals to `self._revert_csv` and the replay path is dead in production; (b) fix the in-function bugs in place (resolve path before calling `get_versions_dir`, pass `csv_path` not `csv_file` to `read_version_manifest`, read `version_filename` not `version_id`, fix the manifest iteration); (c) replace the whole body with a delegation to `revert_csv_pipeline`. | The replay function had three dormant bugs (no-arg `get_versions_dir()`, wrong-arg `read_version_manifest`, `version_id` vs `version_filename` field mismatch). (a) Removing the dispatch entry creates an architectural-contract trap: future contributors who consolidate approval paths will discover the replay layer is half-built and either silently broken or missing-by-design. (b) Fixing in place keeps a parallel implementation of revert logic that has to track every change to the direct-handler path (`wl_handler.py:_revert_csv` → `revert_csv_pipeline`); two sources of truth diverged exactly the way (b) would invite. (c) Delegation collapses both paths to the same pipeline call — replay becomes a thin wrapper over the same business logic, which is what the other approval handlers already do (`create_rule_pipeline`, `delete_rule_pipeline`, `delete_csv_pipeline`). Coverage rose 79% → 92% on `wl_replay.py` because the new body is small + fully reachable from tests. | Low — `git revert d267ea3`, re-introduces the broken body. The dispatch entry alias (`"revert" → _execute_replay_revert_csv`) is a separate concern and can stay if the underlying handler is removed — REPLAY_HANDLERS aliasing was added defensively to match future routing intent. **Maintenance rule**: when a replay handler exists for an `action_type`, it MUST delegate to the same canonical pipeline the direct-handler path uses. Do NOT reimplement the business logic in the replay layer — single source of truth keeps drift impossible. |
37+
| 2026-05-20 | **Partial Node-20 deprecation bump in `release.yml`** — bump `actions/checkout@v4 → @v6` and `actions/setup-python@v5 → @v6` to close §8 side-finding #1 from the 2026-05-13 Sigstore dry-run. Leave `sigstore/cosign-installer@v3` deliberately unbumped despite v4.1.2 being GA. The 13 other workflows (`a11y-audit.yml`, `appinspect.yml`, `appinspect-api.yml`, `ci.yml`, `codeql.yml`, `docs.yml`, `e2e-full.yml`, `e2e-smoke.yml`, `integration-tests.yml`, `pip-audit.yml`, `scorecard.yml`, `secret-scan.yml`, `semgrep.yml`, `validate-and-package.yml`, `zap-baseline.yml`) ALSO pin Node-20-era versions and need a separate sweep. | (a) Full project-wide sweep of all 14 workflows in one commit, including cosign-installer v3→v4; (b) bump everything except cosign-installer (signing-critical) in a single sweep; (c) **bump only the two actions §8 explicitly called out + only in release.yml**, defer rest to dedicated cycles. | (a) bundles a signing-critical action change (cosign-installer v3→v4) with routine Node-version bumps, invalidating the 2026-05-13 §8 verification in a non-atomic commit — if a verification step regresses, the cause could be the signing-installer OR any of the other bumps. Recovery requires bisecting across 14 files. (b) is the right scope long-term but is still a 13-workflow change that needs CI verification for each; doing it in this session would mean shipping ~14 untested workflow changes. (c) keeps the change surgical: 2-line edit, no Sigstore re-verification needed (the signing path is untouched), and the 2026-05-13 §8 dry-run remains the authoritative verification artifact. The 2026-09-16 GitHub deprecation deadline is ~4 months away — there's runway to do the full sweep in a dedicated cycle with per-workflow CI verification. The two flagged actions are the ones the §8 dry-run actually warned about, so the closure has a direct provenance link to the side-finding. | Low — `git revert` the bump commit reverts to v4/v5 pins; the 2026-09-16 deadline is the hard constraint, so revert is safe as long as the full sweep happens before then. **Maintenance rule**: bumping `cosign-installer@v3 → v4` MUST be done in a commit that also re-runs `docs/RELEASE_CHECKLIST.md` §8 on a fresh `v0.0.0-sigstore-test-N+1` tag. The §8 verification is keyed to the signing-installer version; changing it invalidates the static verification artifact. Maintain the same rule for any future signing-installer major bump. |
3738
| 2026-05-11 | **E2E tests CI-gated via TWO workflows.** `e2e-smoke.yml` runs ~3 non-destructive E2E flow tests on every PR (~5 min). `e2e-full.yml` runs the entire 20-test E2E suite (destructive + visual regression + concurrency + stress) on a nightly UTC schedule and via manual `workflow_dispatch`. Smoke selection: `test_trash_traversal.cjs` + `test_rate_limit_burst.cjs` + `test_control_panel_long_content.cjs` — all UI-driven, no destructive helpers, exercise the REST → frontend stack end-to-end. The destructive `WL_TEST_HARNESS=1` env var is set only inline per nightly step, never globally. | (a) Full CI on every PR (run all 22 on each PR); (b) tag-gated (PR label `e2e` to run any E2E); (c) manual `workflow_dispatch` only with no nightly; (d) status quo (E2E tests never run in CI, only ad-hoc on developer machines). | (a) is rejected because 20 tests × ~30-60s + Playwright + container setup = 30+ min added to every PR, multiplied across every contributor push. Rate-limit collisions in the integration suite (a documented Ring 3 finding) would be worse for E2E since the destructive E2E tests deplete shared counters faster than the integration suite. (b) shifts the gating decision to contributors who may forget the label — over time the signal degrades to "nobody runs E2E in CI". (c) is what (d) effectively becomes: opt-in tools get used heavily for a month then forgotten. (d) is the prior state — 20 tests with real bug-finding signal lived entirely outside CI, so PR-introduced regressions had to wait for a developer's manual run to surface. The chosen two-workflow shape preserves PR feedback latency (smoke <5 min) while ensuring the full suite runs at least daily; failures in the nightly run upload artifacts and surface in the GitHub Actions summary the next morning. Mirrors the standard test-pyramid principle: heavier tests run less frequently but never skip. | Low — to revert to "full E2E on every PR": change `schedule` and `workflow_dispatch` to `pull_request` in `e2e-full.yml` and delete `e2e-smoke.yml`. To revert to status quo: delete both workflow files. The two-workflow shape is intentional separation; merging them would re-introduce the latency cost (a) was rejected for. **Maintenance rule (adding a new E2E test)**: by default, NEW tests go to the nightly full workflow. Only promote to smoke after the test has been stable in nightly for ≥2 weeks AND a smoke slot opens up (we cap smoke at ~5 tests to keep PR latency <5 min). If you promote a test to smoke, document the choice in the workflow file's comments and remove an existing one if the cap is hit. |
3839

3940
**When a past decision is reversed**: add a NEW row with the new choice and a "Why reversed: see <YYYY-MM-DD> row" note. Do NOT delete or edit the old row — it is evidence for the next person who proposes the same losing option.

0 commit comments

Comments
 (0)