Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/ADRs/0057-repos-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ to Terraform vs cloud provider CLIs.
| `repos upgrade-mint` | Verify token mint deployment against manifest |
| `repos remove` | Remove fullsend from specific repos |

> **Note:** `repos upgrade` now includes automatic mint verification as a pre-flight step (unless `--skip-mint-check` is set). The standalone `repos upgrade-mint` command remains available for verification without triggering an upgrade.

**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
Expand Down
7 changes: 4 additions & 3 deletions docs/cli/repos.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Manage per-repo installations across multiple orgs via a declarative `repos.yaml
| `fullsend repos status` | Compare manifest against actual repo state |
| `fullsend repos diff` | Show configuration drift between manifest and actual state |
| `fullsend repos sync` | Reconcile configuration drift for installed repos |
| `fullsend repos upgrade [repos...]` | Upgrade scaffold shim ref across repos |
| `fullsend repos upgrade [repos...]` | Verify mint deployment then upgrade scaffold shim ref across repos |
| `fullsend repos upgrade-mint` | Verify the token mint deployment matches the manifest |

## `repos init`
Expand Down Expand Up @@ -321,7 +321,7 @@ fullsend repos uninstall acme/old-api --dry-run

## `repos upgrade`

Upgrades the fullsend scaffold workflow ref for repos defined in a `repos.yaml` manifest. Reads each repo's current workflow file, compares against the manifest's `fullsend_ref` (or `--ref` override), and commits the updated workflow.
Upgrades the fullsend scaffold workflow ref for repos defined in a `repos.yaml` manifest. Before upgrading, verifies the mint deployment matches the manifest configuration (unless `--skip-mint-check` is set). Reads each repo's current workflow file, compares against the manifest's `fullsend_ref` (or `--ref` override), and commits the updated workflow.

Floating refs (`latest`, `main`, `v0`) are skipped. Downgrades are blocked unless `--force` is set.

Expand All @@ -341,6 +341,7 @@ fullsend repos upgrade --ref v2.4.0
| `--dry-run` | | `false` | Preview what would be upgraded without making changes |
| `--force` | | `false` | Upgrade even if current ref is newer than target |
| `--concurrency` | | `4` | Max parallel operations (1-32) |
| `--skip-mint-check` | | `false` | Skip mint URL verification before upgrading repos |
| `--direct` | | `false` | Push scaffold directly to default branch (skip PR) |

### Positional arguments
Expand All @@ -357,7 +358,7 @@ If tag-to-SHA resolution fails (e.g. the tag does not exist or the API is unreac

Verifies the token mint Cloud Function matches the manifest configuration. Discovers the current mint deployment and checks that its URL matches the manifest's `mint.url`.

Run this before `repos upgrade` to ensure mint compatibility.
`repos upgrade` now runs mint verification automatically as a pre-flight check. This command remains available for standalone verification without triggering an upgrade.

```bash
fullsend repos upgrade-mint -f repos.yaml
Expand Down
1 change: 1 addition & 0 deletions docs/guides/dev/cli-internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ fullsend
│ │ ├── --dry-run # Preview without making changes
│ │ ├── --force # Upgrade even if current ref is newer
│ │ ├── --direct # Push directly to default branch (skip PR)
│ │ ├── --skip-mint-check # Skip mint URL verification before upgrading
│ │ └── --concurrency <int> # Max parallel operations (1-32, default: 4)
│ └── upgrade-mint # Verify token mint deployment matches manifest
│ └── -f, --manifest <path> # Path or URL to repos.yaml (default: repos.yaml)
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ For organizations that separate GCP and GitHub responsibilities across teams, fu
| Fleet Admin | `fullsend repos status` | Compare `repos.yaml` manifest against actual per-repo state (drift detection) |
| Fleet Admin | `fullsend repos diff` | Show configuration drift between manifest and actual forge state |
| Platform Admin | `fullsend repos sync` | Reconcile configuration drift for installed repos (variables and secrets) |
| Platform Admin | `fullsend repos upgrade [repos...]` | Upgrade scaffold shim ref across manifest repos |
| Platform Admin | `fullsend repos upgrade [repos...]` | Verify mint deployment then upgrade scaffold shim ref across manifest repos |
| Platform Admin | `fullsend repos upgrade-mint` | Verify the token mint deployment matches the manifest |

| Developer | `fullsend agent add <url-or-path>` | Register an agent in config (URL auto-pinned to commit SHA) |
Expand Down
5 changes: 3 additions & 2 deletions docs/plans/repos-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,9 @@ rather than falling back to tag-only format.

Verifies the token mint deployment matches the manifest configuration.
Discovers the current mint via `DiscoverMint` and checks that its URL
matches `mint.url`. Run before `repos upgrade` to confirm the mint
is reachable and correctly configured.
matches `mint.url`. `repos upgrade` now runs this check automatically
as a pre-flight step (unless `--skip-mint-check` is set); this command
remains available for standalone verification.

#### `fullsend repos add`

Expand Down
64 changes: 43 additions & 21 deletions internal/cli/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,19 @@ func confirmBulkAction(printer *ui.Printer, action string, patterns []string, ma
return nil
}

func resolveMintProvisioner(testProv repos.WIFProvisioner, m *repos.Manifest) repos.WIFProvisioner {
if testProv != nil {
return testProv
}
return &gcfProvisionerAdapter{
provisioner: gcf.NewProvisioner(gcf.Config{
ProjectID: m.Mint.Project,
Region: m.Mint.Region,
MintURL: m.Mint.URL,
}, gcf.NewLiveGCFClient(m.Mint.Project)),
}
}

// buildProvisionerFactory creates a ProvisionerFactory for uninstall operations.
// When skipWIF is true or testProv is non-nil, shortcuts are used.
func buildProvisionerFactory(testProv repos.WIFProvisioner, skipWIF bool) repos.ProvisionerFactory {
Expand Down Expand Up @@ -1223,16 +1236,18 @@ func runReposSync(ctx context.Context, opts *reposSyncConfig) error {

// reposUpgradeConfig holds flag values and testing overrides for repos upgrade.
type reposUpgradeConfig struct {
manifest string
refOverride string
dryRun bool
force bool
concurrency int
direct bool
manifest string
refOverride string
dryRun bool
force bool
skipMintCheck bool
concurrency int
direct bool

// Testing overrides — when non-nil, used instead of resolving from
// the environment. Not set by CLI flag parsing.
testClient forge.Client
testClient forge.Client
testProvisioner repos.WIFProvisioner
}

func newReposUpgradeCmd() *cobra.Command {
Expand Down Expand Up @@ -1261,6 +1276,7 @@ unless --force is set.`,
cmd.Flags().StringVar(&opts.refOverride, "ref", "", "override manifest fullsend_ref for all repos")
cmd.Flags().BoolVar(&opts.dryRun, "dry-run", false, "preview what would be upgraded without making changes")
cmd.Flags().BoolVar(&opts.force, "force", false, "upgrade even if current ref is newer than target")
cmd.Flags().BoolVar(&opts.skipMintCheck, "skip-mint-check", false, "skip mint URL verification before upgrading repos")
cmd.Flags().IntVar(&opts.concurrency, "concurrency", 4, "max parallel operations")
cmd.Flags().BoolVar(&opts.direct, "direct", false, "push scaffold directly to default branch (skip PR)")

Expand Down Expand Up @@ -1303,6 +1319,22 @@ func runReposUpgrade(ctx context.Context, opts *reposUpgradeConfig, repoFilter [
return err
}

if !opts.skipMintCheck {
printer.StepStart("Verifying mint deployment")

provisioner := resolveMintProvisioner(opts.testProvisioner, m)

mintProgressFn := func(repo, phase, msg string) {
printer.StepInfo(fmt.Sprintf("[%s] %s", repo, msg))
}

if err := repos.UpgradeMint(ctx, m, provisioner, mintProgressFn); err != nil {
return fmt.Errorf("mint verification failed: %w", err)
}

printer.StepDone("Mint verified successfully")
}

commitFn := func(ctx context.Context, owner, repo string, files []forge.TreeFile, isDirect bool) error {
targetRepo, repoErr := client.GetRepo(ctx, owner, repo)
if repoErr != nil {
Expand Down Expand Up @@ -1390,8 +1422,9 @@ func newReposUpgradeMintCmd() *cobra.Command {
Long: `Verifies the token mint Cloud Function matches the manifest configuration.

Discovers the current mint deployment and checks that its URL matches
the manifest's mint.url. Run this before 'repos upgrade' to ensure
mint compatibility.`,
the manifest's mint.url. This check runs automatically as a pre-flight
step in 'repos upgrade'; this command is available for standalone
verification without triggering an upgrade.`,
RunE: func(cmd *cobra.Command, args []string) error {
return runReposUpgradeMint(cmd.Context(), opts)
},
Expand All @@ -1415,18 +1448,7 @@ func runReposUpgradeMint(ctx context.Context, opts *reposUpgradeMintConfig) erro
}
printer.StepDone("Loaded manifest")

var provisioner repos.WIFProvisioner
if opts.testProvisioner != nil {
provisioner = opts.testProvisioner
} else {
provisioner = &gcfProvisionerAdapter{
provisioner: gcf.NewProvisioner(gcf.Config{
ProjectID: m.Mint.Project,
Region: m.Mint.Region,
MintURL: m.Mint.URL,
}, gcf.NewLiveGCFClient(m.Mint.Project)),
}
}
provisioner := resolveMintProvisioner(opts.testProvisioner, m)

progressFn := func(repo, phase, msg string) {
printer.StepInfo(fmt.Sprintf("[%s] %s", repo, msg))
Expand Down
Loading
Loading