feat(cli): implement specify self upgrade#2475
feat(cli): implement specify self upgrade#2475chordpli wants to merge 28 commits intogithub:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Implements a functional specify self upgrade command to replace the previous reserved stub, enabling in-place upgrades (uv tool / pipx) with install-method detection, dry-run previews, tag pinning, token scrubbing, and post-upgrade verification via a child specify --version.
Changes:
- Adds install-method detection + upgrade orchestration helpers and replaces the
self upgradestub with a working implementation. - Introduces a comprehensive new test suite for
specify self upgradeand removes the old stub-pin tests. - Updates README and docs to recommend
specify self upgradeand document the new flows.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Adds self-upgrade planning/execution/verification logic and updates self command help text. |
tests/test_self_upgrade.py |
New test module covering detection, argv assembly, dry-run behavior, tag validation, token scrubbing, and verification. |
tests/test_upgrade.py |
Removes tests that pinned the previous non-functional stub output. |
README.md |
Documents specify self check / specify self upgrade as the preferred upgrade path. |
docs/upgrade.md |
Refreshes upgrade guide to include self-upgrade commands, verification steps, and troubleshooting. |
docs/installation.md |
Adds “Stay current” pointer to specify self check and upgrade guide. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@mnriem I’ve addressed the Copilot review feedback, rebased onto the latest |
There was a problem hiding this comment.
Copilot's findings
Comments suppressed due to low confidence (1)
docs/upgrade.md:40
- In the recommended command block,
specify self upgrade --tag vX.Y.Zis shown without indicating it’s a placeholder; the implementation rejects that literal value via--tagvalidation. Consider adding “replace vX.Y.Z …” or using a real tag so the snippet is copy/paste-safe.
# Upgrade in place to the latest stable release (auto-detects uv tool vs pipx install)
specify self upgrade
# Or pin a specific release tag
specify self upgrade --tag vX.Y.Z
</details>
- **Files reviewed:** 6/6 changed files
- **Comments generated:** 3
|
@mnriem I’ve addressed the latest review feedback and pushed the follow-up fixes. Could you please take another look when you have a moment? |
Summary
Replace the v0.7.5 reserved stub from #2316 with an actually working
specify self upgradecommand. Closes the unresolved portion of #2282.The CLI classifies the runtime via a 3-tier detection ladder, runs the appropriate installer subprocess, and verifies the result by spawning a fresh
specify --versionin a child process (the in-process module is still the pre-upgrade build).Behavior
specify self upgrade— executes immediately. No confirmation prompt. Matches thepip install -U/uv tool upgrade/npm updateconvention.--dry-run— on upgradable paths (uv tool,pipx) prints the preview block (method / current / target / installer argv) and exits 0 without launching any subprocess. On non-upgradable paths (uvx (ephemeral)/ source checkout / unsupported) emits the same path-specific guidance as a non-dry-run invocation and exits 0.--tag vX.Y.Z[suffix]— pins a specific release tag. Validated against^v\d+\.\d+\.\d+(?:[a-z0-9.+\-]*)?$; rejects barelatest, branch names, hash refs.uv tool/pipx(auto-upgrade),uvx (ephemeral)/ source-checkout / unsupported (path-specific guidance + exit 0, no installer launched).GH_TOKEN/GITHUB_TOKENscrubbed from child-process environments; never appears in installer argv.Exit codes
0--dry-run, or non-upgradable path with guidance)1--tagregex validation failure2specify --versiondoes not resolve to target)3124SPECIFY_UPGRADE_TIMEOUT_SECSis set)Files changed
src/specify_cli/__init__.py— Phase 2 helpers (_InstallMethod,_UpgradePlan,_detect_install_method,_assemble_installer_argv,_build_upgrade_plan,_run_installer,_verify_upgrade,_emit_guidance,_emit_failure,_validate_tag,_scrubbed_env, …) + replacedself_upgrade()orchestrator body. Also refreshes the now-staleselfgroup help andself_check()docstring sospecify self --help/specify self check --helpreflect the current behavior.tests/test_self_upgrade.py(new) — 44 test cases across 23 classes covering detection, argv assembly, dry-run, tag validation, token scrubbing, verification flows.tests/test_upgrade.py— removedTestSelfUpgradeStub(the stub it pinned no longer exists).README.md—Get Started → Install Specify CLI → Option 1now leads withspecify self upgradeas the recommended path; manual--forceretained as fallback.docs/upgrade.md— Quick Reference table, Part 1, Verify, Common Scenarios, and Troubleshooting all updated.docs/installation.md— Verification section gets a "Stay current" pointer.Test plan
uvx ruff check src/— cleanuv sync --extra test+uv run pytest— 2828 passed, 34 skipped on Python 3.11 / 3.12 / 3.13tests/test_self_upgrade.py+tests/test_upgrade.py— 88 passed combinedspecify self upgrade --dry-run→ preview, target=v0.8.6 (auto-resolved)specify self upgrade --dry-run --tag v0.8.0+build.42→ build-metadata tag acceptedspecify self upgrade --dry-run --tag latest→BadParameter(regex rejection)Notes for reviewers
pip install -U/uv tool upgrade/npm update)._fetch_latest_release_tag()(added in feat(cli): add specify self check and self upgrade stub #2316) is reused unchanged. No new GitHub HTTP code.re,dataclasses,enum,urllib.parse); PEP 723 deps unchanged._-prefixed; no new public API surface.Design and ripple review context
This change was developed through the full speckit workflow:
specify -> plan -> tasks -> blueprint -> implement -> ripple-scan -> ripple-resolve.Design artifacts (spec, plan, blueprint, ripple-report) were kept in
specs/002-self-upgrade-apply/during development and are not part of this PR.Ripple review surfaced 9 findings. Each was triaged as either resolved in-branch or accepted risk with explicit rationale.