diff --git a/README.md b/README.md index 1307894..3696d72 100644 --- a/README.md +++ b/README.md @@ -53,24 +53,41 @@ make install ### `flywork setup` -Bootstraps the entire Firefly Framework into your local environment. Clones all **34 framework repositories** in **DAG-resolved dependency order** and installs them to your local Maven cache (`~/.m2`). +Bootstraps the entire Firefly Framework into your local environment. Clones all **38 framework repositories** in **DAG-resolved dependency order** and installs them to your local Maven cache (`~/.m2`). The CLI resolves a dependency graph across all repositories, groups them into layers, and processes each layer sequentially to guarantee correct compilation order. Progress is shown with real-time progress bars, per-repo spinners with elapsed time, and a final summary box. ```bash -flywork setup # full setup (prompts whether to run tests) +flywork setup # full interactive setup (prompts whether to run tests) flywork setup --skip-tests # skip tests during Maven install +flywork setup --retry # retry only previously failed repositories +flywork setup --fresh # ignore previous manifest, start from scratch +flywork setup --fetch-updates # also fetch updates for already-cloned repos +flywork setup --jdk /path # use a specific JDK instead of auto-detection flywork setup -v # verbose: show DAG layers and per-repo status ``` When `--skip-tests` is not provided, the CLI interactively asks whether to run tests (default: **yes**). +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--skip-tests` | `false` | Skip running tests during Maven install | +| `--retry` | `false` | Retry only previously failed repositories | +| `--fresh` | `false` | Force a fresh setup, ignoring any previous manifest | +| `--fetch-updates` | `false` | Fetch latest changes for already-cloned repos | +| `--jdk` | `""` | Explicit JAVA_HOME path (skip JDK auto-detection) | + **What it does:** -1. Resolves the dependency DAG (34 repos across 6 layers) -2. **Phase 1** — Clones all repos layer-by-layer with a live progress bar -3. **Phase 2** — Runs `mvn clean install` on each repo in dependency order (with or without tests), with per-repo spinners showing elapsed time -4. Displays a summary box with total time, repos cloned/installed, and layer count +1. **Preflight** — Verifies Git, Maven, and Java are installed +2. **Resume/Retry Detection** — Detects previous setup manifest and offers to resume, retry, or restart +3. **JDK Selection** — Auto-detects installed JDK versions matching the configured `java_version` +4. **Cloning** — Resolves the dependency DAG (38 repos across 6 layers) and clones all repos layer-by-layer +5. **Installing** — Runs `mvn clean install` on each repo in dependency order with per-repo spinners +6. **Post-Install Retry** — If any repos fail, offers to retry them immediately +7. Displays a summary box with total time, repos cloned/installed, and layer count ### `flywork create [archetype]` @@ -84,13 +101,27 @@ Scaffolds a new project from one of four YAML-driven archetypes: | **library** | Single-module library with Spring Boot auto-configuration | ```bash -flywork create core +flywork create # fully interactive mode +flywork create core # core archetype with prompts flywork create domain --group-id com.example --artifact-id my-service flywork create application -g com.example -a my-app -d "My Application" flywork create library -g com.example -a my-lib --no-git +flywork create core --version 1.0.0 -o ./output-dir # custom version and output ``` -If no flags are provided, the CLI enters interactive mode with prompts for archetype selection, group ID, artifact ID, package name, and description. +If no archetype or flags are provided, the CLI enters interactive mode with prompts for archetype selection, group ID, artifact ID, package name, description, and infrastructure defaults. + +**Flags:** + +| Flag | Short | Default | Description | +|------|-------|---------|-------------| +| `--group-id` | `-g` | `""` | Maven groupId (interactive if omitted) | +| `--artifact-id` | `-a` | `""` | Maven artifactId (interactive if omitted) | +| `--package` | `-p` | `""` | Base Java package (derived from groupId if omitted) | +| `--description` | `-d` | `""` | Project description | +| `--version` | | `0.0.1-SNAPSHOT` | Initial project version | +| `--output` | `-o` | `""` | Output directory (defaults to artifactId) | +| `--no-git` | | `false` | Skip git init | ### `flywork doctor` @@ -123,6 +154,14 @@ flywork update -v # verbose with layer info When `--skip-tests` is not provided (and not `--pull-only`), the CLI interactively asks whether to run tests (default: **yes**). +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--pull-only` | `false` | Only git pull, skip Maven install | +| `--repo` | `""` | Update a single repository by name | +| `--skip-tests` | `false` | Skip running tests during Maven install | + The update command uses the same DAG resolver as `setup`, with two distinct phases: 1. **Phase 1** — Git pull with progress bar @@ -141,6 +180,16 @@ flywork build --skip-tests # skip running tests during Maven install flywork build --jdk /path # use an explicit JAVA_HOME ``` +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--all` | `false` | Rebuild everything (ignore change detection) | +| `--repo` | `""` | Build a specific repo and its dependents | +| `--dry-run` | `false` | Show what would be built without building | +| `--skip-tests` | `false` | Skip running tests during Maven install | +| `--jdk` | `""` | Explicit JAVA_HOME path | + **Phases:** 1. **Preflight** — Verifies Git, Maven, and Java are installed @@ -162,6 +211,16 @@ flywork publish --skip-tests # skip tests during deploy (default: true) flywork publish --jdk /path # use an explicit JAVA_HOME ``` +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--all` | `false` | Publish everything (ignore change detection) | +| `--repo` | `""` | Publish a specific repo only | +| `--dry-run` | `false` | Show what would be published without publishing | +| `--skip-tests` | `true` | Skip tests during deploy | +| `--jdk` | `""` | Explicit JAVA_HOME path | + Requires `GITHUB_TOKEN` environment variable set with `write:packages` scope. **Phases:** @@ -190,8 +249,8 @@ flywork dag export # export full DAG as JSON for CI/CD co |------------|-------------| | `show` | Full dependency graph with arrows showing dependencies | | `layers` | Repos grouped by build layer (0 = no dependencies) | -| `affected` | Transitive closure of repos affected by a change in `--from` | -| `export` | JSON export of the entire DAG (nodes, edges, layers) | +| `affected` | Transitive closure of repos affected by a change in `--from` (required flag) | +| `export` | JSON export of the entire DAG (nodes, edges, layers) for CI/CD | ### `flywork fwversion` @@ -227,6 +286,32 @@ flywork fwversion families # show version family release history | `--dry-run` | `false` | Show changes without modifying files | | `--install` | `false` | Run `mvn install` in all repos after bumping | +### `flywork run` + +Runs a Firefly Framework application with interactive configuration assistance. Detects the Spring Boot module, scans configuration files for missing environment variables, and launches an interactive wizard before starting the app. + +```bash +flywork run # interactive run with configuration wizard +flywork run --profile dev # activate the 'dev' Spring profile +flywork run --skip-wizard # skip the configuration wizard +flywork run --profile local --skip-wizard # non-interactive run with 'local' profile +``` + +**What it does:** + +1. **Project Analysis** — Detects archetype (core, domain, application, library), multi-module layout, and locates the web/boot module +2. **Profile Selection** — If Spring profiles are detected (e.g. `dev`, `local`) and `--profile` is not provided, offers an interactive selection prompt +3. **Configuration Scanning** — Parses `application.yaml` for `${PLACEHOLDER}` variables and groups them into: set from environment, have defaults, or missing (required) +4. **Interactive Wizard** — Prompts for required variables, offers to override defaults, and uses smart defaults for common names (e.g. `DB_HOST` → `localhost`, `DB_PORT` → `5432`) +5. **Launch** — Starts the application with `mvn spring-boot:run` passing the selected profile and environment variable overrides + +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--profile` | `""` | Spring profile to activate (e.g. dev, local) | +| `--skip-wizard` | `false` | Skip the interactive configuration wizard | + ### `flywork upgrade` Self-updates the CLI binary from GitHub releases. @@ -236,6 +321,12 @@ flywork upgrade # download and install latest version flywork upgrade --check # just check if an update is available ``` +**Flags:** + +| Flag | Default | Description | +|------|---------|-------------| +| `--check` | `false` | Only check for updates, don't install | + ### `flywork config` View and manage CLI configuration stored in `~/.flywork/config.yaml`. @@ -258,6 +349,17 @@ flywork version --- +## Global Flags + +| Flag | Short | Description | +|------|-------|-------------| +| `--verbose` | `-v` | Enable verbose output (DAG layers, per-repo details, etc.) | +| `--help` | `-h` | Show help for any command | + +The `--verbose` flag is available on all commands. It enables additional output such as DAG layer headers, per-repo status lines, and detailed version information. + +--- + ## DAG Dependency Resolution The CLI maintains an internal **directed acyclic graph** of all 38 framework repositories with their real Maven dependency relationships. This ensures: @@ -289,8 +391,9 @@ Configuration is stored in `~/.flywork/config.yaml`. | `github_org` | `fireflyframework` | GitHub organization name | | `default_group_id` | `org.fireflyframework` | Default Maven groupId for new projects | | `java_version` | `25` | Target Java version for compilation | -| `parent_version` | `1.0.0-SNAPSHOT` | Parent POM version for archetypes | +| `parent_version` | `26.01.01` | Parent POM CalVer version for archetypes | | `cli_auto_update` | `false` | Auto-check for CLI updates on launch | +| `branch` | `develop` | Git branch to clone during setup | ### Dynamic Java Version @@ -428,6 +531,7 @@ fireflyframework-cli/ │ ├── fwversion.go # flywork fwversion (CalVer management) │ ├── upgrade.go # flywork upgrade (self-update) │ ├── config.go # flywork config (get/set/reset) +│ ├── run.go # flywork run (application runner) │ └── version.go # flywork version ├── internal/ │ ├── build/ # Smart build engine @@ -444,6 +548,7 @@ fireflyframework-cli/ │ │ ├── publisher.go # DAG-ordered Maven deploy │ │ ├── python.go # Python package publishing │ │ └── settings.go # Maven settings.xml management +│ ├── runner/ # Application runner with config wizard │ ├── scaffold/ # Archetype engine │ │ ├── engine.go # Template rendering and project generation │ │ ├── archetypes/*.yaml # Embedded archetype definitions diff --git a/cmd/build.go b/cmd/build.go index 2c52e1c..ef21702 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -41,8 +41,44 @@ var ( var buildCmd = &cobra.Command{ Use: "build", Short: "Smart DAG-aware build with change detection", - Long: "Detects which repos have changed since the last build, computes affected downstream repos, and builds them in dependency order", - RunE: runBuild, + Long: `Detects which repositories have changed since the last successful build, +computes the transitive closure of affected downstream repositories via the +dependency graph, and builds them in layer-by-layer dependency order. + +The build process runs through the following phases: + + Phase 0 — Preflight Checks + Verifies that Git, Maven, and Java are installed and available. + + Phase 1 — Change Detection + Compares HEAD commit SHAs against the last-build manifest + (~/.flywork/build-manifest.json). Repos with different SHAs are + considered changed. + + Phase 2 — Build Plan + Displays affected repos grouped by DAG layer. Directly changed repos + are marked with '*'. Shows total count and layer breakdown. + + Phase 3 — DAG Build + Runs 'mvn clean install' layer-by-layer with progress bars and per-repo + spinners showing elapsed time. + + Phase 4 — Summary + Reports built/skipped/failed counts, total time, and log file locations + for any failures. + +Use --all to ignore change detection and rebuild everything. Use --repo to +target a specific repository and its downstream dependents. Use --dry-run to +preview the build plan without executing it. + +Examples: + flywork build Build changed repos + affected dependents + flywork build --all Rebuild everything + flywork build --repo Build a specific repo and its dependents + flywork build --dry-run Preview build plan without building + flywork build --skip-tests Skip tests during Maven install + flywork build --jdk /path/to/jdk Use a specific JAVA_HOME`, + RunE: runBuild, } func init() { diff --git a/cmd/config.go b/cmd/config.go index 6c6c6bc..6f5594e 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -26,21 +26,55 @@ import ( var configCmd = &cobra.Command{ Use: "config", Short: "View and manage Flywork CLI configuration", - Long: "View all configuration values. Use subcommands to get, set, or reset individual keys.", - RunE: runConfigList, + Long: `View all configuration values. Use subcommands to get, set, or reset individual +keys. Configuration is stored in ~/.flywork/config.yaml. + +Available Subcommands: + get Get a single configuration value + set Set a configuration value + reset Reset all configuration to defaults + +Valid configuration keys: + repos_path Where framework repos are cloned (default: ~/.flywork/repos) + github_org GitHub organization name (default: fireflyframework) + default_group_id Default Maven groupId for new projects (default: org.fireflyframework) + java_version Target Java version for compilation (default: 25) + parent_version Parent POM version for archetypes (default: 26.01.01) + cli_auto_update Auto-check for CLI updates on launch (default: false) + branch Git branch to clone during setup (default: develop) + +Examples: + flywork config Show all configuration + flywork config get java_version Get a single value + flywork config set java_version 25 Set a value + flywork config set branch main Change the default branch + flywork config reset Reset to defaults`, + RunE: runConfigList, } var configGetCmd = &cobra.Command{ - Use: "get ", - Short: "Get a configuration value", + Use: "get ", + Short: "Get a configuration value", + Long: `Prints the value of a single configuration key to stdout with no formatting. +This is useful for scripting and CI/CD integration. + +Valid keys: repos_path, github_org, default_group_id, java_version, +parent_version, cli_auto_update, branch`, Args: cobra.ExactArgs(1), ValidArgs: config.ValidKeys, RunE: runConfigGet, } var configSetCmd = &cobra.Command{ - Use: "set ", - Short: "Set a configuration value", + Use: "set ", + Short: "Set a configuration value", + Long: `Sets a configuration key to the specified value and saves it to +~/.flywork/config.yaml. + +Valid keys: repos_path, github_org, default_group_id, java_version, +parent_version, cli_auto_update, branch + +For cli_auto_update, accepted values are: true, false, 1, 0, yes, no.`, Args: cobra.ExactArgs(2), ValidArgs: config.ValidKeys, RunE: runConfigSet, @@ -49,7 +83,9 @@ var configSetCmd = &cobra.Command{ var configResetCmd = &cobra.Command{ Use: "reset", Short: "Reset configuration to defaults", - RunE: runConfigReset, + Long: `Resets all configuration keys to their default values and saves the result +to ~/.flywork/config.yaml. The default values are displayed after the reset.`, + RunE: runConfigReset, } func init() { diff --git a/cmd/create.go b/cmd/create.go index ff4ed91..6f7d63c 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -43,9 +43,35 @@ var ( var createCmd = &cobra.Command{ Use: "create [archetype]", Short: "Scaffold a new Firefly Framework project", - Long: "Creates a new project from an archetype: core, domain, application, or library", - Args: cobra.MaximumNArgs(1), - RunE: runCreate, + Long: `Creates a new project from one of four YAML-driven archetypes. If no archetype +is provided as an argument, the CLI enters interactive mode with prompts for +archetype selection, group ID, artifact ID, package name, and description. + +Available archetypes: + core Multi-module microservice with R2DBC, Flyway, MapStruct, OpenAPI SDK, + and reactive services (5 modules: interfaces, models, core, sdk, web) + domain Multi-module CQRS/Saga microservice with transactional engine + (5 modules: interfaces, infra, core, sdk, web) + application Single-module application with plugin architecture and Spring Security + library Single-module library with Spring Boot auto-configuration + +For core, domain, and application archetypes, an infrastructure wizard prompts +for default values (server port, database host/port/name/user/password) that +are embedded into the generated application.yaml file. These values can be +overridden at runtime via environment variables. + +Custom archetypes can be placed in ~/.flywork/archetypes/.yaml to override +built-in archetypes or define new ones. + +Examples: + flywork create Interactive mode + flywork create core Core archetype with prompts + flywork create domain -g com.example -a my-service Provide group and artifact IDs + flywork create application -o ./output-dir Custom output directory + flywork create library --no-git Skip git init + flywork create core --version 1.0.0 Custom initial version`, + Args: cobra.MaximumNArgs(1), + RunE: runCreate, ValidArgs: scaffold.ListArchetypes(), } diff --git a/cmd/dag.go b/cmd/dag.go index 091930f..b74ac2a 100644 --- a/cmd/dag.go +++ b/cmd/dag.go @@ -27,19 +27,43 @@ import ( var dagCmd = &cobra.Command{ Use: "dag", Short: "Inspect the framework dependency graph", - Long: "Commands for viewing and querying the fireflyframework dependency DAG", + Long: `Commands for viewing and querying the fireflyframework dependency DAG +(Directed Acyclic Graph). The DAG encodes the real Maven dependency +relationships between all framework repositories and is used by setup, +build, and publish to determine correct processing order. + +Available Subcommands: + show Display the full dependency graph as an ASCII tree + layers Show repositories grouped by build layer (0 = no dependencies) + affected Compute transitive closure of repos affected by a change + export Export the entire DAG as JSON for CI/CD consumption + +Examples: + flywork dag show + flywork dag layers + flywork dag affected --from fireflyframework-utils + flywork dag affected --from fireflyframework-utils --json + flywork dag export`, } var dagShowCmd = &cobra.Command{ Use: "show", Short: "Display the full dependency graph as an ASCII tree", - RunE: runDagShow, + Long: `Displays the full framework dependency graph as a styled ASCII tree. Each +repository is shown with arrows pointing to its direct dependencies. +Repositories are grouped by layer, separated by dotted lines.`, + RunE: runDagShow, } var dagLayersCmd = &cobra.Command{ Use: "layers", Short: "Show repositories grouped by build layer", - RunE: runDagLayers, + Long: `Shows all repositories grouped by their build layer. Layer 0 contains +repositories with no dependencies (e.g. parent). Each subsequent layer +depends only on repositories in earlier layers. Repositories in the same +layer are independent of each other and can theoretically be built in +parallel.`, + RunE: runDagLayers, } var ( @@ -50,7 +74,18 @@ var ( var dagAffectedCmd = &cobra.Command{ Use: "affected", Short: "Compute transitive closure of repos affected by a change", - RunE: runDagAffected, + Long: `Computes all downstream repositories that would be affected by a change in +the specified source repository. This is the transitive closure of the +'depends-on' relationship — i.e., all repos that directly or indirectly +depend on the source. + +The --from flag is required and must be a valid repository name from the DAG. +Use --json for machine-readable output suitable for CI/CD pipelines. + +Examples: + flywork dag affected --from fireflyframework-utils + flywork dag affected --from fireflyframework-web --json`, + RunE: runDagAffected, } var dagExportJSON bool @@ -58,7 +93,11 @@ var dagExportJSON bool var dagExportCmd = &cobra.Command{ Use: "export", Short: "Export the DAG as JSON for CI/CD consumption", - RunE: runDagExport, + Long: `Exports the entire dependency graph as a JSON document containing nodes, +edges, and layer assignments. This is intended for CI/CD pipeline +integration, allowing external tools to understand the build order and +dependency relationships.`, + RunE: runDagExport, } func init() { diff --git a/cmd/doctor.go b/cmd/doctor.go index 9f4ab67..6d4a950 100644 --- a/cmd/doctor.go +++ b/cmd/doctor.go @@ -27,8 +27,31 @@ import ( var doctorCmd = &cobra.Command{ Use: "doctor", Short: "Diagnose your Firefly Framework environment and project", - Long: "Runs global environment checks and, when inside a project directory, project-specific diagnostics.", - RunE: runDoctor, + Long: `Runs comprehensive diagnostics on your environment and, when executed inside +a Firefly project directory, also runs project-specific checks. + +Global environment checks: + - Java version detection (matches configured java_version) + - JAVA_HOME resolution + - Maven version and Java compatibility + - Git installation + - Framework repositories cloned status + - Parent POM presence in ~/.m2 + - BOM presence in ~/.m2 + - CLI version check (latest available vs installed) + +Project-specific checks (when inside a Firefly project): + - Project structure validation (pom.xml, src layout) + - Archetype detection + - Module structure verification + +Each check reports pass, warn, or fail with a detail message. The final +summary shows total counts by status. + +Examples: + flywork doctor Run all diagnostics + flywork doctor -v Verbose output with additional details`, + RunE: runDoctor, } func init() { diff --git a/cmd/fwversion.go b/cmd/fwversion.go index 0306b48..91b966a 100644 --- a/cmd/fwversion.go +++ b/cmd/fwversion.go @@ -34,7 +34,23 @@ import ( var fwversionCmd = &cobra.Command{ Use: "fwversion", Short: "Manage framework-wide CalVer versions", - Long: "Show, bump, check, and track CalVer versions across all Firefly Framework repositories.", + Long: `Show, bump, check, and track CalVer versions across all Firefly Framework +repositories. The framework uses Calendar Versioning (CalVer) in the format +YY.MM.PP (e.g. 26.01.01). + +Available Subcommands: + show Show current framework version across all repos + bump Bump framework version across all repos (updates pom.xml files) + check Validate version consistency across all repos + families Show version family release history + +Examples: + flywork fwversion show + flywork fwversion bump --auto + flywork fwversion bump --auto --push + flywork fwversion bump --dry-run + flywork fwversion check + flywork fwversion families`, } // ── fwversion show ────────────────────────────────────────────────────────── @@ -42,7 +58,11 @@ var fwversionCmd = &cobra.Command{ var fwversionShowCmd = &cobra.Command{ Use: "show", Short: "Show current framework version across all repos", - RunE: runFwversionShow, + Long: `Displays the current POM version for each framework repository, highlights +mismatches against the configured target version, and reports dirty working +trees. Use -v for a detailed per-repository listing with version, git tag, +and dirty status.`, + RunE: runFwversionShow, } func runFwversionShow(cmd *cobra.Command, args []string) error { @@ -166,8 +186,33 @@ var ( var fwversionBumpCmd = &cobra.Command{ Use: "bump", Short: "Bump framework version across all repos", - Long: "Updates all pom.xml files, optionally commits, tags, and pushes.", - RunE: runFwversionBump, + Long: `Updates all pom.xml files across every framework repository to a new CalVer +version, and optionally commits, tags, and pushes the changes. + +By default the CLI auto-increments the patch number from the current version. +Use --auto to explicitly request auto-computation. Use --year, --month, and +--patch to set a specific version manually. + +The bump process: + 1. Detects the current version from the parent POM + 2. Computes or accepts the target version + 3. Updates all pom.xml files across every cloned repository + 4. Updates the GenAI module version files (if present) + 5. Optionally commits changes (--commit, default: true) + 6. Optionally tags each repo with v (--tag, default: true) + 7. Optionally pushes to remote (--push, default: false) + 8. Optionally runs mvn install after bumping (--install) + 9. Records a version family snapshot for history tracking + 10. Updates ~/.flywork/config.yaml with the new parent_version + +Examples: + flywork fwversion bump Auto-increment patch version + flywork fwversion bump --auto Explicitly auto-compute next CalVer + flywork fwversion bump --auto --push Bump, commit, tag, and push + flywork fwversion bump --dry-run Preview changes without modifying files + flywork fwversion bump --install Bump + run mvn install after + flywork fwversion bump --year 26 --month 2 --patch 1 Set explicit version`, + RunE: runFwversionBump, } func runFwversionBump(cmd *cobra.Command, args []string) error { @@ -391,7 +436,19 @@ func runFwversionBump(cmd *cobra.Command, args []string) error { var fwversionCheckCmd = &cobra.Command{ Use: "check", Short: "Validate version consistency across all repos", - RunE: runFwversionCheck, + Long: `Runs a comprehensive set of consistency checks across all framework +repositories: + + - POM version consistency: all repos should be at the same version + - Config matches repos: ~/.flywork/config.yaml parent_version matches actual POMs + - Git tags: each repo's latest tag should match its POM version (v) + - Clean working trees: no uncommitted changes in any repository + - All repos cloned: verifies all expected repositories exist + - Parent POM in .m2: the parent POM artifact is installed at the target version + - BOM in .m2: the BOM artifact is installed at the target version + +Each check reports pass, warn, or fail with a detail message.`, + RunE: runFwversionCheck, } func runFwversionCheck(cmd *cobra.Command, args []string) error { @@ -591,7 +648,12 @@ func runFwversionCheck(cmd *cobra.Command, args []string) error { var fwversionFamiliesCmd = &cobra.Command{ Use: "families", Short: "Show version family history", - RunE: runFwversionFamilies, + Long: `Shows the history of version bumps recorded in ~/.flywork/version-families.json. +Each entry includes the version string, release date, and the number of modules +that were updated. The most recent version is marked with '*'. + +Use -v to also display the per-module git commit SHAs for each version family.`, + RunE: runFwversionFamilies, } func runFwversionFamilies(cmd *cobra.Command, args []string) error { diff --git a/cmd/publish.go b/cmd/publish.go index 8117f61..05152a8 100644 --- a/cmd/publish.go +++ b/cmd/publish.go @@ -44,8 +44,48 @@ var ( var publishCmd = &cobra.Command{ Use: "publish", Short: "Publish artifacts to GitHub Packages", - Long: "Deploys Maven artifacts to GitHub Packages and Python packages as GitHub Release assets, using DAG-aware ordering with change detection", - RunE: runPublish, + Long: `Deploys Maven artifacts to GitHub Packages and Python packages as GitHub +Release assets, using DAG-aware ordering with change detection. + +Requires the GITHUB_TOKEN environment variable to be set with 'write:packages' +scope. The token is used for Maven deploy authentication and Python package +release uploads. + +The publish process runs through the following phases: + + Phase 0 — Preflight Checks + Verifies GITHUB_TOKEN is set, and Git, Maven, and Java are available. + + Phase 1 — Maven Settings + Ensures ~/.m2/settings.xml contains the GitHub Packages server + configuration for authentication. + + Phase 2 — Publish Plan + Uses the same SHA-based change detection as 'flywork build' to determine + which repos need publishing. Displays repos grouped by DAG layer. + + Phase 3 — Maven Deploy + Runs 'mvn deploy' on each affected repository in dependency order with + progress bars and per-repo spinners. + + Phase 4 — Python Publish (conditional) + If fireflyframework-genai is in scope, publishes the Python package as + GitHub Release assets. + + Phase 5 — Summary + Reports published/skipped/failed counts and total time. + +Use --all to publish everything regardless of change detection. Use --repo to +publish a specific repository only. Use --dry-run to preview without publishing. + +Examples: + flywork publish Publish changed repos + flywork publish --all Publish everything + flywork publish --repo Publish a specific repo + flywork publish --dry-run Preview what would be published + flywork publish --skip-tests=false Run tests during deploy + flywork publish --jdk /path/to/jdk Use a specific JAVA_HOME`, + RunE: runPublish, } func init() { diff --git a/cmd/root.go b/cmd/root.go index bba5e11..fddab98 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -80,7 +80,33 @@ func shouldSkipBanner(cmd *cobra.Command) bool { var rootCmd = &cobra.Command{ Use: "flywork", Short: "Firefly Framework CLI", - Long: bannerStyle.Render(banner) + "\n" + subtitleStyle.Render(" The Firefly Framework command-line interface"), + Long: bannerStyle.Render(banner) + "\n" + subtitleStyle.Render(" The Firefly Framework command-line interface") + ` + +The official CLI for the Firefly Framework. Scaffold, setup, build, publish, +and manage your Firefly-based Java microservices from the terminal. + +Available Commands: + setup Bootstrap the Firefly Framework (clone + install all repos) + create Scaffold a new project from an archetype (core, domain, application, library) + doctor Diagnose your environment and project health + update Pull latest changes and reinstall framework repos + build Smart DAG-aware build with change detection + publish Publish Maven artifacts to GitHub Packages + run Run a Firefly Framework application with configuration assistance + dag Inspect the framework dependency graph + fwversion Manage framework-wide CalVer versions + config View and manage CLI configuration + upgrade Self-update the CLI binary from GitHub releases + version Print CLI version information + +Getting Started: + flywork setup Bootstrap the framework into your local environment + flywork create core Scaffold a new Core microservice project + flywork doctor Verify your environment is correctly configured + +Configuration: + Config file: ~/.flywork/config.yaml + Repos path: ~/.flywork/repos`, PersistentPreRun: func(cmd *cobra.Command, args []string) { if !shouldSkipBanner(cmd) { fmt.Println(bannerStyle.Render(banner)) diff --git a/cmd/run.go b/cmd/run.go index 10ff253..860c816 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -33,8 +33,39 @@ var ( var runCmd = &cobra.Command{ Use: "run", Short: "Run a Firefly Framework application with configuration assistance", - Long: "Detects the Spring Boot module, scans application config for missing variables, and launches an interactive wizard before running the application", - RunE: runRun, + Long: `Detects the Spring Boot module in your project, scans application configuration +files for missing environment variables, and launches an interactive wizard +before running the application with 'mvn spring-boot:run'. + +The run process: + + 1. Project Analysis + Detects the project archetype (core, domain, application, library), + identifies multi-module layout, and locates the web/boot module. + + 2. Profile Selection + If Spring profiles are detected (e.g. dev, local) and --profile is not + provided, offers an interactive selection prompt. + + 3. Configuration Scanning + Parses application.yaml/properties for ${PLACEHOLDER} variables. Groups + them into: set from environment, have defaults, or missing (required). + + 4. Interactive Wizard (skipped with --skip-wizard) + - Prompts for any required variables that have no default and no env value + - Offers to override default values if desired + - Uses smart defaults for common variables (DB_HOST, DB_PORT, etc.) + + 5. Launch + Starts the application with 'mvn spring-boot:run' passing the selected + profile and environment variable overrides. + +Examples: + flywork run Interactive run with wizard + flywork run --profile dev Activate the 'dev' Spring profile + flywork run --skip-wizard Skip the configuration wizard + flywork run --profile local --skip-wizard Non-interactive run`, + RunE: runRun, } func init() { diff --git a/cmd/setup.go b/cmd/setup.go index de570eb..04197d2 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -40,8 +40,46 @@ var ( var setupCmd = &cobra.Command{ Use: "setup", Short: "Bootstrap the Firefly Framework into your local environment", - Long: "Clones all fireflyframework repos and installs them to your local Maven repository (~/.m2)", - RunE: runSetup, + Long: `Clones all fireflyframework repositories and installs them to your local Maven +repository (~/.m2) in DAG-resolved dependency order. + +The setup process runs through the following phases: + + Phase 0 — Preflight Checks + Verifies that Git, Maven, and Java are installed and available. + + Phase 1 — JDK Selection + Auto-detects installed JDK versions matching the configured java_version + (default: 25). Use --jdk to skip auto-detection and provide an explicit path. + + Phase 2 — Cloning Repositories + Clones all framework repos layer-by-layer based on the dependency graph. + A live progress bar tracks overall progress. + + Phase 3 — Installing Artifacts + Runs 'mvn clean install' on each repository in dependency order. Per-repo + spinners show elapsed time. When --skip-tests is not provided, the CLI + interactively asks whether to run tests (default: yes). + + Post-Install — Retry Loop + If any repositories fail to install, the CLI offers to retry them + immediately. + +Resume and retry behavior: + If a previous setup was interrupted, the CLI detects the manifest file + (~/.flywork/setup-manifest.json) and offers to resume, retry failed repos, + or start fresh. Use --retry to skip the prompt and directly retry failures. + Use --fresh to ignore any previous manifest and start over. + +Examples: + flywork setup Full interactive setup + flywork setup --skip-tests Skip tests during Maven install + flywork setup --retry Retry only previously failed repositories + flywork setup --fresh Ignore previous manifest, start from scratch + flywork setup --fetch-updates Also fetch updates for already-cloned repos + flywork setup --jdk /path/to/jdk Use a specific JDK instead of auto-detection + flywork setup -v Verbose output with DAG layer details`, + RunE: runSetup, } func init() { diff --git a/cmd/update.go b/cmd/update.go index 2838d7d..b6a1afa 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -38,8 +38,31 @@ var ( var updateCmd = &cobra.Command{ Use: "update", Short: "Update framework repositories and reinstall to local Maven cache", - Long: "Pulls the latest changes for all cloned fireflyframework repos and reinstalls them to ~/.m2", - RunE: runUpdate, + Long: `Pulls the latest changes for all cloned fireflyframework repositories and +reinstalls them to your local Maven repository (~/.m2) in DAG-resolved +dependency order. + +The update process has two phases: + + Phase 1 — Pulling Latest Changes + Runs 'git pull' on each cloned repository with a live progress bar. + Repositories that are not cloned are skipped with a warning. + + Phase 2 — Installing Artifacts (skipped with --pull-only) + Runs 'mvn clean install' on each repository in dependency order. + Per-repo spinners show elapsed time. When --skip-tests is not provided, + the CLI interactively asks whether to run tests (default: yes). + +Use --repo to update a single repository by name (e.g. fireflyframework-utils). +Use --pull-only to only fetch the latest code without running Maven install. + +Examples: + flywork update Pull + install all repos + flywork update --skip-tests Skip tests during install + flywork update --pull-only Only git pull, skip Maven + flywork update --repo fireflyframework-utils Update a single repository + flywork update -v Verbose with layer details`, + RunE: runUpdate, } func init() { diff --git a/cmd/upgrade.go b/cmd/upgrade.go index ca4f9fe..55cf533 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -27,8 +27,21 @@ var upgradeCheckOnly bool var upgradeCmd = &cobra.Command{ Use: "upgrade", Short: "Upgrade the Flywork CLI to the latest version", - Long: "Checks GitHub releases for a newer version and self-updates the binary in place", - RunE: runUpgrade, + Long: `Checks GitHub releases for a newer version of the Flywork CLI and +self-updates the binary in place. + +The process: + 1. Fetches the latest release from GitHub + 2. Compares the remote version against the currently installed version + 3. If a newer version is available, downloads the platform-specific binary + 4. Replaces the current binary with the downloaded one + +Use --check to only check for updates without installing. + +Examples: + flywork upgrade Download and install the latest version + flywork upgrade --check Only check if an update is available`, + RunE: runUpgrade, } func init() { diff --git a/cmd/version.go b/cmd/version.go index 2ebc764..6515ea1 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -32,6 +32,9 @@ var ( var versionCmd = &cobra.Command{ Use: "version", Short: "Print CLI version information", + Long: `Prints the Flywork CLI version, git commit hash, build date, Go version, and +operating system/architecture. Version information is embedded at build time +via ldflags.`, Run: func(cmd *cobra.Command, args []string) { p := ui.NewPrinter() p.KeyValue("Version", Version)