Skip to content

refactor!: unify the four product command trees behind ProductProfile - #16

Merged
hectorvent merged 2 commits into
mainfrom
refactor/unify-trees
Jul 29, 2026
Merged

refactor!: unify the four product command trees behind ProductProfile#16
hectorvent merged 2 commits into
mainfrom
refactor/unify-trees

Conversation

@hectorvent

Copy link
Copy Markdown
Contributor

Summary

Collapses the four near-identical product command trees into ONE implementation per shared command, parameterized by ProductProfile — the single source of per-product config (endpoint, container, image, env prefix, control prefix, display name). The gcp/az/oci classes become ~8-line shims carrying only their per-product help description; the three *GlobalOptions clones are deleted. Each product tree drops from ~1,360 to ~530 lines, the "apply every change to all four trees" rule is retired from AGENTS.md/CONTRIBUTING.md, and copy-drift (the source of several past bugs) becomes structurally impossible.

Verified with a captured baseline of 480 CLI outputs (every --help × 5 trees, env/status/doctor JSON, exit codes, default-product routing) diffed against main after every phase, plus native-image smoke tests across all trees.

Deliberate behavior changes (all in CHANGELOG):

  • gcp/az/oci snapshot commands perform real /snapshots API calls with graceful degradation and exit 1 while server support is pending (previously note + exit 0) — see BREAKING CHANGE footer in the commit
  • product logs/services gained --service/--mode (drift fix); services resolves the endpoint from the container port mapping in all trees (extends feat(oci): add floci oci command group for the Floci OCI emulator #15's OCI fix tree-wide)
  • the AWS tree brands itself Floci AWS in banners and help, matching the other products
  • snapshot errors link the product issue tracker instead of maintainer TODO.md

Type of change

  • Bug fix (fix:)
  • New feature (feat:)
  • Breaking change (feat!: or fix!:) — snapshot exit codes on stubbed trees
  • Docs / chore

Product trees affected

  • AWS (root tree)
  • GCP (commands/gcp/)
  • Azure (commands/az/)
  • N/A

Also commands/oci/; the template predates the fourth tree.

Checklist

  • mvn test passes locally (66 tests)
  • New or updated tests added (ProductProfileTest, ProductTreesParsingTest, DoctorCheckListTest, GlobalOptionsTest — first-ever coverage of the gcp/az/oci trees)
  • CHANGELOG.md entry added under [Unreleased]
  • README.md updated (snapshot exit-code note)
  • Native binary verified (mvn package -Pnative) — per-tree smoke at the pilot phase and at the end
  • Commit messages / PR title follow Conventional Commits

Every shared command now has ONE implementation in commands/,
parameterized by ProductProfile (the single source of per-product
config: endpoint, container, image, env prefix, control prefix,
display name). The gcp/az/oci command classes become ~8-line shims
(GcpStartCommand extends StartCommand { super(ProductProfile.GCP); })
that carry only their per-product help description; the three
near-identical *GlobalOptions clones are deleted. Each product tree
drops from ~1,360 to ~530 lines and copy-drift becomes impossible.

Mechanics: per-product option defaults are constructor-set field
values rendered in help via ${DEFAULT-VALUE} (annotation defaults are
compile-time constants); commands pre-initialize their GlobalOptions
mixin with the profile (picocli uses a non-null mixin field instance
as-is). Verified against a captured baseline of 480 CLI outputs
(every --help x 5 trees, env/status/doctor JSON, exit codes, routing)
plus new pinning tests: ProductProfileTest, ProductTreesParsingTest,
DoctorCheckListTest, GlobalOptionsTest.

Behavior changes, all deliberate:
- snapshot commands in gcp/az/oci trees now perform the real
  /snapshots API calls with graceful degradation and exit 1 while the
  server lacks the endpoints (previously: note + exit 0)
- product logs/services gained --service/--mode, and services now
  resolves the endpoint from the container port mapping in all trees
- the AWS tree brands itself 'Floci AWS' in banners and help,
  matching the other products
- snapshot errors link the product issue tracker instead of TODO.md
- completion generates from spec.root() instead of a hardcoded
  FlociCli instance (output unchanged)

BREAKING CHANGE: 'floci gcp|az|oci snapshot export/import' (and bare
'floci snapshot ...' with a non-AWS default product) now exit 1
instead of 0 while server-side snapshot support is pending; CI
scripts relying on the silent success of stubbed snapshot commands
will fail.
Comment thread src/main/java/io/floci/cli/commands/snapshot/SnapshotListCommand.java Outdated
@greptile-apps

greptile-apps Bot commented Jul 29, 2026

Copy link
Copy Markdown

Greptile Summary

Unifies AWS/GCP/Azure/OCI CLI trees behind ProductProfile and shared command implementations.

  • Deletes per-product GlobalOptions clones; product shims pass ProductProfile into shared commands.
  • Snapshot save/load/list/delete now use Docker port resolution and product control prefixes (real HTTP for all trees).
  • Deliberate breaking change: non-AWS snapshot stubs become real API calls with exit 1 when unsupported; branding and drift fixes for logs/services.

Confidence Score: 5/5

The PR appears safe to merge; the prior snapshot remapped-port issue is fixed on HEAD and no blocking failures remain.

Snapshot list/save/load/delete all call global.resolvedEndpoint before constructing FlociHttpClient, matching status/wait/services; no remaining blocking failure from the prior thread or this follow-up pass.

Important Files Changed

Filename Overview
src/main/java/io/floci/cli/ProductProfile.java Centralizes per-product name, image, ports, env prefix, and control-plane prefix for the unified command tree.
src/main/java/io/floci/cli/GlobalOptions.java Single mixin with product-scoped defaults and resolvedEndpoint using product.defaultPort().
src/main/java/io/floci/cli/commands/snapshot/SnapshotListCommand.java Uses resolvedEndpoint before FlociHttpClient, fixing remapped-port reachability for list (and siblings save/load/delete).
src/main/java/io/floci/cli/commands/ServicesCommand.java Adopts Docker port resolution and product control prefix tree-wide for services listing.

Reviews (2): Last reviewed commit: "fix: snapshot save/load/list/delete reso..." | Re-trigger Greptile

Same port auto-detection status/services/wait use — a container started
with --port <n> is now reachable by the snapshot commands without an
explicit --endpoint. Applies to all four trees via the unified base
commands.
@hectorvent

Copy link
Copy Markdown
Contributor Author

Addressed in 7314d99: snapshot save/load/list/delete now resolve the endpoint from the container's port mapping via resolvedEndpoint, exactly like status/services/wait — one change in the unified base commands covers all four trees. Verified live against a running emulator (graceful Snapshot API not available + exit 1 on a server without the endpoints). 66/66 tests pass.

@hectorvent
hectorvent merged commit 6dc8fc9 into main Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant