Adopt Bashly (bashly.dev) to generate the installer from a single YAML-defined CLI
## Summary Adopt [Bashly](https://bashly.dev/) as the framework for building the installer, replacing the hand-written, hand-maintained bash scripts with a single generated CLI defined in YAML plus per-command bash partials. ## Current state The installer is ~750 lines of hand-rolled bash spread across four files on `1.0.x`: - `install.sh` (61) — OS/distro detection and dispatch - `install-macos.sh` (258) - `install-linux.sh` (283) - `github-push.sh` (147) — sourced at runtime Pain points this creates: - **Duplicated boilerplate.** The color codes and `step`/`ok`/`warn`/`die` helper functions are copy-pasted into `install.sh`, `install-macos.sh`, `install-linux.sh`, and `github-push.sh`. A change to one must be repeated in all four. - **Runtime script fetching.** `install.sh` does `bash <(curl ... install-<os>.sh)` and the platform scripts in turn `curl ... github-push.sh` into a temp file and `source` it. This couples execution to network availability of every individual file and makes the control flow hard to follow. - **Manual argument parsing.** `-yolo` is parsed with an ad-hoc `for arg in "$@"` loop in each platform script. There is no `--help`, no `--version`, and no validation of unknown flags. - **No structure for subcommands.** Distinct behaviours (new-site vs existing-project, the `test-mr` contributor tool) are separate scripts or inline branches rather than first-class commands. ## What Bashly gives us [Bashly](https://bashly.dev/) is a Ruby gem that generates a **single, dependency-free bash script** from a `bashly.yml` definition plus bash partials for each command: - One generated `install.sh` bundles everything — no runtime `curl`-and-`source` of sibling scripts, so `bash <(curl ...)` still works but pulls one file. - Automatic argument parsing, `--help`/`--version`, flag validation, required args, and environment-variable handling. - Shared library functions (colors, `step`/`ok`/`die`) defined once and injected into the bundle, eliminating the four-way duplication. - Natural home for subcommands, e.g. `install`, `install --existing`, `test-mr <MR>`. - The generated output is committed, so end users still need **zero** Ruby/gem tooling; only maintainers regenerating the script do. ## Proposed approach 1. Add Bashly as a dev/build dependency and a `bashly.yml` defining the CLI (commands, flags like `--yolo`, args). 2. Port the existing logic into `src/` command and library partials, factoring the duplicated helpers into a single shared library. 3. Commit the generated `install.sh` and wire regeneration into CI so the committed script can't drift from `src/`. 4. Keep the public entry point identical: `bash <(curl -fsSL .../install.sh)` — no change for end users. ## Risks / open questions - **Build-time dependency.** Maintainers need Ruby + the Bashly gem to regenerate. End users are unaffected (they run the committed output). - **Generated diffs.** The committed generated script produces large diffs; CI regeneration + a check that the committed file matches `src/` mitigates drift and review noise. - **Scope.** This is a structural refactor and should be staged so behaviour is preserved at each step; it may be split into child issues (scaffold CLI, port macOS, port Linux, port github-push, CI regeneration). - Confirm Bashly's license and maintenance status are acceptable for a Drupal contrib project before committing. --- *Proposed after a code read of branch `1.0.x`. Issue drafted with AI (Claude) assistance.*
issue