Tags give the ability to mark specific points in history as being important
-
4.13.0
protectedRelease: pipeline 4.13.0a0855aa6 · ·## [4.13.0] - 2026-10-25 The `ci` image's Node moves 22 -> 24. A **minor**: no template input added, removed or renamed. Consumers with `engines` pinned below 24, or native modules built against Node 22, should check before bumping. ### Changed - **`ci` installs Fedora's `nodejs24` stream.** `node` and `npm` on PATH are 24 (was 22.23.1 from the unversioned `nodejs`), which satisfies Astro 7's `node >=22.23.4`. The build fails if node is older than 22.23.4, or `npm` or `wrangler` does not run.
-
4.12.0
protectedRelease: pipeline 4.12.04169c474 · ·dunn.dev/pipeline 4.12.0 The reference-check recipe in the ci image runs reference's justfile (just guard, just check) instead of its Makefile. A minor: no template input added, removed or renamed.
-
4.11.0
protectedRelease: pipeline 4.11.0fdd876f8 · ·dunn.dev/pipeline 4.11.0 The ci-go image ships Go 1.27.2 (security fixes in crypto/tls, net/http, http2 and textproto; GO-2026-6617, GO-2026-6613, GO-2026-6611). A minor: no template input added, removed or renamed.
-
4.10.0
protectedRelease: pipeline 4.10.0270cc4ec · ·dunn.dev/pipeline 4.10.0 `ci-runtime-node` moves to Node 24 (`ubi10/nodejs-24-minimal:10.2`). A **minor**: no template input added, removed or renamed. A `ci-runtime-node` consumer gets Node 24 on its next bump; the `ci` builder image stays on Node 22. `claude-drift-triage` defaults to `claude-sonnet-5-5`. ### Changed - **`ci-runtime-node`'s Node major moves 22 to 24.** The base is now `ubi10/nodejs-24-minimal:10.2` (was `nodejs-22-minimal`). A consumer gets Node 24 on its next `ci-runtime-node` bump; `bitwarden-cli` and `othala` are the consumers. The `ci` builder image is unchanged. - **`renovate-config.json`: the UBI image rules cover `nodejs-24` as well as `nodejs-22`.** The ubi9-to-ubi10 replacement rules and the clean `X.Y` tag rule list the `nodejs-24` and `nodejs-24-minimal` names beside the 22 ones, so `nodejs-24` rejects date-stamped tags too. The Node major is part of the image name, so Renovate never moves `nodejs-24` to another Node major on its own; behaviour for `nodejs-22` is unchanged. - **`claude-drift-triage`: default model is now `claude-sonnet-5-5`** (was `claude-sonnet-5`), the current Sonnet on the API. Consumers that set `model` are unaffected. ### Fixed - **`claude-drift-triage` reads the first text block of the response** instead of `content[0]`, and reports a refusal as such.
-
4.9.0
protectedRelease: pipeline 4.9.0553c1834 · ·dunn.dev/pipeline 4.9.0 `cloudflare-worker` gains an MR-only `validate-worker` job that runs `wrangler deploy --dry-run`, so a worker bundle that cannot build fails its merge request instead of main. A **minor**: one template input added (`cloudflare-worker`'s `mr_dry_run`, default `true`), none removed or renamed. A `cloudflare-worker` consumer gets the new job on its next merge request unless it sets `mr_dry_run: false`. `osv-verdict` no longer fail-closes on a repo that tracks files with Git LFS. ### Added - **New MR-only `validate-worker` job: `wrangler deploy --dry-run`.** Merge requests ran only `build`, which never bundles the worker entry script, so a wrangler or worker-dependency bump could pass its MR and fail on main at deploy. The job runs the deploy's own config parse and bundle (after the same `npm ci` when `needs_npm_install` is set) without uploading, and unsets the Cloudflare credentials, so it needs none. New input `mr_dry_run` (default `true`); `false` omits the job. ### Changed - **`renovate-config.json`: dead keys dropped, Go majors guarded.** The scan's `RENOVATE_FORCE` already nulls `schedule` and sets `prHourlyLimit: 0`, so `lockFileMaintenance.schedule`, the top-level `prHourlyLimit` and the default-valued `assignAutomerge` are gone; lockfile maintenance behaves as before. A top-level `postUpdateOptions` sets `gomodTidy` and `gomodUpdateImportPaths`, so a Go `/vN` major rewrites the import paths in source and keeps `go.sum` complete (Renovate skips `go mod tidy` on majors without the import-path option). It is top-level because a rule scoped to `gomod` is lost on a grouped branch whose first dependency is another manager; only the gomod manager reads these values. - **`renovate-config.json`: rule descriptions trimmed, dead rules removed.** Each description is now one or two sentences. The `dunn.dev/immutable/**` age exemption and the `basef` review rule are gone (every project they match is archived, and no live project references a `basef` image), and the disabled security-products rule drops its dead `pinDigests` key. The internal-catalogs note now states that `base-zfs` and `base-zfs-nvidia` automerge at every update type via the kmod rule. The resolved config is otherwise unchanged. - Routine tracking: `golangci-lint` 2.14.0 (`ci-go`), `uv` 0.12.19 (`ci-iac`), `glab` 1.119.0 (`ci`), rust 1.99 (`ci-rust`), golang 1.27, ubi10 and nodejs-22-minimal digests. ### Fixed - **`osv-verdict`: the merge-base checkout no longer fail-closes on a repo that tracks files with Git LFS.** A clone made by the runner helper carries LFS hooks in `.git/hooks`; `ci-go` has no `git-lfs`, so the post-checkout hook exited non-zero after git had moved HEAD and the job reported "base reachable but checkout failed" on every MR pipeline. The base and return-to-head checkouts now run with hooks and the LFS filter off (the scan reads lockfiles, not LFS blobs), and a genuine checkout failure still fail-closes, now printing git's own error. - **`signal-digest`: red default-branch pipelines are judged per source on completed pipelines.** The red-mains signal read only the newest pipeline on the default ref, so a running or pending pipeline hid a red one before it, and a later green push hid a failed scheduled pipeline. It now takes the newest completed pipeline of each source (push, schedule) and flags failed or canceled, tagging a schedule finding `[schedule]`. A push pipeline canceled by auto-cancel while a newer same-source pipeline exists is skipped rather than counted red, a project red on both sources counts once, and Renovate's "Detected empty commit" lockfile-maintenance no-op is a benign warning.
-
4.8.0
protectedRelease: pipeline 4.8.0d9cac485 · ·dunn.dev/pipeline 4.8.0 `container-image` stops publishing `:latest` from MR pipelines. A **minor**: no template input added, removed or renamed. A consumer that forces a build on every pipeline now gets `:<short-sha>` alone, unsigned, off the default branch and tags. ### Fixed - **`container-image`: `:latest` and its cosign signature are pushed only on the default branch or a tag pipeline.** Previously every firing — including a `BUILD_CI_IMAGE`-forced build on an MR pipeline — pushed and signed `:latest`, so a consumer that force-builds every pipeline (e.g. for a per-pipeline e2e image) republished and signed the public `:latest` from every MR, Renovate's included. Any other build now pushes `:<short-sha>` alone, unsigned. Single-arch and multi-arch manifest paths both changed; digest-file signing is unchanged.
-
4.7.0
protectedRelease: pipeline 4.7.065072233 · ·dunn.dev/pipeline 4.7.0 `ci-iac` now carries `restic` for iac's backup-lane CI job. The Renovate preset sheds rules that restated its defaults, lands monorepo majors as one MR and closes the kmod automerge gap; the token-expiry alarm is gone. A **minor**: no template input added, removed or renamed. - **`ci-iac` image**: bundles `restic`, pinned to a GitHub release and checksum-verified, same pattern as `uv`/`sops`. Renovate-tracked via the `# renovate: datasource=github-releases depName=restic/restic` ARG comment. - **`renovate-config.json`: the "Major updates" and "Fedora VERSION bumps" rules.** Each set only `automerge: false` for majors, which is Renovate's default, and nothing earlier in the preset, its extended presets, or any repo config grants a major automerge. Resolved effective config is unchanged: majors stay human-merged unless the dev-tooling rule grants automerge. - **`renovate-token-expiry` alarm.** Expiries are a maintenance convention, never a gate: a date-keyed job manufactures a red pipeline on a calendar day with no underlying failure. The `RENOVATE_TOKEN_EXPIRES` CI variable it read is retired next. - **`renovate-config.json`: monorepo majors land as one MR.** The major-updates rule no longer resets `groupName`, so `config:recommended`'s `group:monorepos` holds: `vitest` and `@vitest/*` majors arrive together instead of as two MRs that are each red without the other. Majors stay in the human-merge lane unless the dev-tooling rule grants automerge. - **`renovate-config.json`: internal-trust rules collapsed, kmod-lane defect closed.** The internal-trusted-catalog minor/patch/digest and major rules were two duplicate-scoped rules restating what the broad automerge rules already grant by later-rule-wins order — merged into one, matching `nomograph/pipeline`'s shape. `base-zfs`/`base-zfs-nvidia` were misclassified "non-kmod" and inherited automerge from that rule (live defect: `cairn/hagstone!5` showed Automerge: Enabled on a digest bump) — added to the kmod-review rule so ABI review wins by order. Removed the now-inert per-package `minimumReleaseAge: null` on the timestamp-less-docker rule now that `minimumReleaseAgeBehaviour: timestamp-optional` (4.5.1) covers it estate-wide, restoring the 7-day gate as a self-healing fallback.
-
4.6.1
protectedRelease: pipeline 4.6.1c319e3cf · ·dunn.dev/pipeline 4.6.1 Hotfix off the 4.6.0 tag. A **patch**: no template input added, removed or renamed. A consumer releasing aarch64 binaries bumps `rust-release-binary` to `@4.6.1`. ### Fixed - **`rust-release-binary`: the `aarch64-unknown-linux-gnu` and `aarch64-apple-darwin` legs build again.** Their `BUILD_CMD` was `cargo zigbuild`, so the recipe ran `cargo zigbuild build`, which cargo-zigbuild 0.23.0 rejects (`unexpected argument 'build' found`). `BUILD_CMD` now names the binary, `cargo-zigbuild`, whose `build` alias takes the same arguments. The `x86_64-unknown-linux-gnu` leg was never affected.
-
4.6.0
protectedRelease: pipeline 4.6.003c0206b · ·dunn.dev/pipeline 4.6.0 `ci-runtime-go` now builds on UBI10 (`ubi10/ubi:10.2` builder, `ubi10/ubi-micro:10.2` final), completing the estate's UBI10 train: consumers pin this catalog at fixed tags, so this release is what actually moves them off ubi9. A **minor**: no template input added, removed, or renamed. - **`ci-runtime-go`: base moved ubi9 → ubi10.** Builder `ubi10/ubi:10.2`, final `ubi10/ubi-micro:10.2`; the OCI `base.name` label now names the real base (!211). Zero ubi9 references remain in any Containerfile. - **`renovate-config.json`: UBI9→UBI10 `replacement` rules added; the cairn `platformAutomerge: false` interim override removed** (!240) — its premise died twice: the branch-head starvation was fixed in the cairn repos themselves, and Renovate's own merge `PUT` cannot satisfy this estate's sha-required merges. - Routine tracking: golang 1.26, `buildah:stable`, renovate 44, `anchore/syft`, ubi10 digests. - **`signal-digest`: `_request()` retries transient read timeouts** (3 attempts, short backoff; !251) — a single slow gitlab.com answer no longer kills the digest job. Real HTTP status answers propagate unchanged.
-
4.5.1
protectedRelease: pipeline 4.5.19328a177 · ·pipeline 4.5.1 `ci-go` now builds on go1.26.6, closing the five stdlib advisories below. Consumers pin `ci-go` at a fixed catalog tag rather than `:latest`, so this tag is what actually delivers the fix — each consumer still has to bump its pinned ref and re-run `audit` before govulncheck goes quiet. A **patch**: no template input added, removed, or renamed. - **`ci-go`: Go toolchain digest bumped past go1.26.5 to close five stdlib CVEs.** `containers/ci-go.Containerfile`'s `mirror.gcr.io/library/golang:1.26` digest pin landed on go1.26.6-equivalent content via the routine digest-track lane (renovate!213, merged 2026-08-15; folded into !219). Fixes, as reported by `go-audit`'s govulncheck against consumers on the affected toolchain: - **GO-2026-5972** / CVE-2026-33818 — `encoding/asn1` `Unmarshal` lacked a recursion limit, allowing stack exhaustion on deeply-nested input. - **GO-2026-5026** / CVE-2026-39821 — `net/http` (via `golang.org/x/net/idna`) accepted ASCII-only Punycode labels it should have rejected, a hostname validation bypass. - **GO-2026-6218** (`net/url` quadratic complexity), **GO-2026-6090** (`crypto/tls` post-handshake message limit), **GO-2026-6088** (`encoding/xml` recursion depth) — same go1.26.6 fix, caught in the same scan. The fix reached `origin/main` before this entry did: the `ci-go` Containerfile is pinned by digest, tracks the upstream `golang:1.26` tag, and Renovate's digest-update lane (`matchUpdateTypes: [digest, pinDigest]`, `minimumReleaseAge: null`) auto-merges those on green CI regardless of cause — it is not the `vulnerabilityAlerts`-specific security lane, which targets manifest-declared package advisories, not a Containerfile `FROM` digest. The gap was cadence, not policy: the fixed image published upstream 2026-08-13T20:27Z; the estate's next scheduled Renovate scan didn't run against it until 2026-08-15T03:00Z, roughly a day and a half later. This CHANGELOG entry is the only thing this fix needed that automerge couldn't supply. **Not yet propagated**: consumers pin `ci-go` at a fixed catalog tag (`bairn@4.4.1`, `tutti@2.1.2`, `qobuz@2.4.0`, all pre-dating this fix) — none will see it until a new catalog tag ships and each consumer bumps its pinned ref. The `go-audit` job is `allow_failure: true`, so none of this blocked anything; it has been failing silently since well before this CVE pair (bairn's `audit` job has red history back to at least 2026-05-18). -
4.5.0
protectedRelease: pipeline 4.5.02213983b · ·pipeline 4.5.0 Two threads. The `validate-*` self-validation harness had never run — every component was included at `@$CI_COMMIT_SHA`, `$[[ component.version ]]` resolves empty for a SHA ref, so each job pulled `ci-rust:` and died at container attach, masked by `when: manual` + `allow_failure: true`. It runs now, and immediately caught a stale Claude model id, a `container-image` publishing path bug, and an unbound-variable class in `pipeline.just`. It is deliberately still not gating: the repo has no language fixtures, so every go/rust/node validate job would fail on that alone, and a permanently-red gate on the L1 catalog is worse than none. The second thread is supply-chain hygiene: Fedora and UBI10 repoints, and an end to the recurring class where GitLab garbage-collects its own published analyzer digest and reddens a pipeline we never touched. A **minor**: no template input added, removed, or renamed. - **Renovate: UBI9 to UBI10 replacement rules.** `replacement` is its own updateType, separate from `major` — the human-review lane never saw these. - **`validate-*` harness is playable.** Image-tag interpolation fixed and wiring corrected. Stays `manual` + `allow_failure` by deliberate decision until language fixtures exist. - **`ci-runtime-node` on UBI10** (`ubi10/nodejs-22-minimal`), removing ten unfixable HIGH curl/libcurl CVEs — 0 of 107 measured findings had a Red Hat fix, so the base moved rather than the finding being waived. - **Fedora containers repoint** `quay.io` to `registry.fedoraproject.org`. - **hadolint checksum** reads the combined `checksums.sha256` (upstream 2.15.0+). - **Rust jobs build, test and clippy `--locked`.** - **`secret-verdict` no longer pins a digest.** GitLab GC'd its own published `security-products/secrets` digest, which reddened this pipeline twice on an image we never changed; it now tracks the immutable version tag. - **`claude-drift-triage`** default model id corrected. - **`lint-includes`** tolerates an `image:` override on suppressed jobs. - **Eleven `pipeline.just` recipes guarded against unbound `CI_COMMIT_TAG`** under `set -u`. Release paths hard-fail with a clear message; artifact paths skip cleanly. A silent `exit 0` in a release path would report green while publishing nothing. - **`signal-digest.py`** discovers group runners dynamically instead of checking a hardcoded id pair, and its wedged-MR predicate now catches conflict-plus-armed. The old check reported a permanent false WARN on a dead runner while covering neither runner that mattered. - **`platformAutomerge: false` scoped to `dunn.dev/cairn/**`** (was estate-wide), moving the decision into Renovate's own retry loop so it self-heals. - **Stop digest-pinning `registry.gitlab.com/security-products/**`.** Pinning a digest we do not control against a registry that GCs it converts vendor housekeeping into a hard red pipeline.
-
4.4.0
protectedRelease: pipeline 4.4.0f59386d7 · ·dunn.dev/pipeline 4.4.0 Minor: secret detection that can actually fail a pipeline. One new component (secret-verdict) and one new optional input on automerge-gate (secret_job). Nothing removed or renamed, and "secret" is deliberately absent from the required-checks default, so an existing consumer that upgrades renders an identical materialized job set and an identical gate verdict. Adoption is opt-in, per repo. Added - secret-verdict: GitLab's own Security/Secret-Detection template cannot block a leak. Its analyzer shells out to gitleaks with --exit-code 0, so the job exits clean even when it finds a credential -- the findings go into gl-secret-detection-report.json and nowhere else. Flipping that template's allow_failure to false does not fix it; it only makes operational faults blocking. This component runs the same analyzer over the same scan surface, so migration is a swap of the include rather than a change in what gets flagged, then parses the report itself and derives its own verdict. It emits CHECK_SECRET=pass|fail as a dotenv for automerge-gate and also exits nonzero on a finding -- unlike osv-verdict, which always exits 0 and leaves blocking to the gate. That divergence is deliberate: a verdict-only component would leave a repo with no automerge-gate still unable to fail, reproducing the exact bug. Fail-closed throughout: a missing, zero-length, schema-foreign, or non-array report, and any nonzero analyzer exit, all emit fail and exit 1 -- absence is never read as cleanliness. Scope control is excluded_paths, visible in the diff. There is deliberately no severity knob and no allow_failure input. Proven with a planted-secret probe. Changed - automerge-gate: new secret_job input plus a matching needs: entry, handled exactly like osv_job. Consumers opt in by adding "secret" to required-checks once they include the component. Because secret-verdict reddens the pipeline itself, the gate is skipped rather than run-and-blocking when a leak is found -- GitLab skips the dependents of a failed needs: job. The pipeline is red, and automerge blocked, either way. - The catalog meta-pipeline dogfoods the new slot: secret-verdict runs for real alongside osv-verdict, and this repo's own automerge-gate sets required-checks "osv,secret". - check-principle-image-tracking-version gains a second documented exception for the GitLab secret-detection analyzer image, pinned tag@digest and Renovate-tracked. Fixed - Renovate: security-fix automerge now requires a real pipeline rather than a green dashboard park. vulnerabilityAlerts keeps automerge true but now also sets platformAutomerge false, so the merge runs through Renovate's own checkAutoMerge instead of GitLab native automerge, which registers a branch carrying zero status checks as mergeable immediately. Scoped to vulnerabilityAlerts only; every other automerge lane is untouched. No consumer migration ships with this tag. patinate, kits, iac and qobuz still include the fail-open upstream template; moving them is a separate decision. Tag convention unchanged since 2.0.0: bare semver, no v-prefix. See CHANGELOG.md for the full entry.
-
4.3.1
protectedRelease: pipeline 4.3.1025295a0 · ·dunn.dev/pipeline 4.3.1 Patch: reference-check migrates off the magic-name GITLAB_TOKEN group variable to ESTATE_READ_API_TOKEN, with a fallback during the dual-variable migration window. No new inputs, no removed/renamed inputs. Fixed - reference-check: GITLAB_TOKEN (provisioned in 4.2.0) is a magic name glab prioritizes over CI_JOB_TOKEN autologin for every glab call across every job in the dunn.dev group -- not just this recipe's own reads. A read_api-only token squatting on that name silently broke dunn.dev/cairn/pipeline's create-release job (403 insufficient_scope: glab picked up the read-only group token instead of the write-capable CI_JOB_TOKEN). Migrated the recipe to read ESTATE_READ_API_TOKEN instead, falling back to GITLAB_TOKEN during the migration window, scoped inside the recipe's own subshell only -- nothing exported process-wide. - reference-check: no longer exports an empty GITLAB_TOKEN. A naive GITLAB_TOKEN="${ESTATE_READ_API_TOKEN:-${GITLAB_TOKEN:-}}" would export an empty GITLAB_TOKEN when neither variable is set, and an empty magic-name variable shadows CI_JOB_TOKEN autologin exactly like a wrong-scoped one -- the identical failure mode this release exists to fix, reintroduced one layer down. Now unsets GITLAB_TOKEN when the resolved value is empty, so autologin sees a genuinely clean environment. The GITLAB_TOKEN fallback stays in place only for the dual-variable migration window and should be dropped once the group GITLAB_TOKEN variable is deleted. Tag convention unchanged since 2.0.0: bare semver, no v-prefix. See CHANGELOG.md for the full entry. -
4.3.0
protectedRelease: pipeline 4.3.07a8b682c · ·4.3.0 — cloudflare-worker: deploy-time script deps + worker_secret_variables Graduated from dunn.dev/gals after a live deploy failure: the deploy job now honors needs_npm_install (wrangler bundles the worker script at deploy time), and an opt-in worker_secret_variables input populates Worker secrets from CI variables via wrangler secret bulk.
-
4.2.0
protectedRelease: pipeline 4.2.055316958 · ·dunn.dev/pipeline 4.2.0 Four correctness fixes, no new inputs, no removed/renamed inputs -- follows 4.1.0's minor-not-patch precedent. Fixed - container-image: builder image (quay.io/buildah/stable) repinned off a :latest that quay.io proved (2026-08) rebuilds in place across v1.43.1, v1.43, v1, and latest alike -- untracked drift, not "always current." Repinned to v1.43.1-immutable@sha256:fc649e18..., a real non-rebuilt tag Renovate can track and bump. - renovate.json templates/*.yml customManager: the sole matchString required a quoted default: value, so container-image.yml's bare image: quay.io/buildah/stable:latest was invisible to it. Added an image:/name: key variant (quoted or bare, digest optional). - reference-check: every API-backed assertion in dunn.dev/reference's primitives (check_gitlab_setting, check_registry_cleanup_coverage) was a silent no-op in CI since introduction -- ci never installed glab, the recipe never set PROJECT_ID. Fixed: ci now bakes glab (checksum-verified, version-pinned to harness/mise.toml's gitlab-org/cli pin); the recipe exports PROJECT_ID from CI_PROJECT_ID plus GLAB_ENABLE_CI_AUTOLOGIN=true. That alone still 403'd on the general Projects API (CI_JOB_TOKEN's job-token-access table doesn't cover GET /projects/:id). Closed by a read_api group access token, wired as group CI variable GITLAB_TOKEN (masked, unprotected, glab's own higher-precedence-than-CI_JOB_TOKEN env var -- confirmed via `glab auth login --help`, and empirically: a CI_JOB_TOKEN-authenticated call would 403 on this endpoint rather than return real settings). Proven end-to-end against a real job (dunn.dev/reference, throwaway branch, this catalog's own ci image): check_registry_cleanup_coverage reads and reports a real live value (PASS ... cleanup disabled (enabled=false), job 15676948764), and a throwaway deliberate-violation assertion reports a real FAIL against real data (FAIL ... default_branch = main (expected /this-branch-does-not-exist/), job 15677067064). fail_on_violation stays false estate-wide: all 9 current consumers were audited against live state and every one fails at least one contract today (pre-existing, unrelated gaps). Fix violations first, then enforce. - renovate-config preset: the cloudflare workers ecosystem group matched almost nothing -- matchUpdateTypes:["major"] excluded wrangler's peer bump to @cloudflare/workers-types ^5 at 4.108.0, a minor, so the group MR only ever carried the types half (the exact ERESOLVE the rule existed to prevent). Dropped matchUpdateTypes entirely. Tag convention unchanged since 2.0.0: bare semver, no v-prefix. See CHANGELOG.md for the full entry.
-
4.1.0
protectedRelease: pipeline 4.1.0277024d5 · ·dunn.dev/pipeline 4.1.0 Minor: additive plus fixes. No input removed or renamed, no existing default behaviour changed. Consumers pick this up by bumping their component pins. Added - model-id-drift (new, opt-in): fails when a consumer's tracked working tree carries a hardcoded claude-(opus|sonnet|haiku) major below the declared current_ga_major (default "5"). No network access; pure regex over the already-checked-out tree. No repo is auto-enrolled. There is no Renovate datasource for Claude model ids, so a hardcoded id rots invisibly -- confirmed stale on dunn.dev/pi and dunn.dev/skald.md while Opus 5 was GA. - ci-go bakes osv-scanner, ci bakes hadolint (both checksum-verified release binaries). osv-verdict now runs on ci-go, so the gate binary is no longer fetched fresh on every MR across the estate. Changed -- renovate-config preset - go.mod indirect dependencies now propose an MR only when they carry an active OSV/GHSA alert (security:gomodIndirectSecurityUpdates). Surfaced by bairn's kin-openapi indirect dep needing a hand-diagnosed fix. - Internal-artifact MAJORs exempt from minimumReleaseAge; automerge stays false (age delay and human review are separate knobs). Closed two coverage gaps while widening: the bare-catalog depName form was never matched, and the gitlab-releases exemption is now scoped by package name so it no longer silently covered upstream gitlab-org/cli. - mergeConfidence:all-badges, display-only, for the human majors-review queue. - minimumReleaseAge:null for four evidenced timestamp-less packages (envoy via mirror.gcr.io, two immich images, @dunn.dev/reference on GitLab's npm registry) -- a strand fix by exact package name, with explicit automerge:false, not a registry-wide trust exemption. Fixed -- osv-verdict - Go call analysis runs for real now that the job is on ci-go. The gate blocks on called=true or called=unknown; a finding call analysis proves unreachable is still logged and kept in the artifact, just not gate-blocking. - Default-branch pushes diff against CI_COMMIT_BEFORE_SHA instead of full-scanning, closing the green-MR-then-red-main asymmetry. - The MR diff base was a silent no-op: git stash swept up the untracked head-scan outputs and nothing ever popped it, so the verdict was pass regardless of whether a new finding existed. Fail-open under a fail-closed gate, on every diff-mode run. Head scan outputs now survive outside the tree. Fixed -- automerge-gate, osv-verdict - Both jobs now instantiate on a bare branch pipeline with no open MR yet. The prior rules matched only merge_request_event or the default branch; audited across 97 consumer projects, ~25 had zero gate coverage in exactly that gap, where the job never emitted and needs:optional read absent rather than failed. - The clause shipped in a two-rule form and was then consolidated to one (CI_COMMIT_BRANCH && CI_OPEN_MERGE_REQUESTS == null). That is a simplification, not a behaviour change -- both forms render identically. Verified pre-tag: a synthetic consumer POSTed to ci/lint at three refs with components pinned by SHA, carrying probes that prove the rendered variable context. Gate jobs instantiate on a no-MR branch, are correctly suppressed on a branch with an open MR, and main is unchanged. A grandparent control at the commit before the branch clause existed confirms the harness discriminates: the gate jobs are absent there on the same ref and present after. Also: baked tool versions advanced (cosign 3.1.2, syft 1.49.0, just 1.57.0; ci-iac uv 0.11.32, sops 3.13.3), image ARG and template spec-input default moving in lockstep.
-
4.0.1
protectedRelease: pipeline 4.0.120226a3f · ·dunn.dev/pipeline 4.0.1 Fix: ci-runtime-go ships the CA trust bundle + tzdata. The UBI-micro base shipped neither, so a static (CGO-off) Go binary doing outbound TLS failed x509 verification on its first call -- caddy's Let's Encrypt ACME + Cloudflare DNS-01, and bairn's Famly API (total-failure for both). Every other ci-* image already installed ca-certificates on purpose; ci-runtime-go was the outlier. Staged from a throwaway full-UBI builder; final image stays package-manager-free (+3.5MB). ci-runtime-node unaffected (Node uses its own compiled-in root store). Adversarially verified pre-tag: the built image carries 146 valid PEM certs (incl. ISRG Root X1/X2) at Go's x509 paths.
-
4.0.0
protectedRelease: pipeline 4.0.054188f8b · ·dunn.dev/pipeline 4.0.0 Breaking major (dead-surface removal + supply-chain hardening). Removed (zero-consumer, estate-wide verified): - cloudflare-pages component + recipes/validate slots (use cloudflare-worker) - release-create `extra_sbom_jobs` input + upload-extra-sbom job/recipe Supply chain: - ci image bakes osv-scanner + cosign (checksum-verified) → osv-verdict gate and node-publish signing install nothing at runtime - syft installer pinned to a release tag (was mutable main) - template tool-version defaults are Renovate-tracked (customManager) Lint: lint-includes (supersedes lint-suppression) — structural YAML bijection + suppression coverage. cosign/syft fallback defaults aligned to baked versions; go-sbom skips .sha256 sidecars. Merged via !96 (rebased onto current main; pipeline green incl. osv-verdict).
-
3.1.0
protectedRelease: pipeline 3.1.0b2d0bfc4 · ·3.1.0 - pin-audit + preset improvements Adds the pin-audit component (I1 enforcement: fails the build on an image pin Renovate cannot track forward -- bare @sha256 / commit-SHA tag) + the ADOPTION.md adoption profile, now adoptable by consumers (pin-audit postdated the 3.0.0 tag, so pin-audit@3.0.0 never resolved). Plus renovate-config preset improvements accumulated since 3.0.0 (abandonment signal, automerge-pin, astro/vitest ecosystem grouping, rebaseWhen=behind-base-branch, lockFileMaintenance release-age exemption, trusted-upstream fast-track, mise-gitlab manager de-dup) and ci/ci-iac fixes. No breaking change: every component's inputs and behavior are unchanged from 3.0.0. Minor bump.