• v0.4.13 754aa26cce

    v0.4.13 Stable

    pipeline-bot released this 2026-07-23 12:52:06 +00:00 | 0 commits to main since this release

    Fixed

    • Best-effort progress and failure status writes now use the shared conflict
      retry path, so a routine Kubernetes 409 Conflict no longer drops the
      condition that explains why reconciliation failed.
    • reconcile/testkit.Env.Stop is safe after envtest setup fails, preserving the
      original startup error instead of masking it with a nil-pointer panic in suite
      teardown.

    Included changes (v0.4.12 -> v0.4.13)

    • 8b112a021ded fix(reconcile): retry best-effort status conflicts
    Downloads
  • v0.4.12 c6620a86f8

    v0.4.12 Stable

    pipeline-bot released this 2026-07-17 09:42:17 +00:00 | 4 commits to main since this release

    Added

    • operator.mk — the canonical shared Makefile scaffolding. Tool pins + installers
      (ENVTEST_VERSION derived from controller-runtime, ENVTEST_K8S_VERSION derived
      MINOR-only from k8s.io/api — full-patch derivation failed live on 1.35.2) and the core
      dev-loop targets. Operators vendor a copy + include it; the lib-bump autoland
      re-syncs the copy from each release tag, so toolchain scaffolding can never silently
      drift again (kratos sat on release-0.19/golangci-v1 for months unnoticed).

    Included changes (v0.4.11 -> v0.4.12)

    • d32a8df94166 feat(operator.mk): canonical shared Makefile scaffolding for the operators
    Downloads
  • v0.4.11 b1a77ace25

    v0.4.11 Stable

    pipeline-bot released this 2026-07-16 14:26:48 +00:00 | 8 commits to main since this release

    Added

    • The extraction wave — the shared surfaces every operator hand-rolled:
      • Config.IsRemoteGone: the harness folds "remote already gone" Delete errors into an
        idempotent finalize (the status-lost-CR credential-leak class was fixed independently
        in two repos within 24h; unmatched errors keep today's semantics, so deliberate holds
        like kratos's ambiguous-miss grace still work).
      • reconcile.Metrics (+ Config.Metrics/MetricsController): reconcile passes,
        durations, status-write outcomes, and InstrumentedCall/RecordCall for API
        clients — namespaced so adopting operators keep their metric names; domain gauges
        stay operator-side. Replaces kratos's 173-line kit + openbao's ~300-line middleware,
        and gives forgejo/pipelines-operator/minio coverage for free.
      • SecretValue/HashValue/HashCanonical: the write-only-secret drift leaves,
        supporting BOTH fingerprint conventions (hash for high-entropy material;
        resourceVersion for low-entropy, per kratos's documented security choice).
      • httpkit: ClusterCATransport (trust-bundle + shared pooling tuning),
        CredentialCache[C] (rotation-aware client cache — the VSO/ESO rotated-token
        contract), BoundedRead/ErrorExcerpt (bounded to the condition-message limit).

    Included changes (v0.4.10 -> v0.4.11)

    • adb1dcf72a52 feat(extract): IsRemoteGone delete fold + Metrics kit + secret-drift helpers + httpkit
    Downloads
  • v0.4.10 7fac3cfda0

    v0.4.10 Stable

    pipeline-bot released this 2026-07-15 17:20:35 +00:00 | 12 commits to main since this release

    Added

    • reconcile/testkit — the shared test surface consumer operators have been
      copy-pasting: FakeCR/FakeCRRetain schemed test CRs, StubHandler scripted
      handler family, NewScheme/NewClient/GetObject/Condition helpers,
      ConflictOnceClient, BaseConfig, and StartEnvtest (framework-agnostic envtest
      bring-up with bin/k8s binary discovery — replaces the ~120-line suite_test.go
      duplicated across every operator). The lib's own harness suite now runs on it.
    • Inverse-gap tests promoted from operator repos to the source:
      StatusUpdateBestEffort (was only proven in openbao), LastTransitionTime
      preservation through the Run flow (was openbao's 386-line e2e suite),
      RemoveFinalizer no-op-when-missing, and MirrorStatus PhaseFailed/PhaseDeleting
      hook coverage (was only proven via kratos's mirror tests).

    Included changes (v0.4.9 -> v0.4.10)

    • 66eebb3bf593 feat(testkit): shared test surface + inverse-gap tests promoted from operators
    Downloads
  • v0.4.9 fc12440d11

    v0.4.9 Stable

    pipeline-bot released this 2026-07-15 14:48:19 +00:00 | 16 commits to main since this release

    Fixed

    • reconcile: a Ready=False condition with an empty caller-supplied reason is no longer emitted —
      ReadyFalse now defaults an empty reason to NotReady. The Kubernetes API rejects a condition with
      an empty Reason (422 FieldValueRequired), so an outcome that reached the failure path with no
      reason previously produced an unwritable condition (silent status-write failure). (ReadyTrue was
      already safe — it always uses a constant reason.) (+TestReadyFalse_DefaultsEmptyReason)
    • reconcile: the dry-run converge path now calls MirrorStatus before persisting, like every
      other status-writing path. A dry-run CR is Ready, but the legacy mirrored fields were left
      reflecting the prior phase — permanently inconsistent with Ready=True for operators that use a
      MirrorStatus hook. (No-op when MirrorStatus is nil, so operators without one are unaffected.)

    Included changes (v0.4.8 -> v0.4.9)

    • 6d458960cddb fix(reconcile): default empty Ready=False reason (422 guard) + mirror on dry-run
    Downloads
  • v0.4.8 921ce217df

    v0.4.8 Stable

    pipeline-bot released this 2026-07-14 20:17:47 +00:00 | 20 commits to main since this release

    Fixed

    • reconcile: dry-run is now symmetric on delete — a dry-run CR no longer performs a
      real Resolve+Delete against the remote on deletion (which destroyed state it promised
      never to touch, or wedged undeletable under HoldUntilSuccess). The K8s-side Cleanup
      and finalizer removal still run, so the CR deletes cleanly. (+TestRunDeleteDryRun)
    • reconcile: the Degraded condition message is now bounded by truncateMessage (like
      Ready=False/SetCondition), so a splatted remote-error body can't exceed the etcd
      condition-message bound or over-disclose.
    • reconcile: a Degraded/failed object no longer retains a stale Progressing=True
      (self-contradictory Ready=False + Degraded=True + Progressing=True);
      markDegradedStyle clears it — covering the converge failPath and both delete-path
      failure calls.
    • reconcile: the converge dry-run gate now clears any stale Degraded/Progressing left
      by a prior non-dry-run reconcile, so a dry-run CR isn't reported Ready and Degraded
      at the same time.

    Included changes (v0.4.7 -> v0.4.8)

    • 530056d18615 docs(changelog): promote Unreleased to [0.4.8] (mid-flight release recovery)
    • df747dd747c9 docs(changelog): add Unreleased section for the harness fixes (v0.4.8)
    • 2ec43c5f29d7 fix(reconcile): 4 shared-harness bugs (dry-run delete, Degraded truncation, stale Progressing)
    • ed2fa525f665 fix(cicd): auto-resolve CHANGELOG land conflicts via .gitattributes merge=union
    • b040ae77b5d9 fix(ci): pin golang:1.25 builder base by digest
    • c3d82fe13b67 docs(readme): Recorder events are size-bounded, not sanitized
    • 7d62c566920c chore(staging): open v0.4.8-dev dev cycle
    Downloads
  • v0.4.7 623b0cb595

    v0.4.7 Stable

    gitea_admin released this 2026-07-01 14:36:09 +00:00 | 34 commits to main since this release

    Added

    • reconcile: unit coverage for Cadences.withDefaults — the previously-unexercised
      defaulting branches. TestCadencesWithDefaults asserts each zero-value field
      resolves to its documented default (Ready 5m, Transient 30s) and that the
      subtle Progressing → Transient fallback resolves to the already-defaulted
      Transient: a zero Progressing tracks the resolved Transient (explicit 45s
      when set, else the 30s default) rather than a stale zero, while explicit values
      are preserved intact. Every other harness test sets all three cadences explicitly,
      so these branches had no coverage.
    Downloads
  • v0.4.6 2ce70ab450

    v0.4.6 Stable

    gitea_admin released this 2026-07-01 10:18:41 +00:00 | 39 commits to main since this release

    Added

    • reconcile: unit coverage for two previously-untested public-API contracts —
      ReasonedError.Unwrap (errors.Is/errors.Unwrap transparency, so a
      Failf(reason, "…: %w", cause) stays matchable by errors.Is(err, cause) while
      keeping its Degraded reason recoverable via ReasonOf) and the
      RequeueTransientOf plain-error fallback (a non-reasoned error classifies as
      non-transient). reason.go previously had only incidental coverage from
      reconcile_test.go.

    Changed

    • CI: route Go module fetches through the in-cluster Athens proxy (GOPROXY, with a
      direct fallback) and add buildkit gomod / go-build cache mounts to
      ci.Dockerfile — a cold build no longer re-downloads the whole module graph from
      proxy.golang.org.
    Downloads
  • v0.4.5 91e852b93b

    v0.4.5 Stable

    gitea_admin released this 2026-06-28 16:09:24 +00:00 | 47 commits to main since this release

    Changed

    • First release shipped through the consolidated, ArgoCD-delivered pipeline —
      the go-library-tag taxonomy now rides the same shared templates as zdns
      (pipeline-build-buildkit validate + pipeline-test-noop + pipeline-promote-tag,
      from sean/pipelines via the registry ApplicationSet), no per-project scripts/ set.
    Downloads
  • v0.4.4 6d44bc0675

    v0.4.4 Stable

    gitea_admin released this 2026-06-28 10:36:36 +00:00 | 48 commits to main since this release

    Fixed

    • The reconcile harness no longer stamps ObservedGeneration on a Converge
      error under ObservedGenOnConvergedOnly. A failed generation is
      not-yet-converged — exactly like a Progressing one — and must stay
      "unobserved", or a consumer's ObservedGeneration-keyed convergence fast path
      (kratos) short-circuits the failed generation on the next pass and masks the
      error as Ready. ObservedGenOnAllSuccess is unchanged (it records the failing
      generation so kstatus reads Failed, not InProgress). Adds
      TestRunErrorObservedGenPolicy — the error-path mirror of the existing
      Progressing/ObservedGeneration test.
    Downloads