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
127 changes: 116 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]`

Expand All @@ -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`

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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:**
Expand Down Expand Up @@ -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`

Expand Down Expand Up @@ -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.
Expand All @@ -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`.
Expand All @@ -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:
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
40 changes: 38 additions & 2 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <name> 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() {
Expand Down
50 changes: 43 additions & 7 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <key> Get a single configuration value
set <key> <value> 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 <key>",
Short: "Get a configuration value",
Use: "get <key>",
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 <key> <value>",
Short: "Set a configuration value",
Use: "set <key> <value>",
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,
Expand All @@ -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() {
Expand Down
32 changes: 29 additions & 3 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/<name>.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(),
}

Expand Down
Loading