diff --git a/CLAUDE.md b/CLAUDE.md index 4f4938e..bfa5469 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,7 +37,12 @@ internal/packages/ npm global snapshot / restore / migrate (merged in PR internal/platform/ platform.go DataDir(), SnapshotsDir(), CacheDir(), LockPath(), IsWindows(), … shell.go RunShell() — all shell exec goes here -internal/ui/ scaffold (mode.go + theme.go + writer.go) merged via #74 PR1; spinners/huh/full migration tracked by #105 +internal/ui/ single source of truth for user-facing output + mode.go Mode (PlainMode / FancyMode) + DecideMode (TTY + NO_COLOR + --no-color gating) + theme.go DefaultTheme — lipgloss styles for FancyWriter + writer.go Writer interface + PlainWriter / FancyWriter implementations + spinner.go bubbletea-backed braille spinner for long-running steps + prompt.go huh-backed Confirm / Select helpers for interactive flows ``` ## Key invariants — read before writing code @@ -52,9 +57,9 @@ internal/ui/ scaffold (mode.go + theme.go + writer.go) merged via **Platform-specific code:** Use `//go:build windows` build tags on `*_windows.go` files. Files without build tags must compile on all three OSes. -**Dependencies:** No new dependencies without a rationale line in the PR body. Core runtime deps: `cobra`, `Masterminds/semver/v3`, `yaml.v3`, `lipgloss` (for `internal/ui` — see #74). Planned but not yet in `go.mod`: `huh`, `bubbletea` (the remaining Charm stack for `internal/ui` spinners + prompts — see #105). +**Dependencies:** No new dependencies without a rationale line in the PR body. Core runtime deps: `cobra`, `Masterminds/semver/v3`, `yaml.v3`, plus the Charm stack for `internal/ui`: `lipgloss` (styling), `bubbletea` (spinner), `huh` (prompts). The plain-vs-fancy switch is the single decision point — see `internal/ui/mode.go`. -**Manager detection order:** `--manager` flag → `~/.nodeup/config.yaml` → auto-detect (env vars → PATH → well-known dirs). `DetectAll()` returns a `Registry`; `ResolveManager(reg, preferred)` picks one or errors. When multiple managers found and no preference, the caller should use `ResolveInteractive` (planned under #105 as part of the `huh` migration). +**Manager detection order:** `--manager` flag → `~/.nodeup/config.yaml` → auto-detect (env vars → PATH → well-known dirs). `DetectAll()` returns a `Registry`; `ResolveManager(reg, preferred)` picks one or errors. When multiple managers found and no preference, the caller should use `ResolveInteractive` (a `huh`-backed Select that lives in `internal/detector/interactive.go` — wired up by #118 as part of the `huh` migration). **Packages to skip during migration:** `npm`, `corepack`, `npx` — these are bundled with Node and must not be migrated. @@ -127,8 +132,8 @@ orchestrator. | 4 — Upgrade command + UI | Done | merged | | 5 — Config subsystem | Done | merged | | 6 — Cross-platform polish | Done | merged (interrupted-upgrade sentinel, `QuotePath`, system-node classifier) | -| 7 — Distribution packaging | Done | GoReleaser, brew/scoop/npm wrappers all shipped (#17, #18); manual v1.0.0 npm publish tracked by #35 | -| 8 — v1.0.0 release | Done | `nodeupx@1.0.1` live on npm (closes #35); trusted-publisher OIDC flow in place for future tags | +| 7 — Distribution packaging | Done | GoReleaser, brew/scoop/npm wrappers all shipped (#17, #18); manual v1.0.0 npm publish (#35) bootstrapped the OIDC trust | +| 8 — v1.0.0 → v1.1.0 releases | Done | `nodeupx@1.0.1` (and now `@1.1.0` matching the Go binary) live on npm; trusted-publisher OIDC flow active for every tag (`#109`) | ## On-disk data layout diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c13b2a3..ea70de9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ opening an issue or a PR. ## Quick orientation -- **Language / runtime:** Go 1.22+ +- **Language / runtime:** Go 1.24+ - **Architecture:** see the `How it works` section in [`README.md`](./README.md) for the high-level pipeline. The single source of truth for implementation details is the Go source under `internal/` plus inline godoc. @@ -123,7 +123,7 @@ by hand in PRs. - **Feature requests:** use `.github/ISSUE_TEMPLATE/feature_request.md`. Read the in-template "Out-of-scope check" before filing — `.nvmrc` / `.node-version` management, `npm`-itself updates, `yarn`/`pnpm` - globals, and self-updates are explicitly out of scope for v1. + globals, and self-updates are explicitly out of scope for v1.x. - **Security issues:** do **not** open a public issue. Email the maintainer directly (see GitHub profile) and give 90 days for a coordinated fix. @@ -139,11 +139,6 @@ by hand in PRs. `fmt.Println` from business logic. This keeps output testable and uniform (color, spinners, summary tables). - **No new dependencies without a rationale line in the PR body.** We - lean on the stdlib + cobra + yaml.v3. - -## Sign-off (future) - -When the project gains external contributors, we'll require a -[DCO](https://developercertificateoforigin.org/) sign-off (`Signed-off-by:` -trailer on every commit). Not required today; will be enabled by a -`.github/workflows/dco.yml` check before the v1.0.0 release. + lean on the stdlib + `cobra` + `yaml.v3` + the Charm stack + (`lipgloss`, `bubbletea`, `huh` — all of which live behind the + `internal/ui` boundary). diff --git a/README.md b/README.md index 2e89b5d..acd7990 100644 --- a/README.md +++ b/README.md @@ -150,8 +150,9 @@ Expand-Archive nodeup.zip -DestinationPath . go install github.com/dipto0321/nodeup/cmd/nodeup@latest ``` -Requires Go 1.22+. Best for: `nodeup` contributors and anyone who -wants to track `main` between releases. +Requires Go 1.24+ (matches `go.mod` and the CI pin). Best for: +`nodeup` contributors and anyone who wants to track `main` between +releases. ## Quickstart @@ -243,19 +244,24 @@ See [`docs/configuration.md`](./docs/configuration.md) for the full schema. ## Project status -This is the **v1.0.0 development line**. See `CHANGELOG.md` for what's done. +Current release: **v1.1.0** (`nodeupx@1.0.1` on npm — the npm wrapper +trails the Go binary by one publish). See `CHANGELOG.md` for the +v1.0.0 → v1.1.0 history. -| Version | Status | Notes | +| Phase | Status | What shipped | |---|---|---| -| v1.0.0 | 🛠 in development | Phase 1 ✅ — 8/8 managers detected. Phase 2 ✅ — `nodeup check` with nodejs.org/dist/index.json fetch + TTL cache. Phase 3 ✅ — package snapshot/restore + migration report. Phase 4 ✅ — end-to-end `nodeup upgrade`. Phase 5 ✅ — YAML config file + `config` subcommands (show / get / set / init). Phase 6 ✅ — cross-platform polish: `QuotePath` for paths with spaces, interrupted-upgrade sentinel + replay, system-node classifier with warnings. Phase 7 🔧 (in progress) — post-upgrade cleanup prompt (`--cleanup` / `--cleanup-version` / `--no-cleanup` / `cleanup.auto` / `cleanup.prompt`) plus native mutation commands for all 7 supported managers have shipped. Distribution packaging (GoReleaser + brew/scoop taps + npm wrapper) is the remaining Phase 7 work — see issues #17 and #18. | - -Phase 1 is the **detection surface** — every manager is recognized and the -version + installed-list reads return real data (PRs #1–#8). Subsequent -phases layer commands on top: `nodeup check` (Phase 2) → `nodeup packages` -(Phase 3) → `nodeup upgrade` end-to-end (Phase 4) → `nodeup config` -(Phase 5) → cross-platform polish (Phase 6) → first tagged release -(Phase 7). The v1.0.0 cut is blocked on Phase 7 (issue #17) and the -release-prep runbook (issue #18). +| 1 — Detector engine | ✅ | 8/8 managers detected (`fnm`, `nvm`, `Volta`, `asdf`, `mise`, `n`, `nodenv`, `nvm-windows`) | +| 2 — Node version API | ✅ | `nodeup check` + nodejs.org/dist/index.json fetch + TTL cache + HTTP retry/backoff/timeout | +| 3 — Package snapshot/restore | ✅ | `nodeup packages {snapshot,restore,diff}` + interrupted-upgrade sentinel + MigrationReport | +| 4 — Upgrade command | ✅ | End-to-end `nodeup upgrade` with snapshot → install → migrate → cleanup | +| 5 — Config subsystem | ✅ | YAML config at `~/.nodeup/config.yaml` + `config {show,get,set,init}` + env vars | +| 6 — Cross-platform polish | ✅ | `QuotePath`, interrupted-upgrade replay, system-node classifier, lock file | +| 7 — Distribution packaging | ✅ | GoReleaser + brew tap + Scoop bucket + npm wrapper (`nodeupx` via OIDC Trusted Publishing) | +| 8 — First tagged release | ✅ | `v1.0.0` shipped (PR #35); `v1.1.0` shipped with the `internal/ui` rollout (`#117`/`#118`/`#119`) | + +**Release train:** every `v*.*.*` tag triggers GoReleaser → brew formula +push → Scoop manifest push → `nodeupx` publish via OIDC. To ship a +new version: see `docs/release-checklist.md`. ## Docs index diff --git a/SPEC.md b/SPEC.md index b24f83b..e6f0a7b 100644 --- a/SPEC.md +++ b/SPEC.md @@ -1,8 +1,9 @@ # SPEC — nodeup Distilled from code (README, CLAUDE.md, CONTRIBUTING.md, docs/*, and -`internal/*` source). Last refresh: 2026-07-05 (post #103 fix-wave; -§C/V2 + §T updated to match current state). +`internal/*` source). Last refresh: 2026-07-05 (post v1.1.0 release; +§C/§I/§V/§T updated to match current state — `internal/ui` rollout +complete via #117/#118/#119, #120/#121 are commitlint relaxations). Caveman encoding per FORMAT.md convention (not present at repo root — using shapes from the caveman skill). @@ -26,8 +27,9 @@ manual steps, single static binary, no Node runtime dependency. `/` or `\`. - `*_windows.go` → `//go:build windows`; other files compile ∀ 3 OS (macOS, Linux, Windows). -- ∀ user-facing output → `internal/ui` (scaffold merged via #74 PR1; - spinners + huh prompts + full call-site migration tracked by #105). +- ∀ user-facing output → `internal/ui` (Writer + Plain/Fancy modes + + bubbletea spinners + huh prompts + full call-site migration shipped + via #74 → #117 → #118 → #119). - packages `{npm, corepack, npx}` ⊥ migrate (bundled w/ Node itself). - Manager resolution order: `--manager` flag → `~/.nodeup/config.yaml` → env vars → PATH → well-known dirs. @@ -62,9 +64,9 @@ manual steps, single static binary, no Node runtime dependency. ## §V Invariants - V1: ∀ shell exec → `platform.RunShell()` | `RunShellScript()` (never raw `os/exec`). -- V2: ∀ user-facing string → `internal/ui` (partial — scaffold via #74 PR1; - full migration tracked by #105; cmd.Printf still present in upgrade/check/ - list/packages/config/cleanup). +- V2: ∀ user-facing string → `internal/ui` (complete — full migration + shipped via #119; every `cmd.Printf` / `fmt.Fprintf` call site in + `internal/cli/*` now flows through `ui.Writer`). - V3: ∀ error return → handled, wrapped w/ `%w` for context. - V4: ∀ cobra `RunE` → `cmd.Context()`, ⊥ `context.Background()`. - V5: ∀ path → `filepath.Join()`, ⊥ hardcoded separators. @@ -116,10 +118,10 @@ T14|x|fail closed (not open) when Current() errors during cleanup|V14,#58,#87 T15|x|verify/fix `n` manager's reliance on `n current` subcommand|#59,#88 T16|x|fix cleanup docs inaccuracies (CHANGELOG issue ref, nvm-windows note, PATH failure mode, Phase 7 conflict)|#60,#97 T17|x|dead-code cleanup: report.go, FileOverlay(), confirm var, fnm.go error wrap, nvm Current() test gap|#61,#98 -T18|.|design + implement internal/ui output layer|V2,#74,#105 -T19|.|fix double-prompt + sticky-no-override at cleanup decision point|#76,#95 +T18|x|design + implement internal/ui output layer|V2,#74,#105,#117,#118,#119 +T19|x|fix double-prompt + sticky-no-override at cleanup decision point|#76,#95 T20|x|rest of cleanup/chore/ci/release batch|#62-#69,#89-#94,#99,#100,#107-#109 -T21|.|doc drift: CLAUDE.md ui/lipgloss/phase-table stale; SPEC §T stale|#106 +T21|x|doc drift: CLAUDE.md ui/lipgloss/phase-table stale; SPEC §T stale|#106 ## §B Bugs diff --git a/docs/installation.md b/docs/installation.md index 09cbc1e..d4a32b5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -139,7 +139,7 @@ self-contained — no runtime, no Node, no manager. go install github.com/dipto0321/nodeup/cmd/nodeup@latest ``` -Requires Go 1.22+. +Requires Go 1.24+ (matches `go.mod` and the CI pin in `.github/workflows/ci.yml` + `release.yml`). **Who this is for:** `nodeup` contributors and Go developers who want to track `main` between tagged releases. The binary lands in diff --git a/docs/managers.md b/docs/managers.md index 79bbf77..c237cba 100644 --- a/docs/managers.md +++ b/docs/managers.md @@ -77,7 +77,7 @@ bin dir (e.g., `fnm env --use-on-cd | source`, or add points at a binary inside the manager's data dir, nodeup's next run will classify it as `manager` and proceed without warning. -> _Status: Phase 7 in progress — post-upgrade cleanup prompt and per-manager native mutation commands have shipped (PR #56 / issue #41). Distribution packaging (GoReleaser, brew/scoop taps, npm wrapper) is the remaining Phase 7 work — see issues #17 and #18. README's "Phase 7 ✅" line refers to the cleanup/mutation work, not the distribution work._ +> _Status: Phase 7 complete. Post-upgrade cleanup prompt, per-manager native mutation commands, and full distribution packaging (GoReleaser, brew/scoop taps, npm wrapper at `nodeupx@1.0.1` via OIDC Trusted Publishing) have all shipped — see `CHANGELOG.md` for the v1.0.0 → v1.1.0 history._ ## Post-upgrade cleanup diff --git a/docs/release-checklist.md b/docs/release-checklist.md index d1da98c..420c333 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -2,8 +2,10 @@ The release pipeline (`.github/workflows/release.yml` + GoReleaser v2) fires automatically on a `v*.*.*` tag push. This checklist is the -human-side companion — use it for the **first stable release** (v1.0.0), -and ad-hoc when shipping a patch release. +human-side companion for shipping any release — including patch +releases off `main`. The first `nodeupx@1.0.1` bootstrap publish was +the only manual step ever required and is preserved below for +historical reference. ## Pre-release (on `chore/release/vX.Y.Z` branch)