feat(init): support extension install during initialization#2180
feat(init): support extension install during initialization#2180officialasishkumar wants to merge 3 commits intogithub:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for installing extensions during specify init, including a transition path away from legacy init flags and toward explicit extension opt-in.
Changes:
- Introduces repeatable
specify init --extension <value>for bundled IDs, local extension directories, and archive URLs, and persists selected extensions in.specify/init-options.json. - Ensures init-time extension installs occur before the default git-extension auto-install, and adds user-visible notices/deprecation warnings (
--ai,--no-git). - Expands CLI integration tests and updates README init documentation/examples.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Adds init-time extension installation flow (name/path/URL), persistence of init options, and deprecation/notice messaging. |
tests/integrations/test_cli.py |
Adds integration tests covering local extension install, repeatable --extension, explicit --extension git with --no-git, and new warnings/notices. |
README.md |
Updates init option docs to include --extension and deprecations; adjusts headings and examples. |
Comments suppressed due to low confidence (1)
README.md:424
- The examples section mixes the new recommended
--integrationflag with several--aiexamples (e.g. qodercli/windsurf/kiro-cli/etc.), even though--aiis now documented as deprecated above. To avoid encouraging deprecated usage, update these remaining examples to use--integration <key>(or explicitly label--aiexamples as legacy/deprecated).
# Initialize with Cursor support
specify init my-project --integration cursor-agent
# Initialize with Qoder support
specify init my-project --ai qodercli
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Adds init-time extension installation support to specify init, including persistence of requested extensions and updated user-facing messaging around upcoming deprecations/default behavior changes.
Changes:
- Added repeatable
specify init --extension ...support (bundled IDs, local extension dirs, and archive URLs) and persisted selections in.specify/init-options.json. - Installed requested extensions during init ahead of default git-extension auto-install, plus added deprecation warnings for
--aiand--no-gitand a post-init notice about the git extension default changing in v1.0.0. - Updated CLI integration tests and README documentation to cover the new init/extension workflow.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Implements init-time extension install flow, URL/archive handling, deprecation warnings, and git-default notice. |
tests/integrations/test_cli.py |
Adds CLI/integration tests for --extension (local dirs, repeatable values, explicit git, TAR safety, bounded URL downloads) and deprecation output assertions. |
README.md |
Documents --integration as primary, adds --extension flag docs/examples, and adjusts related init documentation. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
README.md:424
- In the Examples section, most agent examples still use
--ai ...even though the README now introduces--integrationas the recommended flag and--aias a deprecated alias. Consider switching these examples to--integrationto align with the new guidance (keeping one--aiexample only if you want to explicitly demonstrate the deprecated alias).
# Initialize with Cursor support
specify init my-project --integration cursor-agent
# Initialize with Qoder support
specify init my-project --ai qodercli
- Files reviewed: 3/3 changed files
- Comments generated: 4
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback. If not applicable, please explain why
4ddb1cb to
9889c0b
Compare
There was a problem hiding this comment.
Pull request overview
Adds init-time extension installation and messaging to support the transition away from the git extension being enabled by default, while preserving legacy init flags with deprecation warnings.
Changes:
- Adds repeatable
specify init --extension ...to install bundled extensions, local extension directories, and extension archive URLs during initialization (and persists choices to.specify/init-options.json). - Adds visible deprecation warnings for
--aiand--no-git, plus a non-blocking notice when the git extension is auto-enabled by default. - Updates CLI integration tests and README documentation to reflect the init/integration/extension workflow.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Implements init-time extension installation flow, URL download/install helpers, deprecation warnings, and git-default-change notice; redacts URLs in extension add. |
tests/integrations/test_cli.py |
Adds coverage for init --extension (local/bundled/URL), URL redaction, TAR safety checks, and bounded-download behavior. |
README.md |
Updates init option docs/examples to center --integration and document --extension and deprecations. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 2
| ) | ||
|
|
||
| if not tarfile.is_tarfile(archive_path): | ||
| raise ValidationError("Extension archive must be a ZIP, .tar.gz, or .tgz file") |
There was a problem hiding this comment.
The error message here says archives must be ZIP, .tar.gz, or .tgz, but the implementation accepts plain .tar as well (tarfile.is_tarfile + tarfile.open('r:*')). Either update the message to include .tar, or enforce the intended restriction by rejecting .tar files explicitly so users aren’t misled.
| raise ValidationError("Extension archive must be a ZIP, .tar.gz, or .tgz file") | |
| raise ValidationError( | |
| "Extension archive must be a ZIP, .tar, .tar.gz, or .tgz file" | |
| ) |
There was a problem hiding this comment.
Updated the validation message to include .tar, matching the archive formats the implementation accepts.
| console.print("Only install extensions from sources you trust.\n") | ||
| console.print(f"Downloading from {from_url}...") | ||
| console.print(f"Downloading from {display_url}...") | ||
|
|
||
| # Download ZIP to temp location | ||
| download_dir = project_root / ".specify" / "extensions" / ".cache" / "downloads" |
There was a problem hiding this comment.
In the --from URL install branch, the download implementation later uses response.read() to pull the entire archive into memory before writing it out. This can cause large memory spikes and lacks the MAX_EXTENSION_ARCHIVE_BYTES safeguard you added for init-time URL installs. Consider reusing the same bounded streaming helper (and shared URL validation) here so specify extension add --from ... also downloads in chunks with a size limit.
There was a problem hiding this comment.
Reworked this path to use the shared bounded streaming URL download helper instead of reading the response into memory.
|
Can you please address each of the issues separately? |
Add repeatable --extension support to specify init for bundled extension IDs, local extension directories, and archive URLs. Persist requested extensions in init options and install them before the default git-extension auto-install so explicit git opt-in does not double-install. Warn when legacy --ai and --no-git flags are used, and show a visible notice when the git extension is still auto-enabled by default ahead of the v1.0.0 opt-in change. Update README init option docs and add CLI regression coverage for init-time extension installation and deprecation messaging. Signed-off-by: Asish Kumar <[email protected]>
Signed-off-by: Asish Kumar <[email protected]>
Signed-off-by: Asish Kumar <[email protected]>
9889c0b to
ab5e033
Compare
Description
Closes #2165
Closes #2166
Closes #2167
Closes #2169
Adds the init-time extension transition path:
specify init --extension <value>support for bundled extension IDs, local extension directories, and extension archive URLs..specify/init-options.jsonand installs them before the default git-extension auto-install, so explicit--extension gitdoes not double-install.--aiand--no-gitwhile preserving current behavior.--extension gitorspecify extension add git.Testing
.venv/bin/specify --help(uvis not installed in this environment).venv/bin/python -m pytest -q--extension git, and default git auto-install)Additional checks:
.venv/bin/ruff check src/npx --yes markdownlint-cli2 README.mdgit diff --checkAI Disclosure
I used AI assistance for codebase analysis, implementation support, test updates, and PR drafting. I reviewed the resulting changes and validated them locally with the commands listed above.