Skip to content

feat(phpup): consolidate 5 CLI binaries as phpup subcommands (PR 6/6)#71

Merged
phramz merged 1 commit into
mainfrom
feat/local-ci-pr6-cli-consolidation
Apr 24, 2026
Merged

feat(phpup): consolidate 5 CLI binaries as phpup subcommands (PR 6/6)#71
phramz merged 1 commit into
mainfrom
feat/local-ci-pr6-cli-consolidation

Conversation

@phramz

@phramz phramz commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Sixth and final PR of the local-CI unification rollout (design). Merges cmd/planner, cmd/lockfile-update, cmd/gc-bundles, cmd/hermetic-audit, and cmd/compat-diff into phpup subcommands so the repo ships a single Go binary.

New subcommands (byte-identical stdout/stderr + flag surface to the retired binaries for the same inputs):

Subcommand Replaces Internal package
phpup plan cmd/planner internal/planner (cli.go added)
phpup lockfile-update cmd/lockfile-update internal/lockfileupdate
phpup gc-bundles cmd/gc-bundles internal/gcbundles
phpup hermetic-audit cmd/hermetic-audit internal/hermeticaudit
phpup compat-diff cmd/compat-diff internal/compatdiff

Each cmd/<name>/ directory was moved under internal/<name>/ (package renamed from main<name>; func main()func Main(args []string) error). Flags are parsed through a dedicated flag.FlagSet so they don't collide with phpup's setup-flow flag.Parse.

Exit conventions preserved:

  • phpup hermetic-audit: 0 = clean, 1 = findings, 2 = error (via hermeticaudit.ErrFindings returned from Main).
  • phpup compat-diff: 0 = match, 1 = deviation(s), 2 = malformed input (via compatdiff.ExitCode returned from Main).

Updated call sites:

  • .github/workflows/ci.yml: publish job uses bin/phpup lockfile-update instead of go run ./cmd/lockfile-update. github.repository_owner is pulled in via env: to keep run: free of untrusted-input interpolation.
  • .github/workflows/release-please.yml: drops dist/planner-linux-amd64 build; releases ship only phpup-linux-amd64 (planner is phpup plan).
  • Makefile: drops cmd/planner from build / build-linux-*; gc-bundles-dry-run uses $(PHPUP_BIN) gc-bundles.
  • .golangci.yml: subprocess-call allowlist paths retargeted from cmd/lockfile-update/ / cmd/gc-bundles/ → their new internal/…/ homes.

Docs refreshed: CLAUDE.md, CONTRIBUTING.md, README.md, and stale comments in internal/planner/helpers.go / internal/oci/client.go.

Test plan

  • make check green locally (25 Go packages pass; coverage held across all internal packages)
  • phpup plan --help, phpup lockfile-update --help, phpup gc-bundles --help, phpup hermetic-audit --help, phpup compat-diff --help all work and mirror the previous binaries' flags
  • CI ci.yml green on this PR
  • After merge: first push to main runs ci.yml::publish, which now invokes bin/phpup lockfile-update — verify the lockfile-update commit lands on main

Sixth and final PR of the local-CI unification rollout (see
docs/superpowers/specs/2026-04-23-local-ci-unification-design.md).
Merges cmd/planner, cmd/lockfile-update, cmd/gc-bundles,
cmd/hermetic-audit, and cmd/compat-diff into phpup subcommands so the
repo ships a single binary.

New subcommands (byte-identical stdout/stderr + flag surface to the
retired binaries for the same inputs):

  phpup plan              — was cmd/planner
  phpup lockfile-update   — was cmd/lockfile-update
  phpup gc-bundles        — was cmd/gc-bundles
  phpup hermetic-audit    — was cmd/hermetic-audit
  phpup compat-diff       — was cmd/compat-diff

Each cmd/<name>/ has been moved under internal/<name>/ (package renamed
from main; func main → func Main(args []string)). Flags are parsed
through a dedicated FlagSet so they don't collide with phpup's
setup-flow flag.Parse. Exit conventions preserved where load-bearing:

  - phpup hermetic-audit: 0 = clean, 1 = findings, 2 = error (via
    hermeticaudit.ErrFindings returned from Main)
  - phpup compat-diff: 0 = match, 1 = deviation(s), 2 = malformed input
    (via compatdiff.ExitCode returned from Main)

Updated call sites:
  - .github/workflows/ci.yml: `bin/phpup lockfile-update` replaces
    `go run ./cmd/lockfile-update` in the publish job. Uses an env var
    for github.repository_owner so the `run:` block is free of
    untrusted-input interpolation.
  - .github/workflows/release-please.yml: drops the
    `dist/planner-linux-amd64` build; releases now ship only
    phpup-linux-amd64 (planner is accessible as `phpup plan`).
  - Makefile: drops the second `go build` of cmd/planner in `build` /
    `build-linux-*` targets; `gc-bundles-dry-run` now calls
    `$(PHPUP_BIN) gc-bundles` instead of `go run ./cmd/gc-bundles`.
  - .golangci.yml: retargeted subprocess-call allowlist paths from
    `cmd/lockfile-update/`, `cmd/gc-bundles/` to their new
    `internal/lockfileupdate/`, `internal/gcbundles/` homes.
  - compat-diff tests build phpup via `./cmd/phpup` and prepend
    `compat-diff` to argv to keep the integration-style exit-code
    checks intact.

Docs refreshed:
  - CLAUDE.md Architecture section now describes phpup as the single
    binary hosting runtime + maintainer subcommands.
  - CONTRIBUTING.md Project Structure section updated; orphan-bundle
    cleanup instruction now uses `phpup gc-bundles`.
  - README.md compat-matrix section refers to `phpup compat-diff`.
  - Stale comments in internal/planner/helpers.go and
    internal/oci/client.go that pointed at the deleted cmd/ paths.

Verification: `make check` green. Each new subcommand exercises
`--help` (help output identical to the retired binaries aside from the
"Usage of phpup <name>:" prefix) and runs through its package test
suite (20+ tests across the five new internal packages).
@phramz
phramz merged commit 0ff12e4 into main Apr 24, 2026
20 checks passed
@phramz
phramz deleted the feat/local-ci-pr6-cli-consolidation branch April 24, 2026 09:37
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