# DeployForge (CLI prototype) DeployForge is a working prototype of a manifest-driven, idempotent check-then-install step runner: you describe a deployment as an ordered list of steps, each with a "check" command (does this already look done?) and an "install" command (make it done), and DeployForge runs the list, skipping any step whose check already passes and logging the whole run. This is the real mechanism underneath "guided deployment recipes" like Ansible or Chocolatey-style provisioning, implemented here in a minimal, dependency-free form. The full DeployForge product concept also covers custom Windows image creation, unattended setup, boot USB creation, EFI repair, and driver injection -- all of that requires privileged, Windows-only deployment APIs (DISM, WinPE, Windows Setup, firmware/EFI access) that cannot be built as a portable, dependency-free Go CLI, so those pieces are intentionally out of scope for this prototype and are tracked as roadmap items. See ../plan.md for the full product plan. ## Build from source Requires Go 1.24+, no external dependencies. go build -o deployforge . Cross-compile for another platform: GOOS=windows GOARCH=amd64 go build -o deployforge.exe . GOOS=darwin GOARCH=arm64 go build -o deployforge . ## Usage deployforge apply [--dry-run] [--log run.log] deployforge validate deployforge help ### Manifest format A manifest is a JSON file describing a deployment recipe as a name and an ordered list of steps. Each step's "check" and "install" are shell command lines, run via the OS-appropriate shell (`sh -c` on macOS/Linux, `cmd /C` on Windows): { "name": "dev-workstation-setup", "steps": [ { "name": "create-projects-dir", "check": "test -d /tmp/deployforge-demo/projects", "install": "mkdir -p /tmp/deployforge-demo/projects" }, { "name": "write-config-file", "check": "test -f /tmp/deployforge-demo/config.txt", "install": "sh -c \"echo configured > /tmp/deployforge-demo/config.txt\"" } ] } ### apply For each step, in order: 1. Run its "check" command. If it exits 0, the step is ALREADY SATISFIED: the install command is skipped entirely, and the step is reported "SKIP (already satisfied)". 2. If check exits non-zero, the step is NOT satisfied: - Without --dry-run: the "install" command runs. If it exits 0, the step is reported "INSTALLED". If it exits non-zero, the step is reported "FAILED" -- and DeployForge STOPS processing further steps (fail-fast) and exits the whole command with a non-zero status. A failed step likely means later steps that depend on it would fail too, so remaining steps are never attempted. - With --dry-run: the install command never runs at all. The step is reported "WOULD INSTALL (check failed)", and, unlike a real run, the preview continues through every remaining step regardless of outcome -- since nothing is actually happening, there is no reason to stop early. A final summary line reports counts: satisfied / installed / failed for a real run, or satisfied / would-install for a dry run. Flags: --dry-run Preview only; never runs install commands, never stops early. --log Append a JSON-lines record of every step's outcome to -- one JSON object per line, with fields name, verdict, check_exit_code, install_exit_code (or null), timestamp, and dry_run (true/false so a real apply and a preview are clearly distinguished in the log). Real runs and dry runs both write to the log, and entries are appended, so a single file can accumulate a full history across many invocations. ### validate Parses the manifest and checks that: - it is valid JSON - every step has a non-empty name, check, and install - no two steps share the same name Nothing is executed. Reports "OK: manifest ... is valid" and exits 0, or lists each specific problem found and exits non-zero. ## Prebuilt binaries See ../downloads/ for prebuilt binaries (Windows/macOS/Linux) and CHECKSUMS.txt for their SHA-256 hashes. These are unsigned indie builds -- Windows SmartScreen and macOS Gatekeeper will warn on first run, which is expected until a code-signing certificate is in place.