| title | 57. Repos management for per-repo installations | |||||
|---|---|---|---|---|---|---|
| status | Accepted | |||||
| relates_to |
|
|||||
| topics |
|
Date: 2026-06-17
Accepted
Annotation (2026-08-18): The manifest format was simplified in
#6346: the
forge: wrapper and defaults.forge were replaced with top-level
github: and gitlab: platform sections; per-repo entries use name:
instead of repo: and always use object form; NullableString was
replaced with a "none" sentinel.
Builds on ADR 0033 (per-repo
installation mode) and ADR 0048 (automatic
updates). Core commands work independently of ADR 0048;
version-management commands require its --upstream-ref mechanism.
Per-repo installation (ADR 0033)
is fullsend's target model — each repo is self-contained with its own
.fullsend/ directory, shim workflow, WIF provider, variables, and
secrets. However, the per-repo install path (runPerRepoInstall() in
admin.go) handles one repo at a time. Organizations managing tens or
hundreds of repos across multiple GitHub orgs face three gaps:
- No bulk operations. Installing on 50 repos means 50 manual runs.
- No enrollment inventory. Discovering which repos have fullsend requires scanning for guard variables across all repos — an O(n) API operation with no centralized record.
- No drift detection. No reference state to compare against: "which repos have a stale mint URL?" or "which repos are still on v2.1.0?"
Per-org's enrollment system provides these operationally but at the cost of a dedicated config repo, org-level variables, enrollment PRs, reconciliation scripts, and three-level workflow nesting. A thin orchestration layer over existing per-repo machinery can provide the same value without that infrastructure.
Add a fullsend repos subcommand group that manages per-repo
installations at scale via a declarative repos.yaml manifest.
Target persona: platform administrators (SRE/DevOps) managing
fullsend across an organization. Individual repo owners continue using
fullsend github for single-repo setup. The relationship is analogous
to Terraform vs cloud provider CLIs.
Subcommands:
| Command | Purpose |
|---|---|
repos init |
Discover existing installations, generate manifest |
repos status |
Read-only comparison of manifest vs actual state |
repos install |
Provision fullsend on uninstalled manifest repos |
repos sync / repos diff |
Reconcile configuration drift |
repos upgrade |
Upgrade scaffold shim ref across repos |
repos remove |
Remove fullsend from specific repos |
Manifest: a YAML file declaring desired state — mint config, default
field values, and a list of repos (strings for defaults, objects for
overrides). Supports glob patterns (acme-corp/*) and multi-org repos
in a single file. Lives wherever the operator chooses (not in a
.fullsend config repo). All read commands accept --manifest as a
local path or URL per ADR 0038.
Key design constraints:
- Install uses two phases: parallel discovery → parallel scaffold. GCP infrastructure (WIF, mint) is provisioned separately.
- Version changes (
repos upgrade) are separated from config reconciliation (repos sync) to prevent accidental upgrades. - Works alongside per-org installations during a migration period; serves as the migration path for ADR 0044 (pending) deprecation.
Manifest schema, field resolution semantics, and subcommand specifications are covered in the sections below.
- Operational parity with per-org — bulk install, inventory, and drift detection without per-org's infrastructure complexity (config repo, org-level variables, enrollment workflows).
- Cross-org management — a single manifest manages repos across multiple GitHub orgs, unlike per-org's single-org model.
- Operator discipline required — the manifest must be maintained manually; adding repos to the org doesn't auto-add them (unless matched by a glob pattern).
- API rate scaling — discovery is O(n) API calls per repo; large
deployments may require rate limiting and
--repofiltering. - Migration path — if per-org is deprecated, the repos tool provides the migration mechanism before the old model is removed.
- ADR 0033 — per-repo installation model
- ADR 0038 — URL-based resource references
- ADR 0044 (pending) — per-org deprecation; repos tool replaces its deferred Option C
- ADR 0045 — harness composition via
baseURLs - ADR 0048 —
--upstream-refversion pinning - PR #5713 — added forge URL fields (
forge.github.url,forge.gitlab.url) to the manifest schema and--forge-urlflag torepos init(nowrepos migrate);forge.gitlab.urlis required (breaking change)
Note: ADR 0074 consolidates the subcommands defined above into five commands (
migrate,install,status,uninstall,set-default).
Implemented subcommands:
repos migrate— PR #5816 (replacedrepos init; one-command migration from per-org to per-repo)repos install— PR #3033, consolidated into convergence operator in PR #5807repos status— PR #3031repos uninstall— PR #4081, expanded with--manifest-onlyand--uninstall-onlyin PR #5807
Consolidated in PR #5807 (absorbed into repos install and repos uninstall):
repos add(PR #4081) →repos installwith positional args and--forgerepos remove(PR #4081) →repos uninstallwith--manifest-onlyrepos diff(PR #4079) →repos install --dry-runrepos sync(PR #4079) →repos installconvergence phaserepos upgrade(PR #4080) →repos installconvergence phase
Removed:
repos init(PR #3033) → replaced byrepos migratein PR #5816