{"id":16360211,"url":"https://github.com/larsrollik/templatepy","last_synced_at":"2025-10-26T04:32:13.244Z","repository":{"id":41900354,"uuid":"370470893","full_name":"larsrollik/templatepy","owner":"larsrollik","description":"Template repository for best-practice Python packages","archived":false,"fork":false,"pushed_at":"2025-06-06T13:35:21.000Z","size":259,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-25T10:56:26.431Z","etag":null,"topics":["build-system","bumpversion","community","linting","package","pre-commit","pypi","python","template","zenodo","zenodo-upload"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/larsrollik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-05-24T20:01:57.000Z","updated_at":"2025-07-03T08:29:00.000Z","dependencies_parsed_at":"2024-10-11T02:10:57.942Z","dependency_job_id":"c584bce8-4fb3-45d5-9299-c64fcfda3c1b","html_url":"https://github.com/larsrollik/templatepy","commit_stats":{"total_commits":69,"total_committers":3,"mean_commits":23.0,"dds":0.3188405797101449,"last_synced_commit":"428cf34f5751aa92a96202ccd453499f37c883b3"},"previous_names":[],"tags_count":27,"template":true,"template_full_name":null,"purl":"pkg:github/larsrollik/templatepy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larsrollik%2Ftemplatepy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larsrollik%2Ftemplatepy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larsrollik%2Ftemplatepy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larsrollik%2Ftemplatepy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/larsrollik","download_url":"https://codeload.github.com/larsrollik/templatepy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/larsrollik%2Ftemplatepy/sbom","scorecard":{"id":579383,"data":{"date":"2025-08-11","repo":{"name":"github.com/larsrollik/templatepy","commit":"3ba512b993f796fb278959c7aacb4b3d54afb325"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Maintained","score":4,"reason":"5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/20 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":0,"reason":"dangerous workflow patterns detected","details":["Warn: script injection with untrusted input ' github.event.pull_request.head.ref ': .github/workflows/pr-to-prod.yaml:43"],"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'actions' permission set to 'write': .github/workflows/pr-to-prod.yaml:17","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/pr-to-prod.yaml:16","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-to-deploy.yaml:68","Warn: no topLevel permission defined: .github/workflows/pr-to-prod.yaml:1","Warn: no topLevel permission defined: .github/workflows/pre-pr-checks.yaml:1","Warn: no topLevel permission defined: .github/workflows/release-to-deploy.yaml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pr-to-prod.yaml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pr-to-prod.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:58: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:91: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pre-pr-checks.yaml:94: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/pre-pr-checks.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-to-deploy.yaml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/release-to-deploy.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-to-deploy.yaml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/release-to-deploy.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-to-deploy.yaml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/release-to-deploy.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-to-deploy.yaml:86: update your workflow using https://app.stepsecurity.io/secureworkflow/larsrollik/templatepy/release-to-deploy.yaml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/pre-pr-checks.yaml:44","Warn: pipCommand not pinned by hash: .github/workflows/pre-pr-checks.yaml:45","Warn: pipCommand not pinned by hash: .github/workflows/pre-pr-checks.yaml:78","Warn: pipCommand not pinned by hash: .github/workflows/pre-pr-checks.yaml:79","Warn: pipCommand not pinned by hash: .github/workflows/release-to-deploy.yaml:24","Warn: pipCommand not pinned by hash: .github/workflows/release-to-deploy.yaml:91","Warn: pipCommand not pinned by hash: .github/workflows/release-to-deploy.yaml:92","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   7 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":2,"reason":"SAST tool is not run on all commits -- score normalized to 2","details":["Warn: 3 commits out of 14 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T18:46:33.793Z","repository_id":41900354,"created_at":"2025-08-20T18:46:33.793Z","updated_at":"2025-08-20T18:46:33.793Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281059645,"owners_count":26437056,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-26T02:00:06.575Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-system","bumpversion","community","linting","package","pre-commit","pypi","python","template","zenodo","zenodo-upload"],"created_at":"2024-10-11T02:10:55.181Z","updated_at":"2025-10-26T04:32:13.238Z","avatar_url":"https://github.com/larsrollik.png","language":"Python","readme":"[//]: # (Links)\n[Github-flavored markdown]: https://github.github.com/gfm\n\n[manifest]: https://packaging.python.org/en/latest/guides/using-manifest-in\n[packaging]: https://packaging.python.org/en/latest/tutorials/packaging-projects\n[setup.cfg]: https://setuptools.pypa.io/en/latest/userguide/declarative_config.html\n\n[bump2version]: (https://github.com/c4urself/bump2version\n[pre-commit]: https://pre-commit.com\n\n[//]: # ([black]: https://github.com/psf/black)\n[ruff]: https://docs.astral.sh/ruff\n[mypy]: https://mypy.readthedocs.io\n\n[pypi]: pypi.org\n[test.pypi]: test.pypi.org\n\n[Zenodo]: https://zenodo.org\n\n[contribution guidelines]: https://github.com/larsrollik/templatepy/blob/main/CONTRIBUTING.md\n[issues]: https://github.com/larsrollik/templatepy/issues\n[BSD 3-Clause License]: https://github.com/larsrollik/templatepy/blob/main/LICENSE\n[Github]: https://github.com/larsrollik/templatepy/settings/secrets/actions/new\n[release]: https://github.com/larsrollik/templatepy/releases/new\n\n[//]: # (Badges)\n\n[![Contributions](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](https://github.com/larsrollik/templatepy/blob/main/CONTRIBUTING.md)\n[![DOI](https://zenodo.org/badge/370470893.svg)](https://zenodo.org/badge/latestdoi/370470893)\n[![Website](https://img.shields.io/website?up_message=online\u0026url=https%3A%2F%2Fgithub.com/larsrollik/templatepy)](https://github.com/larsrollik/templatepy)\n[![PyPI](https://img.shields.io/pypi/v/templatepy.svg)](https://pypi.org/project/templatepy)\n[![Wheel](https://img.shields.io/pypi/wheel/templatepy.svg)](https://pypi.org/project/templatepy)\n![CI](https://img.shields.io/github/actions/workflow/status/larsrollik/templatepy/pre-pr-checks.yaml?branch=main\u0026label=build)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white)](https://github.com/pre-commit/pre-commit)\n\n\n# templatepy\nTemplate repo for python repositories \u0026 PyPi integration\n---\n**Version: \"0.2.9\"**\n\n\n## Usage\n1. **Change** files according to overview in `TODO` below\n2. **Develop** package...\n3. **Install** package:\n   - static/normal install: `pip install .`\n   - editable install:`pip install -e .`\n   - dev install: `pip install -e .[dev]` (some terminals require to escape brackets with ` \\ ` as `\\[`, esp. zsh)\n\n\n\n## File overview\n\n\n### General\n- `LICENSE`: license text\n\n- `README.md`: [Github-flavored markdown] file\n\n- `templatepy`: placeholder folder for any python package that is configured for install via `setup.cfg` and `pyproject.toml`\n  - `__init__.py`: contains basic package info and example function that is called by console entrypoint (see `setup.cfg`)\n  - `example.data.file.config`: a file to demonstrate that data files are included based on `setup.cfg` criteria\n  - `example.data.file.test-extension-yu48`: a file to demonstrate data exclusion via `setup.py`\n\n\n### Testing\n- `tests`: placeholder folder for unit/integration tests and associated data\n- `pytest.ini`: config for testing framework with `pytest` and `coverage` plugin (`pytest-cov`)\n\n\n### Packaging System (see: [packaging] and [pyproject.toml])\n\n- **`MANIFEST.in`**:\n  Defines additional files to include/exclude in the build (if not automatically detected).\n\n- **`pyproject.toml`**:\n  Central configuration file that replaces the traditional `setup.cfg` and `setup.py` files:\n  - **Build System**: Specifies the build system requirements and configuration, as defined in [PEP 518](https://peps.python.org/pep-0518/) and [PEP 621](https://peps.python.org/pep-0621/).\n  - **Package Metadata**: Includes the project's metadata (name, version, dependencies, etc.).\n  - **Code Formatting**: Configuration for tools like [ruff] and [mypy] (if used).\n  - **Optional Dependencies**: Organizes extra dependencies for development or other environments.\n\n- **`setup.py`**:\n  Legacy file retained only for backward compatibility if needed (e.g., older tooling). New projects should avoid it entirely.\n\n\n## CI Workflow Overview\n\nThe CI workflow is triggered on push to `main` or when a tag is created. It ensures code quality and automates the release process:\n\n1. **Linting and Testing**:\n   - `lint`: Checks code style with `black` and `flake8`, runs pre-commit hooks.\n   - `test`: Runs tests with `pytest` and generates coverage reports.\n\n2. **Tag Validation**:\n   - `check-tag`: Verifies that the tag is valid (not `dev` or `rc`) before proceeding.\n\n3. **Release Creation**:\n   - `release`: Creates a GitHub release when the tag is valid.\n\n4. **Deployment to PyPI**:\n   - `deploy`: Builds and uploads the package to PyPI using `twine`.\n\nThe pipeline ensures code quality, passing tests, and automated deployment on new releases.\n\n### Testing CI Locally\n\n- Install `act`:\n  - **macOS/Linux**: `brew install act` / `sudo apt install act`\n  - **Windows**: Download from [act GitHub Releases](https://github.com/nektos/act/releases) and follow the installation instructions.\n- Ensure Docker is installed and running. Download from [Docker Desktop](https://www.docker.com/products/docker).\n- Run the CI workflow with `act`:\n  ```bash\n  act push\n  act push --verbose  # very verbose output !\n  ```\n\n\n### Code maintenance (linting/formatting/github)\n- `.pre-commit-config.yaml`: use [pre-commit] to run code formatting (e.g. with [black] and `flake8`) and PEP compliance checks\n  - Install pre-commit hook with `pre-commit install` (Note: only installs it in the current virtual environment)\n  - Run it manually with `pre-commit run --all` or leave it to run on commit (requires to re-stage changed files!)\n\n- `.github`: folder that contains github automation workflows and issues templates\n\n- `.gitignore`: ignored files/folders in git tools\n\n- `.bumpversion.cfg`:  config for [bump2version]\n\n## TODO for **adapting** template to new project\n\n- [ ] Change package name:\n  - (1) Rename the `templatepy` folder.\n  - (2) Update all occurrences  of `templatepy` in `README.md`.\n  - (3) Update the `name` field in `pyproject.toml`.\n  - (4) (optional) Update `.github/workflows` files.\n  - (5) Reset version references in `pyproject.toml` and `templatepy/__init__.py` to `0.0.0.dev0`.\n- [ ] Update project author and metadata details in `pyproject.toml`, `README.md`, and `templatepy/__init__.py`.\n- [ ] Update the license holder in the `LICENSE` file.\n- [ ] Update `README.md` badge paths at the top.\n- [ ] Verify inclusions/exclusions of installable files/folders in `MANIFEST.in` and `pyproject.toml` under `[tool.setuptools]`.\n- [ ] Ensure `.gitignore` contains relevant entries for the new project.\n- [ ] Add all version string locations to `[tool.bump2version]` in `pyproject.toml`.\n  - Use syntax like `[bumpversion:file:templatepy/__init__.py]` to specify locations for version updates.\n- [ ] To upload to [PyPI], follow the instructions in the section below.\n- [ ] To upload to [Zenodo] (if the repository is for a publication):\n  - (1) Connect Zenodo to your GitHub account.\n  - (2) Enable Zenodo integration for the repository (Zenodo requires the repository to be **public**).\n  - (3) Create a new GitHub release (manually or via `.github/workflows/CI.yaml`).\n  - (4) Wait for Zenodo to sync and assign a DOI (this usually takes about a minute).\n  - (5) Add the DOI badge to `README.md`.\n\n\n## Workflow for Automatically Uploading Package to [PyPI] or [Test PyPI]\n\n1. **Generate a PyPI API Key**:\n   - Go to [PyPI](https://pypi.org/) and create a new API key, either specific to the repository or a general-purpose key.\n\n2. **Add the API Key to GitHub**:\n   - In your repository's settings on [GitHub](https://github.com/):\n     - Navigate to **Settings \u003e Secrets and variables \u003e Actions**.\n     - Add a new **Actions secret** with the name `TWINE_API_KEY`.\n     - Paste the PyPI API key into the secret's value field.\n\n3. **Create a New Release**:\n   - On [GitHub](https://github.com/), create a new release manually via the **Releases** page.\n     - Use a version number without a release extension (e.g., `x.y.z`).\n   - Alternatively, trigger the GitHub workflow configured for releasing by incrementing the version with `bump2version` (see info below)\n   - Desperately, manually update the version strings in the relevant files and add git commit tag to trigger the release workflow on push\n\nThe package will then be automatically uploaded to [PyPI](https://pypi.org/) or [Test PyPI](https://test.pypi.org/) as configured in your CI/CD workflow.\n\n\n## Using `bump2version` for Versioning\n\n`bump2version` is used to increment version numbers based on semantic versioning. Here’s how you can use it with the current setup to trigger a release:\n\n1. **Bumping the Minor Version**:\n   Increment the minor version (e.g., from `v1.2.3` to `v1.3.0`):\n   ```bash\n   # Bumping the minor Version:\n   bump2version minor\n\n   # Bumping the major version (e.g., from v1.2.3 to v2.0.0):\n   bump2version major\n\n   # Bumping for a release Version (e.g., from v1.0.0.dev to v1.0.0.rc or v1.0.0):\n   bump2version release\n   ```\n\n## Workflows Summary\n\n| **Workflow**               | **Triggers**                                      | **Purpose**                                | **Outputs**                            |\n|----------------------------|---------------------------------------------------|--------------------------------------------|----------------------------------------|\n| **Lint and Test**          | Push to any branch                                | Runs linting and testing for Python code   | Ensures code quality and functionality |\n| **Release to PyPI**        | Push to `prod` branch with a tag (e.g., `v1.0.0`) | Builds and uploads the package to PyPI     | Publishes a new release on PyPI        |\n| **Squash Merge to `prod`** | Pull requests merged into `main`                  | Squashes and merges commits into `prod`    | Maintains clean history in `prod`      |\n| **AI Pull Request Review** | Pull request events (`opened`, `synchronize`)     | Provides AI-generated pull request reviews | Adds review comments to the PR         |\n\n\n## Required Repository Secrets\n\n| **Secret**       | **Purpose**                                 | **How to Obtain**                                                                           |\n|------------------|---------------------------------------------|---------------------------------------------------------------------------------------------|\n| `TWINE_API_KEY`  | Authentication for publishing to PyPI       | Generate from [PyPI Account Settings](https://pypi.org/manage/account/) under \"API Tokens.\" |\n| `OPENAI_API_KEY` | Required for AI Pull Request Reviewer       | Generate from [OpenAI API Settings](https://platform.openai.com/account/api-keys).          |\n| `GITHUB_TOKEN`   | Built-in token for accessing the repository | Automatically provided by GitHub (no setup needed).                                         |\n\n\n## Github Flow overview\n\n1) Create a new feature branch from main using git checkout -b.\n2) Make and commit a dummy change (e.g., adding a file).\n3) Use bumpversion to bump the version (you can adjust patch, minor, or major based on what change you want), and create a release tag.\n4) Push both the feature branch and the release tag to the remote repository.\n5) Open a pull request using GitHub CLI (gh pr create) or the GitHub UI to merge the feature branch into main.\n6) Review the pull request online or in the CLI (e.g.: `gh pr list`, `gh pr view \u003cnr\u003e`, `gh pr merge \u003cnr\u003e --merge --delete-branch`)\n7) After the PR is merged, delete the feature branch both locally and remotely.\n\n\n### Example commands for the workflow:\n\n```bash\n# 1. Checkout a new feature branch from main\ngit checkout main  # Ensure you are on the main branch\ngit pull origin main  # Fetch latest changes from main\ngit checkout -b feature/my-new-feature  # Create and switch to a new feature branch\n\n# 2. Make a dummy commit (e.g., add a new file or change)\necho \"Some feature work\" \u003e feature.txt  # Add a new file or make a change\ngit add feature.txt  # Stage the file for commit\ngit commit -m \"Add feature.txt - dummy commit\"  # Commit the changes\n\n# 3. Bump the version and automatically tag the release\n# (Bumpversion will handle both version bumping and tagging)\nbumpversion patch  # Bumps version, e.g., from v0.1.0 to v0.1.1 (adjust based on version part you want)\n\n# 4. Push the changes to remote (feature branch and the tag)\ngit push origin feature/my-new-feature  # Push the feature branch\ngit push origin --tags  # Push the new tag(s) created by bumpversion\n\n# 5. Open a pull request from the feature branch to the main branch\n# This can be done via GitHub UI, or using GitHub CLI\ngh pr create \\\n  --base main \\\n  --head feature/my-new-feature \\\n  --title \"pr_title\" \\\n  --body \"pr_body\"\n\n# 6.\ngh pr list  # -\u003e shows PRs and their IDs\ngh pr view \u003cid\u003e\n\ngh pr merge \u003cid\u003e --merge --delete-branch\n\n# 7. After the PR is accepted and merged, delete the feature branch locally and remotely\ngit checkout main  # Switch back to main branch\ngit pull origin main  # Ensure your main branch is up-to-date\ngit branch -d feature/my-new-feature  # Delete the local feature branch\ngit push origin --delete feature/my-new-feature  # Delete the remote feature branch\n\n```\n\n## Notes\n\n#### New(er) Build System with `pyproject.toml` and `setup.cfg`\n\nHistorically, packaging in Python was governed by standards such as `PEP-426`, `PEP-517`, and `PEP-518`. These PEPs introduced various mechanisms for packaging and building Python projects, but with certain limitations, especially regarding flexibility and future-proofing.\n\n- **PEP-426**: Introduced the `setup.cfg` and `setup.py` files as the standard way to define package metadata and build configuration.\n- **PEP-517**: Introduced a standardized interface for building Python projects, separating the build process from the packaging process and allowing for more flexible build systems.\n- **PEP-518**: Defined how `pyproject.toml` should be used to declare build dependencies and system requirements, allowing tools like `pip` to know which backend to use for the build process.\n\nWhile these PEPs were important milestones, the latest changes to the packaging ecosystem make `pyproject.toml` the preferred way to configure projects going forward.\n\n- **`pip`**:\n  - Tested with `pip install . --use-feature=in-tree-build` for forward compatibility with `pip 21.3` and later.\n  - While `setup.py` is technically optional, an empty `setup.py` is still kept for enabling editable installs (`pip install -e .`), as this requires such a file for now.\n  - `wheel` is added as a build-system dependency to maintain compatibility with versions of `pip` that do not yet fully implement `PEP 517`.\n\n- **Replacing `setup.cfg` and `setup.py` with `pyproject.toml`**:\n  - In the modern packaging ecosystem, `pyproject.toml` is increasingly the standard for declaring build systems, dependencies, and metadata. This configuration file simplifies the process and eliminates the need for separate `setup.py` and `setup.cfg` files in many cases.\n\nFor further reading on the transition to `pyproject.toml` and the removal of `setup.py`/`setup.cfg`, see the following discussions:\n- [PEP-426](https://peps.python.org/pep-0426/)\n- [PEP-517](https://peps.python.org/pep-0517/)\n- [PEP-518](https://peps.python.org/pep-0518/)\n- [Discussion on Setup.cfg Deprecation](https://stackoverflow.com/questions/44878600/is-setup-cfg-deprecated)\n\n#### Using GitHub CLI in Workflow Actions\n\nEasily integrate GitHub CLI into workflows to perform repository tasks. See the [GitHub CLI in workflows documentation](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-github-cli-in-workflows).\n\n**Example: Create a pull request**\n\n```yaml\n- name: Create a pull request\n  run: gh pr create --title \"My pull request\" --body \"This is an amazing PR\" --label bug\n  env:\n    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n```\n\n\n## Common issues\n\n### `bump2version` fails on git tag with exit status 128\n\n- check a signing key is configured: `git config --global user.signingkey` (see below for generating a key)\n- repo is a detached HEAD? check out a branch: `git checkout main`\n- there are changes that need to be committed? `git commit -am \"commit message\"`\n- tag already exists? `git tag` to list tags, `git tag -d \u003ctag\u003e` to delete a tag\n\n### No gpg key for signing commits\n- generate a key with `gpg --full-generate-key`\n  - standard options for keys: \"(9) ECC (sign and encrypt) *default*\" -\u003e Curve 25519 -\u003e expiry 2 years: \"2y\" -\u003e name/email\n- list keys with `gpg --list-secret-keys --keyid-format LONG`\n- set the key for signing commits with `git config --global user.signingkey \u003ckey-id\u003e`\n- enable signing commits with `git config --global commit.gpgsign true`\n- set the key for signing tags with `git config --global tag.gpgSign true`\n- export the public key with `gpg --armor --export \u003ckey-id\u003e`\n  - and add it to your GitHub account: select 'New key' -\u003e paste output of command above\n\nWhich one is the key id you might ask?\n```\n/home/$USER/.gnupg/secring.gpg\n------------------------------\nsec   4096R/\u003cKEY_ID\u003e 2024-11-22 [expires: 2025-11-22]\n      uid                          Your Name \u003cyouremail@example.com\u003e\nssb   4096R/\u003cKEY_SUBKEY_ID\u003e 2024-11-22\n\n```\n\n### GPG hangs/errors and never asks for passphrase of key?\n\n- try: `export GPG_TTY=$(tty)`\n\n\n## Contributing\nContributions are very welcome!\nPlease see the [contribution guidelines] or check out the [issues]\n\n\n## License\nThis software is released under the **[BSD 3-Clause License]**\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flarsrollik%2Ftemplatepy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flarsrollik%2Ftemplatepy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flarsrollik%2Ftemplatepy/lists"}