diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml new file mode 100644 index 0000000..b8aa435 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -0,0 +1,61 @@ +name: '🐛 Bug Report' +description: Report a bug with the template or generated projects +labels: [bug] +title: '[Bug] ' + +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please provide as much detail as possible. + + - type: dropdown + id: issue_scope + attributes: + label: Is this a template issue or generated project issue? + options: + - Template/Cookiecutter + - Generated Project + validations: + required: true + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of the bug + placeholder: | + What went wrong? Please be as specific as possible. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + description: How can we reproduce this issue? + placeholder: | + Either a minimum reproducible example or detailed steps. + validations: + required: true + + - type: textarea + id: environment + attributes: + label: Environment + description: Please provide relevant environment details + value: | + - OS: + - Python version: + - Cookiecutter version (if template issue): + - Project configuration (rust extension enabled?): + validations: + required: true + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other information that might be helpful + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/02_feature_request.yml b/.github/ISSUE_TEMPLATE/02_feature_request.yml new file mode 100644 index 0000000..7fe33d5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02_feature_request.yml @@ -0,0 +1,49 @@ +name: '✨ Feature Request' +description: Suggest new features or improvements +labels: [enhancement] +title: '[Feature] ' + +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please help us understand your idea. + + - type: dropdown + id: feature_scope + attributes: + label: Is this for the template or generated projects? + options: + - Template (new options, generation features) + - Generated Project (tooling, structure) + - Both + validations: + required: true + + - type: textarea + id: summary + attributes: + label: Feature Summary + description: What feature would you like to see? + placeholder: | + A brief description of the feature you're requesting... + validations: + required: true + + - type: textarea + id: example + attributes: + label: Example + description: How would this look to the end user? + placeholder: | + Show an example of how this would work or what the user would see/do... + validations: + required: true + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Any other relevant information about this feature request + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/03_documentation.yml b/.github/ISSUE_TEMPLATE/03_documentation.yml new file mode 100644 index 0000000..1440b8e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/03_documentation.yml @@ -0,0 +1,52 @@ +name: '📖 Documentation Issue' +description: Report documentation issues or suggest improvements +labels: [documentation] +title: '[Docs] ' + +body: + - type: markdown + attributes: + value: | + Help us improve our documentation! + + - type: dropdown + id: doc_type + attributes: + label: What type of documentation issue is this? + options: + - Missing documentation + - Incorrect/outdated information + - Unclear explanation + - Broken links + - Other improvement + validations: + required: true + + - type: textarea + id: description + attributes: + label: Description + description: Describe the documentation issue + placeholder: | + What's wrong with the documentation? What needs to be improved? + validations: + required: true + + - type: input + id: link + attributes: + label: Documentation Link + description: Link to the problematic documentation (if applicable) + placeholder: https://... + validations: + required: false + + - type: textarea + id: suggestion + attributes: + label: Suggested Improvement + description: How would you improve this documentation? + placeholder: | + What changes would make this clearer or more helpful? + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..1702c37 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: ❓ Questions & Support + url: https://github.com/56kyle/cookiecutter-robust-python/discussions + about: Ask questions and get help using cookiecutter-robust-python + - name: 💬 General Discussion + url: https://github.com/56kyle/cookiecutter-robust-python/discussions + about: Discuss ideas, best practices, and share your projects diff --git a/README.md b/README.md index 3940b08..8236d5d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# cookiecutter-robust-python +# Cookiecutter Robust Python A Python project template robust enough to follow up [cookiecutter-hypermodern-python] @@ -8,37 +8,44 @@ A Python project template robust enough to follow up [cookiecutter-hypermodern-p --- -## Usage/Installation +## Quick Start -The only prerequisite for using the template is to [install uv]. +### Prerequisites +The only requirement is [uv]. -From there just cd into the directory you want to create the project in and run: -```terminaloutput +### Create Your Project +Navigate to where you want to create your project and run: + +```bash uvx cruft create https://github.com/56kyle/cookiecutter-robust-python.git ``` -Which will prompt you for a few inputs before generating the project. -```terminaloutput -> [1/15] project_name (robust-python): my-repo-name -> ... + +This will prompt you for a few inputs to customize your project: +``` +[1/15] project_name (robust-python): my-awesome-project +[2/15] package_name (my_awesome_project): +[3/15] friendly_name (My Awesome Project): +... ``` -#### Local Setup +### Project Setup + +After generating your project, set it up for development: -Once you have generated your project, and preferably before opening the IDE, the normal workflow to setup everything would go as follows: -```terminaloutput -cd my-repo-name +```bash +cd my-awesome-project -# Pins the uv python version, generates/syncs a venv, etc. +# Set up virtual environment and install dependencies uvx nox -s setup-venv -# Sets up a git repo w/ a main/develop branch along with an initial commit of everything just generated. +# Initialize git repository with main/develop branches uvx nox -s setup-git -# Sets up the remote reference and ensures main/develop are pushed/synced. Requires that the remote exists (should be empty). -uvx nos -s setup-remote +# Set up remote repository (requires empty remote repo to exist) +uvx nox -s setup-remote ``` -You can also run `uvx nox -t env` for the same effect. +**Quick setup:** Run `uvx nox -t env` to execute all environment setup tasks at once. ## Most Notable Features @@ -46,9 +53,9 @@ You can also run `uvx nox -t env` for the same effect. - Built for supporting most OS's (windows, linux, macos) and all currently supported [python] versions - Platform agnostic CI/CD ([github], [gitlab], [bitbucket]) - CI/CD that parities local [nox] sessions for all [python] -- [maturin] support that can be at any time during the project's lifecycle +- [maturin] support that can be added at any time during the project's lifecycle - Designed to be a maintainable template over time through the use of automated demos and integration tests -- ... and much more! +- Rich documentation explaining tooling decisions and rationale For a general overview of where we are at with this template, please see the [roadmap](#roadmap) section. @@ -127,7 +134,7 @@ to Python's ecosystem overall. That being said, it's generally good practice to avoid the complexity of this dual language system unless you actually need the performance bump for your use case. However knowing ahead of time if performance will be an issue is rather tricky, and a much easier route is to just prepare as though you _might_ swap to it some day. -The [Robust Python Cookiecutter] includes a `include_rust_extensions` flag that not only toggles [maturin] vs a traditional Python package, +The [Robust Python Cookiecutter] includes an `add_rust_extension` flag that not only toggles [maturin] vs a traditional Python package, but that can be used in combination with [cruft] to swap to [maturin] at any time with just about no risk to CI/CD / etc. Additionally, the [Robust Python Cookiecutter] is designed with both normal and [monorepos] in mind. So whether you need to just add @@ -171,18 +178,25 @@ However, Open Source work is draining, and is especially so for a project templa I can guarantee that if the [Robust Python Cookiecutter] ever sees any number of users, I will immediately transfer it to an organization to enable at least a handful of trusted individuals to ensure the project is taken care of. +[bitbucket]: https://bitbucket.org [bitbucket-pipelines]: https://support.atlassian.com/bitbucket-cloud/docs/write-a-pipe-for-bitbucket-pipelines/ [cookiecutter]: https://cookiecutter.readthedocs.io/en/stable/ [cookiecutter-hypermodern-python]: https://github.com/cjolowicz/cookiecutter-hypermodern-python [cookiecutter-robust-python]: https://github.com/56kyle/cookiecutter-robust-python [cruft]: https://cruft.github.io/cruft/ +[github]: https://github.com [github-actions]: https://docs.github.com/en/actions +[gitlab]: https://gitlab.com [hypermodern python cookiecutter]: https://github.com/cjolowicz/cookiecutter-hypermodern-python [just]: https://github.com/casey/just?tab=readme-ov-fil [maturin]: https://github.com/PyO3/maturin +[monorepos]: https://en.wikipedia.org/wiki/Monorepo +[my personal fork]: https://github.com/56kyle/cookiecutter-hypermodern-python +[nox]: https://nox.thea.codes/ [noxfile]: https://github.com/56kyle/cookiecutter-robust-python/blob/main/%7B%7Bcookiecutter.project_name%7D%7D/noxfile.py [poetry]: https://python-poetry.org/docs/ [polars]: https://github.com/pola-rs/polars +[python]: https://www.python.org/ [robust python cookiecutter]: https://github.com/56kyle/cookiecutter-robust-python [ruff]: https://docs.astral.sh/ruff/ [rust]: https://www.rust-lang.org/learn diff --git a/docs/getting-started-template-contributing.md b/docs/getting-started-template-contributing.md index fa24464..433ba41 100644 --- a/docs/getting-started-template-contributing.md +++ b/docs/getting-started-template-contributing.md @@ -10,32 +10,29 @@ To contribute to the template, you will need: 2. **Python 3.9+**: We recommend using a supported Python version. 3. **uv**: Our chosen dependency manager (see [Dependency Management (02)](topics/02_dependency-management.md)). Install `uv` globally or in a base environment following the official {uv-install}`uv installation guide<>`. 4. **Docker or Podman**: Required for testing the containerization aspects of the generated template (see [Container Build (11)](topics/11_container-build.md), [Dev Containers (17)](topics/17_dev-containers.md)). -5. **Task Automation Tools**: The template itself uses a `noxfile.py` to manage its own development and documentation build workflows. Install `nox`: - ```bash - uv add nox # Ensure you have uv first - ``` +5. **Task Automation Tools**: The template uses `noxfile.py` for development workflows. We use `uvx` to run `nox` so that it automatically installs if needed. ## Setting up Your Development Environment 1. **Clone the Template Repository:** ```bash - git clone https://github.com/56kyle/cookiecutter-robust-python.git # **UPDATE WITH TEMPLATE REPO URL** + git clone https://github.com/56kyle/cookiecutter-robust-python.git cd cookiecutter-robust-python ``` 2. **Install Template Development Dependencies:** - The template needs dependencies to run its tests, build its documentation, and check its own code. + Install all dependency groups needed for template development: ```bash - uv sync # This installs deps from the template's pyproject.toml into a .venv + uv sync --all-groups ``` 3. **Install Pre-commit Hooks for the Template:** - To ensure your contributions meet the template's own code quality standards, install the pre-commit hooks for _this template repository_: + Set up pre-commit hooks to maintain code quality: ```bash - uvx nox -s pre-commit -- install # Installs hooks based on the template's .pre-commit-config.yaml + uvx nox -s pre-commit -- install ``` 4. **Set up Dev Container (Optional):** @@ -52,10 +49,10 @@ The template's own `noxfile.py` defines tasks for maintaining the template itsel ``` 2. **Run Core Template Checks:** - This includes linting the template's own Python files (like `noxfile.py`), checking formatting, etc. + Lint and format the template's own Python files: ```bash - uvx nox -s check # Runs the template's internal checks + uvx nox -s lint ``` 3. **Build Template Documentation:** @@ -66,15 +63,17 @@ The template's own `noxfile.py` defines tasks for maintaining the template itsel ``` 4. **Run Template Tests:** - (Assuming the template itself has tests, e.g., testing cookiecutter rendering or noxfile sessions). + Test the template's generation functionality: ```bash - uvx nox -s test # Runs tests for the template itself + uvx nox -s test ``` -5. **Run All Checks and Tests:** +5. **Generate Demo Project:** + Create a demo project to test template functionality: + ```bash - uvx nox # Runs the default sessions defined in noxfile.py (often check and test) + uvx nox -s generate-demo ``` ## Updating Template Version and Releasing @@ -82,10 +81,9 @@ The template's own `noxfile.py` defines tasks for maintaining the template itsel This template uses Calendar Versioning (YYYY.MM.DD) for its own releases. 1. **Ensure Your Branch is Up-to-date:** Pull the latest changes from the main branch. -2. **Run Commitizen Bump for the Template:** (Assuming Commitizen is used for template versioning). Use `uvx` to run Commitizen against the template: +2. **Release the Template:** ```bash - uvx cz bump --changelog # Follow prompts, generates tag/changelog entry - # Alternatively, specify increment e.g., uvx cz bump --changelog --increment major_version_zero + uvx nox -s release-template # Uses Commitizen to bump version and create tags ``` This will update the version string(s) (e.g., in `__version__.py` or `conf.py`), create a Git tag, and potentially update the changelog. 3. **Push Changes and Tags:** Push the commits and the newly created tag to the template repository: diff --git a/docs/our-chosen-toolchain.md b/docs/our-chosen-toolchain.md index 787e98d..c662115 100644 --- a/docs/our-chosen-toolchain.md +++ b/docs/our-chosen-toolchain.md @@ -117,7 +117,7 @@ The true power of this template lies in how these chosen tools work together coh 1. **Configuration:** Defined primarily in `pyproject.toml` and separate tool config files ([01](topics/01_project-structure.md)). 2. **Dependency/Environment Management:** Handled efficiently by {uv}`uv<>`, creating standard virtual environments and managing packages based on `pyproject.toml` and `uv.lock` ([02](topics/02_dependency-management.md)). 3. **Task Automation:** Orchestrated by {nox}`Nox<>`, calling commands from other tools via `uv run` (or `uvx`), providing the single interface for developers and CI/CD to run workflows ([12](topics/12_task-automation.md)). -4. **Code Quality & Testing:** Ensured by {ruff}`Ruff<>` (formatting/linting), {pyright}`Pyright<>` (typing), {pip-audit}`pip-audit<>` (dep security), and {bandit-bandit}`Bandit<>` (code security), along with {pytest-pytest-cov}`pytest<>`/{coveragepy-coverage}`coverage.py<>` for testing. These tools are installed via {uv}`uv<>` and executed via Task Automation ([03](topics/03_code-formatting.md)-[08](topics/08_security-checks.md), orchestrated by [12](topics/12_task-automation.md)). +4. **Code Quality & Testing:** Ensured by {ruff}`Ruff<>` (formatting/linting), {pyright}`Pyright<>` (typing), {pip-audit}`pip-audit<>` (dep security), and {bandit-bandit}`Bandit<>` (code security), along with {pytest-pytest-cov}`pytest<>`/{coveragepy}`coverage.py<>` for testing. These tools are installed via {uv}`uv<>` and executed via Task Automation ([03](topics/03_code-formatting.md)-[08](topics/08_security-checks.md), orchestrated by [12](topics/12_task-automation.md)). 5. **Packaging & Distribution:** Artifacts created via {uv}`uv<>` build using selected backends, and published via {uv}`uv<>` publish, orchestrated by Task Automation ([09](topics/09_packaging-build.md)-[10](topics/10_packaging-publish.md)). 6. **Containerization:** Defined by `Dockerfile`, built by {docker}`Docker<>`/{podman}`Podman<>` (often via `uv` installing deps inside), orchestrated by Task Automation. Local multi-container setups managed by {docker}`Docker Compose<>` ([11](topics/11_container-build.md), [15](topics/15_compose-local.md)). 7. **Automated Workflows:** Triggered by CI/CD platforms (configured to call Task Automation commands), handling matrices, secrets, and reporting ([13](topics/13_ci-orchestration.md)-[14](topics/14_cd-orchestration.md)). diff --git a/docs/philosophy.md b/docs/philosophy.md index 8abd7a3..749a1d5 100644 --- a/docs/philosophy.md +++ b/docs/philosophy.md @@ -40,6 +40,19 @@ These principles form the basis for the evaluation criteria and justifications d ## Solved Issues -The [Robust Python Cookiecutter] also exists to solve a few key issues that were omnipresent in [cookiecutter-hypermodern-python]. +The Robust Python Cookiecutter addresses several key challenges that existed in the original cookiecutter-hypermodern-python: -### +### Template Update Propagation +One major issue with traditional cookiecutter workflows is the difficulty of propagating template updates to existing projects. The Robust Python Cookiecutter includes built-in support for Cruft, enabling projects to receive template updates through manageable pull requests rather than manual recreation. + +### Project Domain Expansion +While pure Python projects are common, many modern Python packages benefit from optional Rust extensions for performance-critical components. The template includes configurable Rust support via Maturin, allowing projects to start as pure Python and add Rust components when needed without architectural disruption. + +### Documentation of Decisions +Rather than just providing tooling, this template documents the reasoning behind each tool choice. This enables maintainers to evaluate whether decisions remain valid as the ecosystem evolves, supporting long-term template maintenance. + +### CI/CD Vendor Independence +The template is designed to work across GitHub Actions, GitLab CI, and Bitbucket Pipelines by centralizing logic in Nox sessions rather than platform-specific workflow syntax. This ensures consistency and portability. + +### Long-term Maintenance Strategy +The template includes comprehensive testing infrastructure with automated demo projects and integration tests, helping ensure changes don't break the generation process and providing confidence in template evolution. diff --git a/docs/quickstart.md b/docs/quickstart.md index 8d7d1b2..aedfc41 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -1,8 +1,8 @@ # Quickstart -This guide provides the absolute minimum steps to get up and running with a project generated by `cookiecutter-robust-python`. It's for developers who want to start coding and use the core workflows right away. +This guide covers the essential steps to get up and running with a project generated by `cookiecutter-robust-python`. Perfect for developers who want to start coding with the core workflows immediately. -For detailed explanations of the tools and the philosophy, see the full documentation. +For detailed tool explanations and project philosophy, see the full documentation. --- @@ -23,10 +23,10 @@ Navigate to the directory you want to create your new project in. cd ~/path/to/my/repos ``` -Generate your project from the template using the given command: +Generate your project from the template: ```bash -uvx cookiecutter gh:56kyle/cookiecutter-robust-python +uvx cruft create https://github.com/56kyle/cookiecutter-robust-python.git ``` Follow the prompts to customize your project. @@ -39,13 +39,13 @@ Navigate to your new project directory: cd your-project-slug ``` -Install dependencies and create the virtual environment using `uv sync`: +Set up the virtual environment and install dependencies: ```bash -uv sync +uvx nox -s setup-venv ``` -This command reads `pyproject.toml`, resolves dependencies from `uv.lock`, installs them into a standard virtual environment (`.venv` by default), and prepares the project. +This sets up a virtual environment with uv and installs all development dependencies. ## 4. Install Pre-commit Hooks @@ -59,25 +59,27 @@ Now, `git commit` will automatically run code formatting and basic linting check ## 5. Run Checks and Tests -Execute the template's core quality checks and tests using `nox` from the project root: +Run quality checks and tests using the nox sessions: ```bash -uvx nox -s check # Runs linters, type checker, security checks -uvx nox -s test # Runs tests and coverage -uvx nox # Runs default tasks (often check and test) +uvx nox -s lint-python # Run Ruff linting +uvx nox -s typecheck # Run Pyright type checking +uvx nox -s security-python # Run Bandit and pip-audit +uvx nox -s tests-python # Run pytest with coverage ``` -These commands use the Task Automation layer defined in `noxfile.py` and ensure checks run correctly in isolated environments using your specified Python version. +These commands run in isolated environments with the proper Python versions as defined in `noxfile.py`. ## 6. Build Documentation -If you need to view the project's generated documentation locally: +Build and serve the project documentation locally: ```bash -uvx nox -s docs +uvx nox -s docs # Build and serve with live reload +uvx nox -s build-docs # Build only (static files) ``` -This builds the project documentation website into the `docs/_build/html` directory. +The `docs` session builds and serves documentation with automatic reload on changes. ## Next Steps diff --git a/docs/usage.md b/docs/usage.md index ce862b1..34f9abf 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -57,14 +57,14 @@ The template provides a suite of tools for maintaining code quality, integrated - **Format Code:** Code formatting and import sorting is handled by {ruff}`Ruff<>` ([Topic 03](topics/03_code-formatting.md)) using the configuration in `.ruff.toml`. Your pre-commit hooks automatically fix these on commit. To format manually: ```bash - uvx nox -s lint # Includes a formatting check - # Or directly via uv run (often requires specific args): uv run ruff format . + uvx nox -s format-python # Format Python code with Ruff + uvx nox -s lint-python # Lint Python code with Ruff (includes formatting check) ``` - **Lint Code:** Linting checks for code style (beyond formatting), errors, potential bugs, and code smells using {ruff}`Ruff<>` and {pydocstyle}`pydocstyle<>` ([Topic 04](topics/04_code-linting.md)). Run checks via Task Automation: ```bash - uvx nox -s lint + uvx nox -s lint-python ``` - **Type Check Code:** Static type analysis using {pyright}`Pyright<>` ([Topic 05](topics/05_type-checking.md)) based on `pyrightconfig.json`: @@ -76,12 +76,15 @@ The template provides a suite of tools for maintaining code quality, integrated - **Security Checks:** Scan for dependency vulnerabilities with {pip-audit}`pip-audit<>` and code security issues with {bandit-bandit}`Bandit<>` ([Topic 08](topics/08_security-checks.md)): ```bash - uvx nox -s security + uvx nox -s security-python ``` - **Run All Core Checks:** ```bash - uvx nox -s check + # Run individual checks: + uvx nox -s format-python lint-python typecheck security-python + # Or use quality tag: + uvx nox -t quality ``` ## Testing @@ -91,9 +94,9 @@ The template uses {pytest-pytest-cov}`pytest<>` ([Topic 06](topics/06_testing-co - **Write Tests:** Place test files (e.g., `test_*.py` or `*_test.py`) in the `tests/` directory. - **Run Tests with Coverage:** ```bash - uvx nox -s test + uvx nox -s tests-python ``` - This runs tests across applicable Python versions and measures code coverage with {coveragepy-coverage}`coverage.py<>` ([Topic 06](topics/06_testing-coverage.md)) based on `.coveragerc`. Reports are generated (JUnit XML for CI, terminal summary). + This runs tests across applicable Python versions and measures code coverage with {coveragepy}`coverage.py<>` ([Topic 06](topics/06_testing-coverage.md)) based on `.coveragerc`. Reports are generated (JUnit XML for CI, terminal summary). ## Building and Publishing @@ -101,11 +104,11 @@ Create and publish your package following Python standards ([Topic 09](topics/09 - **Build Package:** Create standard `sdist` (`.tar.gz`) and `wheel` (`.whl`) files in the `dist/` directory. ```bash - uvx nox -s build + uvx nox -s build-python ``` - **Publish Package:** Upload built packages using {uv}`uv<>`'s publish command. Requires credentials set via environment variables (e.g., `UV_TOKEN` or `TWINE_API_KEY`). ```bash - uvx nox -s publish + uvx nox -s publish-python ``` ## Containerization @@ -114,7 +117,7 @@ Define and build Docker container images for your application ([Topic 11](topics - **Build Application Image:** Uses the `Dockerfile` in the project root. ```bash - uvx nox -s container + uvx nox -s build-container ``` - **Run with Docker Compose:** ```bash @@ -128,7 +131,7 @@ Use {commitizen}`Commitizen<>` ([Topic 12](topics/12_task-automation.md)) via {u - **Bump Version:** Automatically determine the next version (major, minor, patch, etc.) based on commit messages since the last tag, update version strings, and create a Git tag. ```bash - uvx nox -s release -- [major|minor|patch] # e.g., uvx nox -s release -- minor + uvx nox -s setup-release -- [major|minor|patch] # e.g., uvx nox -s setup-release -- minor ``` Follow the prompts. Requires following {conventional-commits}`Conventional Commits<>`. Pushing the resulting tag often triggers the CD pipeline.