Repository navigation
chore: add interface-first plugin cookiecutter template - #2862
Closed
sfc-gh-olorek wants to merge 3 commits into
Closed
sfc-gh-olorek wants to merge 3 commits into
sfc-gh-olorek wants to merge 3 commits into
Conversation
sfc-gh-olorek
force-pushed
the
feature/plugin-notebook-migration
branch
from
April 7, 2026 11:04
97d36de to
4f2d603
Compare
sfc-gh-olorek
force-pushed
the
feature/plugin-template-and-docs
branch
from
April 7, 2026 11:04
5f7c143 to
e2d7a3a
Compare
sfc-gh-olorek
marked this pull request as draft
April 15, 2026 09:46
sfc-gh-olorek
force-pushed
the
feature/plugin-template-and-docs
branch
from
June 23, 2026 10:11
e2d7a3a to
da3eb5a
Compare
sfc-gh-olorek
changed the base branch from
feature/plugin-notebook-migration
to
main
June 23, 2026 10:11
sfc-gh-olorek
force-pushed
the
feature/plugin-template-and-docs
branch
from
June 23, 2026 10:58
da3eb5a to
9023cc2
Compare
3 of 9 tasks
sfc-gh-olorek
marked this pull request as ready for review
June 23, 2026 11:04
sfc-gh-olorek
force-pushed
the
feature/plugin-template-and-docs
branch
from
June 23, 2026 11:16
9023cc2 to
04a544d
Compare
Scaffold under plugin-template/ for creating interface-first Snowflake CLI plugins. Supports both `group` (multiple subcommands) and `single` command plugins. Generated projects follow the two-phase contribution workflow: interface.py (Phase 1, reviewable command surface + handler ABC) and handler.py (Phase 2, implementation), wired in plugin_spec.py via build_command_spec. Generated files carry the standard Apache license header, so a plugin contributed back as a built-in passes the repo's license check unchanged. The template sources contain Jinja placeholders that are not valid Python/TOML, so they are kept out of the repo's own tooling: - pre-commit excludes plugin-template/ globally (black/ruff/check-ast cannot parse the Jinja sources). - plugin-template/conftest.py keeps the repo-wide pytest runs that collect from the project root (pytest -m performance / -m e2e) from importing the Jinja template tests.
sfc-gh-olorek
force-pushed
the
feature/plugin-template-and-docs
branch
from
June 23, 2026 12:13
04a544d to
c0ca0da
Compare
Collapse the repeated class-name filter chain
`{{ cookiecutter.plugin_module | replace('_', ' ') | title | replace(' ', '') }}`
into a single derived cookiecutter variable `plugin_class_name`, replacing
all 12 occurrences across handler.py, interface.py, plugin_spec.py, and
test_interface.py with `{{ cookiecutter.plugin_class_name }}`.
Generated output is byte-identical before and after for both command_type
variants (group and single).
- Drop the unused `REQUIRED` import. `ParamDef.default` already defaults to
`REQUIRED`, so the example params are required without it -- the import was
dead in every generated project.
- Render `cli_parent_path` as a proper tuple by splitting on whitespace, so a
single-segment parent (e.g. `cortex`) yields a valid 1-tuple `("cortex",)`
instead of a `NameError` / bare string. Empty stays `()` and multi-segment
yields `("app", "bundle",)`.
Verified by rendering empty / single / multi parent paths across both
command_type variants; all generated .py compile.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pre-review checklist
RELEASE-NOTES.md(see when and how).Template/tooling PR:
plugin-template/is excluded from repo CI (Jinja placeholders, not valid Python/TOML), so repo unit/integration tests and manual platform testing don't apply. Instead the generated project was validated end-to-end (see below).skip-release-notesapplied.Changes description
Split from the original scope of this PR; the contributor guide is now in #3132.
Adds a cookiecutter template under
plugin-template/for scaffoldinginterface-first Snowflake CLI plugins:
group(multiple subcommands) andsinglecommand plugins.interface.py(Phase 1 reviewable command surface + handlerABC),
handler.py(Phase 2 implementation),plugin_spec.py(wiring viabuild_command_spec), and a contract test using thesnowflake.cli.api.plugins.command.testinghelpers.scripts/LICENSE.txt), so a plugin contributed back into snowflake-cli as abuilt-in passes the repo's
insert-licensecheck unchanged.Because the template sources contain Jinja placeholders that are not valid
Python/TOML, they are kept out of the repo's own tooling:
plugin-template/globally (black/ruff/check-ast cannotparse the Jinja sources).
plugin-template/conftest.pykeeps the repo-wide pytest runs that collect fromthe project root (
pytest -m performance/-m e2e) from importing the Jinjatemplate tests.
Validated against current
main:cookiecutter plugin-template/renders boththe
groupandsinglevariants, the generated project builds and installs(
pip install), and its contract tests pass (4 passed).Updated from the original draft to match current
main:build_command_specis now imported from...command.bridge(the package__init__no longer re-exports it); the old import would have failed at runtime.pyproject.tomldeclares[tool.hatch.build.targets.wheel] packagesso thegenerated
src/-layout project actually builds.Pairs with the guide in #3132.