From 30a31b8098fac6a22305c21a0c2135f9b3afad14 Mon Sep 17 00:00:00 2001 From: Kevin Mills Date: Sun, 30 Nov 2025 08:18:10 -0600 Subject: [PATCH 1/2] Add GitHub Copilot instructions reference to CONTRIBUTING.md --- .github/copilot-instructions.md | 134 ++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 4 + 2 files changed, 138 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000000..fdb637ecb1 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,134 @@ +# Cookiecutter Django - AI Coding Agent Instructions + +## Project Architecture + +This is a **Cookiecutter template** for Django projects, not a standard Django application. The actual project structure exists in `{{cookiecutter.project_slug}}/` which contains Jinja2 template syntax (`{{ }}`, `{% %}`) that gets rendered when users run `cookiecutter` to generate a new Django project. + +### Key Directories +- `{{cookiecutter.project_slug}}/` - Template for generated Django projects with Jinja2 variables +- `hooks/` - Python scripts that run before/after project generation (`pre_gen_project.py`, `post_gen_project.py`) +- `tests/` - Template generation tests using pytest-cookies +- `docs/` - Project documentation (separate from generated project docs) +- `scripts/` - Maintenance utilities (version bumps, changelog updates) + +### Template Rendering Flow +1. User runs `cookiecutter` with configuration choices in `cookiecutter.json` +2. `hooks/pre_gen_project.py` validates choices (e.g., project_slug format, cloud provider compatibility) +3. Jinja2 renders all `{{cookiecutter.*}}` variables and `{% if %}` conditionals +4. `hooks/post_gen_project.py` removes unused files based on choices (Docker, Celery, frontend pipeline, etc.) + +## Critical Development Workflows + +### Running Template Tests +```bash +# Test template generation (fast) +uv run tox run -e py + +# Test specific scenario +uv run tox run -e py -- -k test_default_configuration + +# Full integration tests (slow) +tests/test_bare.sh use_celery=y # Without Docker +tests/test_docker.sh use_docker=y # With Docker +``` + +### Testing Generated Projects +The template produces different outputs based on `cookiecutter.json` choices. Test scripts generate projects, install dependencies, and run their test suites: +- `test_bare.sh` - Bare metal setup (no Docker) +- `test_docker.sh` - Docker-based setup with compose files + +### Docker Commands for Generated Projects +Generated projects use Docker Compose with different configs: +```bash +# Local development +docker compose -f docker-compose.local.yml up +docker compose -f docker-compose.local.yml run --rm django pytest +docker compose -f docker-compose.local.yml run django uv lock # Generate lockfile + +# Production setup +docker compose -f docker-compose.production.yml build +docker compose -f docker-compose.production.yml up -d +``` + +Generated projects may include a `justfile` with shortcuts: +```bash +just up # Start containers +just manage migrate # Run Django management commands +just logs django # View service logs +``` + +## Project-Specific Conventions + +### Jinja2 Template Syntax +All files in `{{cookiecutter.project_slug}}/` contain template variables: +- `{{ cookiecutter.project_slug }}` - User's project name +- `{% if cookiecutter.use_docker == 'y' %}...{% endif %}` - Conditional sections +- `{%- if ... -%}` - Whitespace control (important for Python indentation) + +**Never edit template files without preserving Jinja2 syntax.** Example from `base.py`: +```python +TIME_ZONE = "{{ cookiecutter.timezone }}" +{% if cookiecutter.use_docker == "y" -%} +DATABASES = {"default": env.db("DATABASE_URL")} +{%- else %} +DATABASES = {"default": env.db("DATABASE_URL", default="postgres:///{{cookiecutter.project_slug}}")} +{%- endif %} +``` + +### Hook System +`hooks/post_gen_project.py` contains cleanup logic that removes files based on user choices: +- `remove_docker_files()` if `use_docker == 'n'` +- `remove_celery_files()` if `use_celery == 'n'` +- `handle_js_runner()` configures Gulp/Webpack or removes frontend tooling + +When adding new optional features, update both the template files AND the corresponding removal function in hooks. + +### Configuration Matrix Testing +`tests/test_cookiecutter_generation.py` defines `SUPPORTED_COMBINATIONS` - a matrix of valid configuration options. Each combination is tested to ensure: +- Valid project generation (no Jinja2 errors) +- No unrendered template variables remain (regex check) +- Basic linting passes (ruff) + +Add new combinations when introducing features with interdependencies (e.g., `cloud_provider` + `mail_service`). + +## Integration Points + +### Dependency Management +Generated projects use **uv** for Python dependencies with lockfiles: +- Template root: `pyproject.toml` defines template dev dependencies (cookiecutter, pytest-cookies, ruff) +- Generated projects: `{{cookiecutter.project_slug}}/pyproject.toml` defines Django app dependencies +- Docker builds run `uv sync` to install from lockfiles + +### CI/CD Configuration +Templates include conditional CI configs: +- `{% if cookiecutter.ci_tool == 'Github' %}` generates `.github/workflows/ci.yml` +- `{% if cookiecutter.ci_tool == 'Gitlab' %}` generates `.gitlab-ci.yml` + +CI tests both linting and project tests with environment-specific commands (Docker vs bare metal). + +### Settings Architecture +Generated projects use django-environ with three settings modules: +- `config/settings/base.py` - Shared settings with Jinja2 variables +- `config/settings/local.py` - Development settings +- `config/settings/production.py` - Production with cloud provider integrations + +Environment variables read from `.envs/.local/` or `.envs/.production/` directories in Docker setups. + +## Common Patterns + +### Adding Optional Features +1. Add choice to `cookiecutter.json` with default +2. Add conditional blocks in template files: `{% if cookiecutter.new_feature == 'y' %}` +3. Create removal function in `hooks/post_gen_project.py` +4. Update test matrix in `tests/test_cookiecutter_generation.py` +5. Document in `docs/1-getting-started/project-generation-options.rst` + +### Version Bumps +Use maintenance scripts instead of manual edits: +- `scripts/node_version.py` - Update Node.js versions across Dockerfiles, package.json, CI +- `scripts/ruff_version.py` - Update Ruff versions in pyproject.toml files +- `scripts/update_changelog.py` - Generate changelog entries + +### Pre-commit Configuration +Both template and generated projects use pre-commit with ruff for linting. Auto-fixable style issues are skipped in CI via `AUTOFIXABLE_STYLES` env var since they're tedious to fix in Jinja2 templates. + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44bfd69ba4..6a7e03debc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,3 +67,7 @@ $ tests/test_bare.sh use_celery=y Once you're happy with your changes and they look ok locally, push and send [a pull request][submit-a-pr] to the main repo, which will trigger the tests on GitHub actions. If they fail, try to fix them. A maintainer should take a look at your change and give you feedback or merge it. [submit-a-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request + +## GitHub Copilot Instructions + +If you use GitHub Copilot, note that this repository includes AI coding agent instructions in `.github/copilot-instructions.md`. These provide Copilot with context about the Cookiecutter template architecture, testing workflows, and development conventions to give more accurate suggestions when working on this project. From d7809adaf1fbb60bea0dccfabc5c1af3814b8048 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 14:25:01 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/copilot-instructions.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index fdb637ecb1..58be411f44 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -5,6 +5,7 @@ This is a **Cookiecutter template** for Django projects, not a standard Django application. The actual project structure exists in `{{cookiecutter.project_slug}}/` which contains Jinja2 template syntax (`{{ }}`, `{% %}`) that gets rendered when users run `cookiecutter` to generate a new Django project. ### Key Directories + - `{{cookiecutter.project_slug}}/` - Template for generated Django projects with Jinja2 variables - `hooks/` - Python scripts that run before/after project generation (`pre_gen_project.py`, `post_gen_project.py`) - `tests/` - Template generation tests using pytest-cookies @@ -12,6 +13,7 @@ This is a **Cookiecutter template** for Django projects, not a standard Django a - `scripts/` - Maintenance utilities (version bumps, changelog updates) ### Template Rendering Flow + 1. User runs `cookiecutter` with configuration choices in `cookiecutter.json` 2. `hooks/pre_gen_project.py` validates choices (e.g., project_slug format, cloud provider compatibility) 3. Jinja2 renders all `{{cookiecutter.*}}` variables and `{% if %}` conditionals @@ -20,6 +22,7 @@ This is a **Cookiecutter template** for Django projects, not a standard Django a ## Critical Development Workflows ### Running Template Tests + ```bash # Test template generation (fast) uv run tox run -e py @@ -33,12 +36,16 @@ tests/test_docker.sh use_docker=y # With Docker ``` ### Testing Generated Projects + The template produces different outputs based on `cookiecutter.json` choices. Test scripts generate projects, install dependencies, and run their test suites: + - `test_bare.sh` - Bare metal setup (no Docker) - `test_docker.sh` - Docker-based setup with compose files ### Docker Commands for Generated Projects + Generated projects use Docker Compose with different configs: + ```bash # Local development docker compose -f docker-compose.local.yml up @@ -51,6 +58,7 @@ docker compose -f docker-compose.production.yml up -d ``` Generated projects may include a `justfile` with shortcuts: + ```bash just up # Start containers just manage migrate # Run Django management commands @@ -60,12 +68,15 @@ just logs django # View service logs ## Project-Specific Conventions ### Jinja2 Template Syntax + All files in `{{cookiecutter.project_slug}}/` contain template variables: + - `{{ cookiecutter.project_slug }}` - User's project name - `{% if cookiecutter.use_docker == 'y' %}...{% endif %}` - Conditional sections - `{%- if ... -%}` - Whitespace control (important for Python indentation) **Never edit template files without preserving Jinja2 syntax.** Example from `base.py`: + ```python TIME_ZONE = "{{ cookiecutter.timezone }}" {% if cookiecutter.use_docker == "y" -%} @@ -76,7 +87,9 @@ DATABASES = {"default": env.db("DATABASE_URL", default="postgres:///{{cookiecutt ``` ### Hook System + `hooks/post_gen_project.py` contains cleanup logic that removes files based on user choices: + - `remove_docker_files()` if `use_docker == 'n'` - `remove_celery_files()` if `use_celery == 'n'` - `handle_js_runner()` configures Gulp/Webpack or removes frontend tooling @@ -84,7 +97,9 @@ DATABASES = {"default": env.db("DATABASE_URL", default="postgres:///{{cookiecutt When adding new optional features, update both the template files AND the corresponding removal function in hooks. ### Configuration Matrix Testing + `tests/test_cookiecutter_generation.py` defines `SUPPORTED_COMBINATIONS` - a matrix of valid configuration options. Each combination is tested to ensure: + - Valid project generation (no Jinja2 errors) - No unrendered template variables remain (regex check) - Basic linting passes (ruff) @@ -94,20 +109,26 @@ Add new combinations when introducing features with interdependencies (e.g., `cl ## Integration Points ### Dependency Management + Generated projects use **uv** for Python dependencies with lockfiles: + - Template root: `pyproject.toml` defines template dev dependencies (cookiecutter, pytest-cookies, ruff) - Generated projects: `{{cookiecutter.project_slug}}/pyproject.toml` defines Django app dependencies - Docker builds run `uv sync` to install from lockfiles ### CI/CD Configuration + Templates include conditional CI configs: + - `{% if cookiecutter.ci_tool == 'Github' %}` generates `.github/workflows/ci.yml` - `{% if cookiecutter.ci_tool == 'Gitlab' %}` generates `.gitlab-ci.yml` CI tests both linting and project tests with environment-specific commands (Docker vs bare metal). ### Settings Architecture + Generated projects use django-environ with three settings modules: + - `config/settings/base.py` - Shared settings with Jinja2 variables - `config/settings/local.py` - Development settings - `config/settings/production.py` - Production with cloud provider integrations @@ -117,6 +138,7 @@ Environment variables read from `.envs/.local/` or `.envs/.production/` director ## Common Patterns ### Adding Optional Features + 1. Add choice to `cookiecutter.json` with default 2. Add conditional blocks in template files: `{% if cookiecutter.new_feature == 'y' %}` 3. Create removal function in `hooks/post_gen_project.py` @@ -124,11 +146,13 @@ Environment variables read from `.envs/.local/` or `.envs/.production/` director 5. Document in `docs/1-getting-started/project-generation-options.rst` ### Version Bumps + Use maintenance scripts instead of manual edits: + - `scripts/node_version.py` - Update Node.js versions across Dockerfiles, package.json, CI - `scripts/ruff_version.py` - Update Ruff versions in pyproject.toml files - `scripts/update_changelog.py` - Generate changelog entries ### Pre-commit Configuration -Both template and generated projects use pre-commit with ruff for linting. Auto-fixable style issues are skipped in CI via `AUTOFIXABLE_STYLES` env var since they're tedious to fix in Jinja2 templates. +Both template and generated projects use pre-commit with ruff for linting. Auto-fixable style issues are skipped in CI via `AUTOFIXABLE_STYLES` env var since they're tedious to fix in Jinja2 templates.