• v0.6.28 396d6e79d5

    v0.6.28 Stable

    pipeline-bot released this 2026-07-27 23:41:29 +00:00 | 20 commits to trunk since this release

    Fixed

    • Bound and redact status.migrationFailureMessage. The field was assigned
      the raw migrate error, and the shared harness's 512-byte truncation applies to
      condition messages and Events, not to status fields a controller assigns
      itself — so an arbitrarily large third-party error body landed verbatim on the
      object. The gitea SDK renders the response body into that error, and Forgejo
      is free to quote submitted fields back in its message, so the credentials the
      migrate request carried are now redacted by exact value (we hold them at the
      call site) before the message is truncated to 512 bytes. Ordinary errors pass
      through unchanged; the field is a diagnostic first.

    Fixed

    • Never prune branches off a repository this resource did not import. The
      branch-selection finalizer added in 0.6.26 ran whenever
      status.importPhase != "Succeeded", which is also what a CR reads when it
      ADOPTS a pre-existing populated repository (GetRepo 200) or when its status
      is lost to an etcd restore, a CR recreate, or a conflicted status write. In
      those states it deleted every branch except spec.importSource.branch off a
      canonical repository. Because the GitMirror XRD defaults branch to main,
      every mirrored repository was affected: an adopting reconcile of
      seanfarm-gitops would have deleted the protected trunk integration branch,
      and one of sean/linux every open feature branch. Branch selection is now
      gated on a new status.importedByThisResource, set only where the operator
      invokes Forgejo's migrate API, so adoption and status loss both settle as
      Succeeded without mutating the repository. The 0.6.26 steady-state test did
      not catch this: it kept Succeeded across reconciles, so it never exercised
      the two states that arm the pruner.
    • Never delete an empty repository this resource did not create. The
      empty-repository retry deletes before re-migrating, and its 60-minute cooldown
      cannot hold back a CR whose status was wiped — a zero lastMigrationAttempt
      reads as "no attempt recorded", not "not ours", so the delete fired on the
      first reconcile. It is now gated on the same ownership evidence; an empty
      repository we did not import is reported not-ready and left alone.

    Included changes (v0.6.27 -> v0.6.28)

    • 6a06eb2e0aa3 fix(repository): bound and redact status.migrationFailureMessage
    • 7046913985e3 fix(repository): gate destructive import steps on ownership evidence
    Downloads