openova/core/controllers
e3mrah 1b29c7178e
refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136)
CC1 (#1135) promoted the easy-to-merge shared internals (semver, render,
placement, labels) but explicitly DEFERRED the Gitea HTTP client because
the four Group C controllers (slices C1-C4) shipped four divergent
client surfaces:

  * organization (C1): Org+Repo CRUD with `Org`/`Repo` struct returns;
    `EnsureRepo(ctx, org, name, desc, private) (Repo, error)`
  * blueprint (C3): File CRUD via `*FileResponse`;
    `EnsureRepo(ctx, org, repo) error`
  * environment (C2): File CRUD via `*FileContent` + `UpsertFile` (with
    committer attribution); BaseURL must include `/api/v1`
  * application (C4): File CRUD via `*FileResponse`;
    `EnsureRepo(ctx, org, repo) error` + `EnsureBranch`

The two `EnsureRepo` shapes collide on signature. CC2's task: design the
SUPERSET, migrate every controller without behavior change.

What CC2 ships:

* `core/controllers/internal/gitea/{client,DESIGN}.go` + `client_test.go`
  — single unified Client. The SUPERSET method list:

    Org+Repo CRUD                  (won from): C1 — only implementer
      GetOrg(ctx, slug) (Org, error)
      CreateOrg(ctx, slug, fullName, desc, vis) (Org, error)
      EnsureOrg(ctx, slug, fullName, desc, vis) (Org, error)
      GetRepo(ctx, owner, name) (Repo, error)
      CreateRepo(ctx, org, name, desc, private, autoInit, defBranch) (Repo, error)
      EnsureRepo(ctx, org, name, desc, private) (Repo, error)  ← C1 surface; C3+C4 callers discard the Repo

    EnsureBranch(ctx, org, repo, branch) error                 (won from): C4
    GetFile(ctx, org, repo, branch, path) (File, error)        (won from): C2 — has repo-vs-file 404 distinction
    PutFile(...) (File, committed bool, err error)             (won from): C4 signature + C1 byte-equal short-circuit + C2 PutFileOpts for committer
    DeleteFile(ctx, org, repo, branch, path, msg) (bool, error) (won from): C3/C4 (identical)

    Errors: ErrOrgNotFound, ErrRepoNotFound, ErrFileNotFound + HTTPError
            + IsNotFound() + IsConflict() — covers every prior helper.

  BaseURL semantics canonicalized: takes Gitea root WITHOUT `/api/v1`;
  client appends internally. environment-controller's GITEA_API_URL
  default updated to drop the `/api/v1` suffix.

  26 tests covering every reconciler-relevant code path including:
    * EnsureOrg / EnsureRepo / EnsureBranch find-or-create + 422/409 races
    * PutFile create / update / byte-equal short-circuit / with author
    * GetFile / DeleteFile typed sentinels (ErrFileNotFound vs ErrRepoNotFound)
    * IsNotFound / IsConflict coverage of typed sentinels + HTTPError

* Per-controller migration:
    * organization (C1): EnsureOrg/EnsureRepo same; PutFile arg-order
      swap (path↔branch — C1 was the outlier) and `(_, _, err :=)`
      triple. 1 reconciler call site updated.
    * blueprint (C3): EnsureRepo wrapped with the canonical description
      literal + private=false (catalog Org). 1 reconciler call site.
    * environment (C2): GiteaClient interface updated; UpsertFile →
      PutFile with PutFileOpts for committer attribution; *Org → Org.
      cmd/main.go drops trailing `/api/v1` from default GITEA_API_URL.
      1 reconciler call site + 1 fake.
    * application (C4): Gitea interface updated to match new shape;
      EnsureRepo wrapped with description + private=true literal.
      1 reconciler call site + 1 fake.

* Each per-controller `internal/gitea/` directory deleted (4 dirs,
  ~2400 LoC removed).

Test-coverage delta:
  Pre-CC2 client tests:  4 + 4 + 10 + 5 = 23 tests across 4 packages
  Post-CC2 shared tests: 26 tests in one package (+3 net)
  Per-controller tests:  unchanged in count, all still GREEN

Verified locally:
  go vet ./...                                 — clean
  go test -count=1 -race ./...                 — every package GREEN
  go build per controller cmd/                 — all 5 binaries link

Architecture rules preserved:
  * No behavior change for any existing call site (the SUPERSET is
    strictly a union; reconciler logic byte-identical).
  * Single shared go.mod; no new module path.
  * Idempotency anchor (PutFile byte-equal short-circuit) preserved.
  * No new Gitea API methods beyond union of existing usage.
  * No deploy-manifest changes (env-controller's URL drop is
    cmd-side default; no chart template touches GITEA_API_URL yet).

Co-authored-by: hatiyildiz <hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:18:51 +04:00
..
application refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136) 2026-05-09 01:18:51 +04:00
blueprint refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136) 2026-05-09 01:18:51 +04:00
environment refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136) 2026-05-09 01:18:51 +04:00
internal refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136) 2026-05-09 01:18:51 +04:00
organization refactor(controllers): unified Gitea client SUPERSET API + consolidation (CC2, #1095) (#1136) 2026-05-09 01:18:51 +04:00
useraccess refactor(controllers): promote duplicated internal/ packages to shared core/controllers/internal/ (CC1, #1095) (#1135) 2026-05-09 00:54:42 +04:00
go.mod refactor(controllers): promote duplicated internal/ packages to shared core/controllers/internal/ (CC1, #1095) (#1135) 2026-05-09 00:54:42 +04:00
go.sum refactor(controllers): promote duplicated internal/ packages to shared core/controllers/internal/ (CC1, #1095) (#1135) 2026-05-09 00:54:42 +04:00