Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates for January 2024 #30

Merged
merged 13 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
### What kind of change does this PR introduce?

* ...

### Does this PR introduce a breaking change?


### Other information:
145 changes: 97 additions & 48 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,12 @@
Cookiecutter PyPackage
======================

.. image:: https://pyup.io/repos/github/audreyfeldroy/cookiecutter-pypackage/shield.svg
:target: https://pyup.io/repos/github/audreyfeldroy/cookiecutter-pypackage/
:alt: Updates

.. image:: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml/badge.svg
:target: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml
:alt: Build Status

.. image:: https://readthedocs.org/projects/cookiecutter-pypackage/badge/?version=latest
:target: https://cookiecutter-pypackage.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
|build|

Cookiecutter_ template for a Python package.

* GitHub repo (fork): https://github.com/Ouranosinc/cookiecutter-pypackage/
* Documentation: https://cookiecutter-pypackage.readthedocs.io/
* Documentation (upstream): https://cookiecutter-pypackage.readthedocs.io/
* Free software: BSD license

Features
Expand All @@ -29,51 +19,93 @@ Features
* `Conda`_ environment file: Optionally use ``conda env create -f environment-dev.yml`` to create a new environment with the correct Python version.
* Tox_ testing: Setup to easily test for Python 3.8, 3.9, 3.10, 3.11, 3.12, and PyPy3.
* Sphinx_ docs: Documentation ready for generation with, for example, `Read the Docs`_
* pre-commit_ hook: Run your tests and linting (e.g. Flake8, Black) before you commit your code!
* bump-my-version_: Pre-configured version bumping with a single command
* pre-commit_ hook: Run your tests and linting (e.g. `black`, `flake8`, `pylint`, etc.) before you commit your code!
* `pre-commit.ci`_: Automate `pre-commit` checks and corrections in your Pull Requests.
* bump-my-version_: Pre-configured `SemVer-2.0-compliant`_ version bumping with a single command.
* dependabot_ for automated dependency updates of both project dependencies and GitHub Actions.
* `sphinx-intl`_ for French internationalization (i18n) and localization (l10n) of Sphinx docs (optional)
* Auto-release to PyPI_ when you push a new tag to main (optional)
* Auto-release to TestPyPI_ and PyPI_ when you push a new tag to main (optional)
* Command line interface using Click (optional)

Build Status
-------------

Linux:

.. image:: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml/badge.svg
:target: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml
:alt: Linux build status on GitHub Actions
Upstream (audreyfeldroy/cookiecutter-pypackage): |docs-upstream| |pyup-upstream|

Quickstart
----------

Install the latest Cookiecutter if you haven't installed it yet (this requires
Cookiecutter 1.4.0 or higher)::
Install the latest Cookiecutter if you haven't installed it yet ::

$ pip install -U cookiecutter

Or, if using Conda::

$ conda install -c conda-forge cookiecutter

Generate a Python package project::

$ cookiecutter https://github.com/Ouranosinc/cookiecutter-pypackage.git

Then:

* Create a repo and put it there.
* Install the dev requirements into a virtualenv. (``pip install -r requirements_dev.txt``)
* Register_ your project with PyPI.
* Enable GitHub Actions and Workflows and activate automated deployment on PyPI when you push a new tag to main branch.
* Add the repo to your `Read the Docs`_ account + turn on the Read the Docs service hook.
* Release your package by pushing a new tag to main.
* Add a ``requirements.txt`` file that specifies the packages you will need for
your project and their versions. For more info see the `pip docs for requirements files`_.
* Activate your project on `pyup.io`_.

.. _`pip docs for requirements files`: https://pip.pypa.io/en/stable/user_guide/#requirements-files
.. _Register: https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives
* Install the development requirements into an environment::

$ pip install -e ".[dev]"

Or, if using Conda::

$ conda env create -f environment-dev.yml
$ pip install -e . --no-deps

* `Register your project with PyPI <https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives>`_.
* Enable GitHub Actions and Workflows (see below).
* Activate automated deployment with `Trusted Publishing`_ to PyPI when you push a new tag to the `main` branch.
* Add the repo to your `Read the Docs`_ account and turn on the ReadTheDocs service hook.
* Release your package by pushing a new tag to `main`.
* Update the `dependencies` field of your `pyproject.toml` file that specifies the packages you will need for
your project and their versions. For more info see the `pip docs for requirements files <https://pip.pypa.io/en/stable/user_guide/#requirements-files>`_.
* Register your project with `pre-commit.ci`_.
* Activate `dependabot`_ for your project.

For more details, see the `cookiecutter-pypackage tutorial`_.

.. _`cookiecutter-pypackage tutorial`: https://cookiecutter-pypackage.readthedocs.io/en/latest/tutorial.html
GitHub Actions
~~~~~~~~~~~~~~

In order to use GitHub Actions, you will need to enable them in your repo. To do so, go to the `Actions` tab of your repo and click the green button to enable them. Afterwards, you will need to ~generate a few Personal Access Tokens (PATs) <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens>`_ to allow the workflows to run. To do so, go to the `Settings` tab of your repo and click on `Secrets` in the left sidebar. Then, click on the `New repository secret` button and add the following secrets:

* `BUMP_VERSION_TOKEN` with the following privileges:
- Contents: Read and Write
- Metadata: Read-Only
- Pull Requests: Read and Write

* `OPENSSF_SCORECARD_TOKEN` with the following privileges:
- Administration: Read-Only
- Metadata: Read-Only
- Webhooks: Read-Only

Trusted Publishing
~~~~~~~~~~~~~~~~~~

For Trusted Publishing with PyPI_ and TestPyPI_, you will need to create deployment environments in your repo. To do so, go to the `Settings` tab of your repo and click on `Environments` in the left sidebar. Then, click on the `New environment` button and add the following environments:

* `staging`
* `production`

Afterwards, you will need to configure your project on both PyPI_ and TestPyPI_ to accept uploads from GitHub Actions. To do so, go to the `Manage` tab of your project on PyPI and click on `Publishing` in the left sidebar. Then, click on the `Add a new publisher` button and fill in the following information:

* Owner: `my_username`
* Repository name: `my_project`
* Workflow name:
* For TestPyPI: `tag-testpypi.yml`
* For PyPI: `publish-pypi.yml`
* Environment name:
* For TestPyPI: `staging`
* For PyPI: `production`

Once this is configured, all you need to do is push a new tag to the `main` branch and your package will be automatically published to TestPyPI_, while performing a release on GitHub will then trigger an upload to PyPI_.

Not Exactly What You Want?
--------------------------
Expand Down Expand Up @@ -128,27 +160,44 @@ I also accept pull requests on this, if they're small, atomic, and if they make
.. _Mkdocs: https://pypi.org/project/mkdocs/
.. _Mypy: https://mypy.readthedocs.io/en/stable/
.. _Poetry: https://python-poetry.org/
.. _Pre-commit: https://pre-commit.com/
.. _Punch: https://github.com/lgiordani/punch
.. _PyPI: https://pypi.python.org/pypi
.. _Read the Docs: https://readthedocs.io/
.. _SemVer-2.0-compliant: https://semver.org/spec/v2.0.0.html
.. _Sphinx: http://sphinx-doc.org/
.. _Tox: http://testrun.org/tox/
.. _`pyproject.toml`: https://www.python.org/dev/peps/pep-0518/
.. _`pyup.io`: https://pyup.io/
.. _bump2version: https://github.com/c4urself/bump2version
.. _bump-my-version: https://github.com/callowayproject/bump-my-version
.. _bump2version: https://github.com/c4urself/bump2version
.. _cookiecutter-pypackage tutorial: https://cookiecutter-pypackage.readthedocs.io/en/latest/tutorial.html
.. _dependabot: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates
.. _flit: https://flit.pypa.io/en/stable/
.. _pre-commit.ci: https://pre-commit.ci/
.. _pre-commit: https://pre-commit.com/
.. _pypi: https://pypi.org/
.. _pyproject.toml: https://www.python.org/dev/peps/pep-0518/
.. _pyup.io: https://pyup.io/
.. _sphinx-intl: https://sphinx-intl.readthedocs.io/en/master/
.. _testpypi: https://test.pypi.org/

.. _GitHub comparison view: https://github.com/tony/cookiecutter-pypackage-pythonic/compare/audreyr:master...master
.. _`Nekroze/cookiecutter-pypackage`: https://github.com/Nekroze/cookiecutter-pypackage
.. _`ardydedase/cookiecutter-pypackage`: https://github.com/ardydedase/cookiecutter-pypackage
.. _`briggySmalls/cookiecutter-pypackage`: https://github.com/briggySmalls/cookiecutter-pypackage
.. _`family tree`: https://github.com/audreyr/cookiecutter-pypackage/network/members
.. _`lgiordani/cookiecutter-pypackage`: https://github.com/lgiordani/cookiecutter-pypackage
.. _`tony/cookiecutter-pypackage-pythonic`: https://github.com/tony/cookiecutter-pypackage-pythonic
.. _`veit/cookiecutter-namespace-template`: https://github.com/veit/cookiecutter-namespace-template
.. _`waynerv/cookiecutter-pypackage`: https://waynerv.github.io/cookiecutter-pypackage/
.. _`zillionare/cookiecutter-pypackage`: https://zillionare.github.io/cookiecutter-pypackage/
.. _Nekroze/cookiecutter-pypackage: https://github.com/Nekroze/cookiecutter-pypackage
.. _ardydedase/cookiecutter-pypackage: https://github.com/ardydedase/cookiecutter-pypackage
.. _briggySmalls/cookiecutter-pypackage: https://github.com/briggySmalls/cookiecutter-pypackage
.. _family tree: https://github.com/audreyr/cookiecutter-pypackage/network/members
.. _lgiordani/cookiecutter-pypackage: https://github.com/lgiordani/cookiecutter-pypackage
.. _network: https://github.com/audreyr/cookiecutter-pypackage/network
.. _tony/cookiecutter-pypackage-pythonic: https://github.com/tony/cookiecutter-pypackage-pythonic
.. _veit/cookiecutter-namespace-template: https://github.com/veit/cookiecutter-namespace-template
.. _waynerv/cookiecutter-pypackage: https://waynerv.github.io/cookiecutter-pypackage/
.. _zillionare/cookiecutter-pypackage: https://zillionare.github.io/cookiecutter-pypackage/

.. |build| image:: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml/badge.svg
:target: https://github.com/Ouranosinc/cookiecutter-pypackage/actions/workflows/main.yml
:alt: Build Status

.. |docs-upstream| image:: https://readthedocs.org/projects/cookiecutter-pypackage/badge/?version=latest
:target: https://cookiecutter-pypackage.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status

.. |pyup-upstream| image:: https://pyup.io/repos/github/audreyfeldroy/cookiecutter-pypackage/shield.svg
:target: https://pyup.io/repos/github/audreyfeldroy/cookiecutter-pypackage/
:alt: Updates
3 changes: 2 additions & 1 deletion hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ def remove_folder(folder_path):

def replace_contents(filepath):
replacements = {
"__BUMPVERSION_TOKEN__": "secrets.BUMPVERSION_TOKEN",
"__BUMP_VERSION_TOKEN__": "secrets.BUMP_VERSION_TOKEN",
"__GITHUB_REF__": "github.ref",
"__GITHUB_REF_NAME__": "github.ref_name",
"__GITHUB_TOKEN__": "secrets.GITHUB_TOKEN",
"__PYTHON_VERSION__": "matrix.python-version",
"__TOX_ENV__": "matrix.tox-env",
"__OPENSSF_SCORECARD_TOKEN__": "secrets.OPENSSF_SCORECARD_TOKEN",
}

lines = []
Expand Down
6 changes: 4 additions & 2 deletions tests/test_bake_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def test_bake_with_apostrophe_and_run_tests(cookies):
assert result.project_path.is_dir()
assert run_inside_dir("python -m coverage", str(result.project_path)) == 0


def test_bake_without_translations(cookies):
with bake_in_temp_dir(cookies, extra_context={"add_translations": "n"}) as result:
found_toplevel_files = [f.name for f in result.project_path.iterdir()]
Expand All @@ -146,6 +147,7 @@ def test_bake_without_translations(cookies):
with open(str(pyproject_path)) as pyproject_file:
assert "sphinx-intl" not in pyproject_file.read()


def test_bake_without_docs(cookies):
with bake_in_temp_dir(cookies, extra_context={"make_docs": "n"}) as result:
found_toplevel_files = [f.name for f in result.project_path.iterdir()]
Expand Down Expand Up @@ -333,8 +335,8 @@ def test_black(cookies, use_black, expected):
with bake_in_temp_dir(cookies, extra_context={"use_black": use_black}) as result:
assert result.project_path.is_dir()
requirements_path = result.project_path.joinpath("pyproject.toml")
assert ("black>=" in requirements_path.read_text()) is expected
assert ("isort>=" in requirements_path.read_text()) is expected
assert ("black==" in requirements_path.read_text()) is expected
assert ("isort==" in requirements_path.read_text()) is expected
assert ("[tool.black]" in requirements_path.read_text()) is expected
makefile_path = result.project_path.joinpath("Makefile")
assert ("black --check" in makefile_path.read_text()) is expected
15 changes: 15 additions & 0 deletions {{cookiecutter.project_slug}}/.github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily
time: '12:00'
open-pull-requests-limit: 10

- package-ecosystem: pip
directory: /
schedule:
interval: daily
time: '12:00'
open-pull-requests-limit: 10
49 changes: 49 additions & 0 deletions {{cookiecutter.project_slug}}/.github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# label rules used by .github/workflows/label.yml

# label 'ci' all automation-related steps and files
# Since this repository is in itself an automation process to deploy a server instance,
# we refer here to CI as the 'meta' configuration files for managing the code and integrations with the repository,
# not configurations related to the deployment process itself.

# Uncomment the following lines to enable the labeler (requires labels with the same name to exist in the repository)

# label 'ci' all automation-related steps and files
#'CI':
# - changed-files:
# - any-glob-to-any-file:
# - '.editorconfig'
# - '.flake8'
# - '.pre-commit-config.yaml'
{%- if cookiecutter.make_docs != 'y' %}
# - '.readthedocs.yml'
{%- endif %}
# - '.yamllint.yml'
# - '.github/workflows/*'
{%- if cookiecutter.make_docs != 'y' %}
# - 'docs/Makefile'
{%- endif %}
# - 'tox.ini'
# - 'Makefile'

{%- if cookiecutter.make_docs != 'y' %}
# label 'docs' all documentation-related steps and files
#'docs':
# - changed-files:
# - any-glob-to-any-file:
# - '.readthedocs.yml'
{%- if cookiecutter.open_source_license != 'Not open source' %}
# - '.zenodo.json'
{%- endif %}
# - 'docs/**/*'
# - 'environment-docs.yml'
{%- if cookiecutter.create_author_file != 'y' %}
# - 'AUTHORS.rst'
{%- endif %}
# - 'CONTRIBUTING.rst'
# - 'CODE_OF_CONDUCT.md'
# - 'DISCUSSION_TEMPLATE/**/*'
# - 'ISSUE_TEMPLATE/**/*'
# - 'ISSUE_TEMPLATE.md'
# - 'PULL_REQUEST_TEMPLATE.md'
# - 'README.rst'
{%- endif %}

This file was deleted.

24 changes: 20 additions & 4 deletions {{cookiecutter.project_slug}}/.github/workflows/bump-version.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This workflow requires a personal access token named `BUMPVERSION_TOKEN` with the following privileges:
# - repo
# - workflow
# This workflow requires a personal access token named `BUMP_VERSION_TOKEN` with the following privileges:
# - Contents: Read and Write
# - Metadata: Read-Only
# - Pull Requests: Read and Write

name: "Bump Patch Version"

Expand Down Expand Up @@ -39,10 +40,25 @@ on:
- {{ cookiecutter.project_slug }}/__init__.py
workflow_dispatch:

permissions:
contents: read

jobs:
bump_patch_version:
runs-on: ubuntu-latest
permissions:
actions: read
contents: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
files.pythonhosted.org:443
github.com:443
pypi.org:443
- uses: actions/checkout@v4
with:
persist-credentials: false
Expand All @@ -65,5 +81,5 @@ jobs:
uses: ad-m/github-push-action@master
with:
force: false
github_token: __BUMPVERSION_TOKEN__
github_token: __BUMP_VERSION_TOKEN__
branch: __GITHUB_REF__
Loading
Loading