Skip to content

Add cookiecutter template for scaffolding new QType projects#154

Merged
lou-k merged 4 commits intomainfrom
copilot/create-cookiecutter-template
Mar 6, 2026
Merged

Add cookiecutter template for scaffolding new QType projects#154
lou-k merged 4 commits intomainfrom
copilot/create-cookiecutter-template

Conversation

Copy link
Contributor

Copilot AI commented Mar 5, 2026

Description / purpose of change(s):

Adds a template/ directory at the repo root with a cookiecutter template for bootstrapping new QType projects with a working structure out of the box.

Template inputs

  • project_name — human-readable (e.g. "My Project")
  • __slug — auto-derived kebab-case (my-project)
  • __module — auto-derived snake_case Python package (my_project)

Generated project layout

my-project/
├── my_project/
│   ├── __init__.py
│   └── tools.py                  # Pydantic custom type + greet() + analyze_text()
├── my-project.qtype.yaml         # InvokeTool → PromptTemplate → LLMInference flow
├── my-project.tools.qtype.yaml   # Pre-generated; matches `qtype convert module` output
├── pyproject.toml                # qtype[interpreter,mcp] dependency (version 0.0.1)
├── Dockerfile                    # Builds & serves the app; secrets passed at runtime
├── README.md                     # validate / serve / run / convert commands
└── .vscode/launch.json           # "QType Serve (debug with reload)" + "QType Run (CLI)"

Also adds .github/workflows/test-template.yml — a CI workflow that runs on every PR to validate the template end-to-end.

Technical notes / screenshots / additional information (optional):

  • tools.qtype.yaml is pre-generated to match qtype convert module output exactly — users can regenerate it with qtype convert module <module>.tools -o <slug>.tools.qtype.yaml after modifying tools.py
  • pyproject.toml uses __slug (e.g. my-project) as the package name field to ensure it is always a valid PEP 508 package name; the human-readable project_name is used only in the description field
  • Dockerfile installs dependencies before copying source code so the heavy dependency layer is cached on rebuilds; secrets are injected at runtime via docker run --env-file
  • The example flow uses InvokeTool (greet by name) → PromptTemplate (build prompt) → LLMInference (OpenAI gpt-4o-mini), demonstrating the tool-chaining pattern
  • .vscode/launch.json "QType Run (CLI)" config uses a promptString input (${input:cliArgs}) so users can supply any arguments at debug time
  • Generated YAML passes qtype validate

CI workflow (test-template.yml) steps:

  1. Skips all steps if no files under template/ changed between the PR base and head
  2. Runs cookiecutter template/ --no-input project_name="PR Test"
  3. Runs uv sync then uv run qtype validate pr-test.qtype.yaml (with a dummy OPENAI_API_KEY)
  4. Re-generates the tools YAML via qtype convert module and fails if it differs from the committed version (drift detection)
  5. Builds the Docker image with docker build

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: lou-k <1943106+lou-k@users.noreply.github.com>
Copilot AI changed the title [WIP] Add cookiecutter template for qtype projects Add cookiecutter template for scaffolding new QType projects Mar 5, 2026
Copilot finished work on behalf of lou-k March 5, 2026 19:25
Copy link
Collaborator

@lou-k lou-k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few changes requested.

In addition please:

Add a github action that tests the template

This should run on each pr. It should stop if nothing in the template directory changed between the PR and head of the branch.
It should:

  • run cookiecutter on template with a hard coded name like "PR Test"
  • Cd into the directory
  • Run uv sync
  • Run uv run qtype validate .. to validate the yaml file (you'll need to set a dummy openai key)
  • run uv run qtype convert ....tools.py and save the output to {{cookiecutter...}}tools.qtype.yaml. Then ensure nothing has changed. if the tools file has changed, fail the pr
  • Run docker build to ensure the docker image builds correctly

"args": [
"run",
"{{ cookiecutter.__slug }}.qtype.yaml",
"--flow",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not be so specific here -- just set up to use inputs in vs code launch and tack them on the end of the args. That way people can put anything they want

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in commit 7dedc43. The "QType Run (CLI)" config now uses ${input:cliArgs} appended to the args, with a promptString input defined in the inputs section so users can type whatever they need at launch time.

COPY {{ cookiecutter.__module }}/ ./{{ cookiecutter.__module }}/

# Install the project and all dependencies
RUN uv pip install --system .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the dependencies are likely heavier than the source code, and the source code changes more often, I think this line should be swapped with line 10. That way the python dependencies get cached on builds

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swapped the order in commit 7dedc43pyproject.toml is now copied and dependencies installed before the source module is added, so the heavy dep layer gets cached on subsequent builds when only source changes.


[project]
name = "{{ cookiecutter.project_name }}"
version = "0.1.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 0.0.1 for initial please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to 0.0.1 in commit 7dedc43.

Copy link
Collaborator

@lou-k lou-k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few changes requested.

In addition please:

Add a github action that tests the template

This should run on each pr. It should stop if nothing in the template directory changed between the PR and head of the branch.
It should:

  • run cookiecutter on template with a hard coded name like "PR Test"
  • Cd into the directory
  • Run uv sync
  • Run uv run qtype validate .. to validate the yaml file (you'll need to set a dummy openai key)
  • run uv run qtype convert ....tools.py and save the output to {{cookiecutter...}}tools.qtype.yaml. Then ensure nothing has changed. if the tools file has changed, fail the pr
  • Run docker build to ensure the docker image builds correctly

…, and CI workflow

Co-authored-by: lou-k <1943106+lou-k@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 5, 2026

A few changes requested.

In addition please:
...

Added .github/workflows/test-template.yml in commit 7dedc43. The workflow:

  • Skips all steps if no files under template/ changed between the PR base and head
  • Runs cookiecutter template/ --no-input project_name="PR Test"
  • Runs uv sync then uv run qtype validate pr-test.qtype.yaml (with OPENAI_API_KEY=DUMMY_KEY_FOR_VALIDATION)
  • Re-generates the tools YAML with qtype convert module pr_test.tools and diffs against the committed file — fails if drift is detected
  • Builds the Docker image with docker build

Copilot finished work on behalf of lou-k March 5, 2026 19:45
Copy link
Collaborator

@lou-k lou-k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your test fails with:

Run uv sync
error: Failed to parse: `pyproject.toml`
  Caused by: TOML parse error at line 6, column 8
  |
6 | name = "PR Test"
  |        ^^^^^^^^^
Not a valid package or extra name: "PR Test". Names must start and end with a letter or digit and may only contain -, _, ., and alphanumeric characters.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
2587 1970 76% 70% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 4d1d6af by action🐍

Co-authored-by: lou-k <1943106+lou-k@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 5, 2026

your test fails with:

Run uv sync...

Fixed in commit 4d1d6af — the name field in pyproject.toml now uses {{ cookiecutter.__slug }} (e.g. pr-test) instead of {{ cookiecutter.project_name }}, which is always a valid PEP 508 package name. The human-readable name is still used in the description field.

Copilot finished work on behalf of lou-k March 5, 2026 19:49
@lou-k lou-k marked this pull request as ready for review March 6, 2026 01:45
@lou-k lou-k requested a review from loukratz-bv as a code owner March 6, 2026 01:45
@lou-k lou-k merged commit 2cd4efa into main Mar 6, 2026
5 checks passed
@lou-k lou-k deleted the copilot/create-cookiecutter-template branch March 6, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants