feat(dev): add integration scaffolder (#2685)

* feat(dev): add integration scaffolder

* fix(dev): address integration scaffold review feedback

* fix(dev): address scaffold follow-up review

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix(dev): default scaffolded integrations to multi_install_safe = False

The scaffold template emitted `multi_install_safe = True` alongside a
placeholder `context_file = "AGENTS.md"`. Registered as-is, that violates the
registry contract (test_safe_integrations_have_distinct_context_files): codex
already pairs AGENTS.md with multi_install_safe = True, so the generated
boilerplate would collide on first registration.

Default the scaffold to False (matching IntegrationBase) so generated code is
registry-test-friendly out of the box; contributors opt in once they pick a
unique context_file. Aligns the generated test skeleton and both scaffold
tests, which previously contradicted each other (one expected True, one False).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): harden scaffold writes and accept case-insensitive --type

- Guard scaffold_integration() against symlinked target directories: walk
  each path component under the repo root and refuse symlinked dirs, then
  confirm the write destination resolves inside the repo (mirrors the
  manifest directory guard). Prevents scaffolding outside the repo when a
  contributor's integrations/tests path is symlinked.
- Make the `--type` click.Choice case-insensitive so `--type YAML` is
  accepted, matching scaffold_integration()'s strip()/lower() normalization
  instead of rejecting at the CLI layer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): report scaffold filesystem failures as a clean CLI error

The `dev integration scaffold` command only caught FileExistsError/ValueError,
so an OSError raised during mkdir()/write_text() (permission denied, read-only
checkout, a path component that is a file, ...) bubbled up as a traceback
instead of a clean error + exit code. Broaden the handler to OSError (which
also covers FileExistsError) and add coverage for the filesystem-error path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(dev): move scaffold command under integration

* fix(dev): roll back partial scaffold writes

* fix(dev): correct lint docs and generated test docstring

- local-development.md: ruff check src/ is enforced in CI, not absent
- scaffolded test docstring: drop misleading 'scaffold' wording

* fix(scaffold): create only leaf integration directory

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Pascal THUET
2026-06-17 00:48:40 +02:00
committed by GitHub
parent 497ca074ed
commit 9cd20c6c25
5 changed files with 613 additions and 9 deletions

View File

@@ -98,15 +98,41 @@ ls -l scripts | grep .sh
On Windows you will instead use the `.ps1` scripts (no chmod needed).
## 6. Run Lint / Basic Checks (Add Your Own)
## 6. Scaffold a Built-In Integration
Currently no enforced lint config is bundled, but you can quickly sanity check importability:
Use the integration scaffold command to create the initial Python package and
test skeleton for a new built-in integration:
```bash
specify integration scaffold my-agent --type markdown
specify integration scaffold my-agent --type toml
specify integration scaffold my-agent --type yaml
specify integration scaffold my-agent --type skills
```
Hyphenated keys are converted to Python-safe package names, for example
`my-agent` creates `src/specify_cli/integrations/my_agent/` and
`tests/integrations/test_integration_my_agent.py`.
The scaffold does not register the integration automatically. Review the
generated metadata, then add the import and `_register()` call in
`src/specify_cli/integrations/__init__.py`.
## 7. Run Lint / Basic Checks
CI enforces `ruff check src/` (see `.github/workflows/test.yml`), so run it locally before pushing:
```bash
uvx ruff check src/
```
You can also quickly sanity check importability:
```bash
python -c "import specify_cli; print('Import OK')"
```
## 7. Build a Wheel Locally (Optional)
## 8. Build a Wheel Locally (Optional)
Validate packaging before publishing:
@@ -117,7 +143,7 @@ ls dist/
Install the built artifact into a fresh throwaway environment if needed.
## 8. Using a Temporary Workspace
## 9. Using a Temporary Workspace
When testing `init --here` in a dirty directory, create a temp workspace:
@@ -128,7 +154,7 @@ python -m src.specify_cli init --here --integration claude --ignore-agent-tools
Or copy only the modified CLI portion if you want a lighter sandbox.
## 9. Debug Network / TLS Issues
## 10. Debug Network / TLS Issues
> **Deprecated:** The `--skip-tls` flag is a no-op and has no effect.
> It was previously used to bypass TLS validation during local testing.
@@ -137,7 +163,7 @@ Or copy only the modified CLI portion if you want a lighter sandbox.
>
> For example, set `SSL_CERT_FILE` or configure `HTTPS_PROXY` / `HTTP_PROXY`.
## 10. Rapid Edit Loop Summary
## 11. Rapid Edit Loop Summary
| Action | Command |
|--------|---------|
@@ -148,7 +174,7 @@ Or copy only the modified CLI portion if you want a lighter sandbox.
| Git branch uvx | `uvx --from git+URL@branch specify ...` |
| Build wheel | `uv build` |
## 11. Cleaning Up
## 12. Cleaning Up
Remove build artifacts / virtual env quickly:
@@ -156,7 +182,7 @@ Remove build artifacts / virtual env quickly:
rm -rf .venv dist build *.egg-info
```
## 12. Common Issues
## 13. Common Issues
| Symptom | Fix |
|---------|-----|
@@ -166,7 +192,7 @@ rm -rf .venv dist build *.egg-info
| Wrong script type downloaded | Pass `--script sh` or `--script ps` explicitly |
| TLS errors on corporate network | Configure your environment's certificate store or proxy. The `--skip-tls` flag is deprecated and has no effect. |
## 13. Next Steps
## 14. Next Steps
- Update docs and run through Quick Start using your modified CLI
- Open a PR when satisfied