diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 8a4a20f..b3bd4d7 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -21,7 +21,7 @@ permissions: jobs: analyze: name: 'Analyze' - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: actions: read contents: read diff --git a/.github/workflows/dependency-review.yaml b/.github/workflows/dependency-review.yaml index 2d7d61b..6fa9564 100644 --- a/.github/workflows/dependency-review.yaml +++ b/.github/workflows/dependency-review.yaml @@ -16,7 +16,7 @@ permissions: jobs: dependency-review: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: 'Harden runner' uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 diff --git a/.github/workflows/ossf-scorecard.yaml b/.github/workflows/ossf-scorecard.yaml index a827242..9066460 100644 --- a/.github/workflows/ossf-scorecard.yaml +++ b/.github/workflows/ossf-scorecard.yaml @@ -20,7 +20,7 @@ permissions: read-all jobs: analysis: name: 'Scorecard analysis' - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: # Needed to upload the results to code-scanning dashboard. security-events: write diff --git a/.github/workflows/python-app.yaml b/.github/workflows/python-app.yaml new file mode 100644 index 0000000..3b2de38 --- /dev/null +++ b/.github/workflows/python-app.yaml @@ -0,0 +1,303 @@ +# This workflow installs Python dependencies, runs tests, builds a release. +# For tagged pushes, it also creates a release, uploads build artifacts to the +# GitHub release, and publishes it to PyPI. +# Originally from: +# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: 'Build, test, release, upload, and publish Python app' + +env: + OUTPUT: dist/release-notes.md +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-22.04 + + outputs: + commit-tag: '${{ steps.envs.outputs.commit-tag }}' + dist-artifact-name: '${{ steps.envs.outputs.artifact-name }}' + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + allowed-endpoints: > + api.github.com:443 + files.pythonhosted.org:443 + github.com:443 + pypi.org:443 + + - name: 'Checkout repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + fetch-tags: true + persist-credentials: false + + - name: 'Install Poetry' + run: 'pipx install poetry' + + - name: 'Set up Python' + id: setup-python + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + with: + python-version: '>=3.9 <3.13' + cache: 'poetry' + + - name: 'Get tag-based commit name' + id: envs + run: | + TAG=$(git describe --tags) && echo "commit-tag=$TAG" | tee -a "$GITHUB_OUTPUT" >>"$GITHUB_ENV" + echo 'python-version=${{ steps.setup-python.outputs.python-version }}' >>"$GITHUB_ENV" + echo 'artifact-name=dist-reliabot-${{ env.commit-tag }}-${{ env.python-version }}' >>"$GITHUB_OUTPUT" + shell: bash + + - name: 'Build distribution packages' + run: 'poetry build' + + - name: 'Generate release notes' + if: "${{ startsWith(github.ref, 'refs/tags/') }}" + uses: orhun/git-cliff-action@8b17108aad4d9362649a5dae020746c2a767c90d # v3.0.2 + with: + args: '--latest' + config: release.toml + + - name: 'Generate "unreleased" notes' + if: "${{ ! startsWith(github.ref, 'refs/tags/') }}" + uses: orhun/git-cliff-action@8b17108aad4d9362649a5dae020746c2a767c90d # v3.0.2 + with: + args: '--unreleased' + config: release.toml + + - name: 'Upload distribution package as an artifact' + id: upload-artifact + if: github.repository == 'dupuy/reliabot' + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + if-no-files-found: error + name: '${{ steps.envs.outputs.artifact-name }}' + overwrite: true + path: 'dist/*' + retention-days: 14 + + test: + runs-on: ubuntu-22.04 + + strategy: + matrix: + fail-fast: [true] + max-concurrency: [5] + python-version: + - '3.8' + - '3.9' + - '3.10' + - '3.11' + - '3.12' + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + allowed-endpoints: > + files.pythonhosted.org:443 + github.com:443 + pypi.org:443 + + - name: 'Checkout repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 1 + fetch-tags: false + persist-credentials: false + + - name: 'Install Poetry' + run: 'pipx install poetry' + + - name: 'Set up Python' + id: setup-python + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + with: + python-version: '${{ matrix.python-version }}' + cache: 'poetry' + + - name: 'Install dependencies' + run: 'poetry install --extras re2-wheels --with testing' + + - name: 'Run tests with coverage' + run: 'poetry run tox -e py' + + draft-release: + runs-on: ubuntu-22.04 + + if: github.repository == 'dupuy/reliabot' + needs: + - build + - test + outputs: + commit-tag: '${{ needs.build.outputs.commit-tag }}' + dist-artifact-name: '${{ needs.build.outputs.dist-artifact-name }}' + permissions: + contents: write + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + allowed-endpoints: > + api.github.com:443 + uploads.github.com:443 + + - name: 'Download release artifacts' + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + name: '${{ needs.build.outputs.dist-artifact-name }}' + path: dist/ + + - name: 'Create draft pre-release and upload artifacts' + if: "${{ contains(needs.build.outputs.commit-tag, '-') }}" + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 + with: + allowUpdates: true + artifactErrorsFailBuild: true + artifacts: dist/* + bodyFile: '${{ env.OUTPUT }}' + draft: true + name: 'Pre-release ${{ needs.build.outputs.commit-tag }}' + prerelease: true + tag: '${{ github.ref }}' + updateOnlyUnreleased: true + + - name: 'Create draft release and upload artifacts' + if: "${{ ! contains(needs.build.outputs.commit-tag, '-') }}" + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 + with: + allowUpdates: true + artifactErrorsFailBuild: true + artifacts: dist/* + bodyFile: '${{ env.OUTPUT }}' + draft: true + name: 'Release ${{ needs.build.outputs.commit-tag }}' + prerelease: false + tag: '${{ github.ref }}' + updateOnlyUnreleased: true + + test-publish: + runs-on: ubuntu-22.04 + + if: "${{ github.repository == 'dupuy/reliabot' && contains(needs.build.outputs.commit-tag, '-') }}" + needs: + - build # does not require 'test' matrix to pass + environment: + name: test-pypi + url: https://test.pypi.org/p/reliabot + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + + - name: 'Download release artifacts' + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + name: '${{ needs.build.outputs.dist-artifact-name }}' + path: dist/ + + - name: 'Publish pre-release to TestPyPI' + uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06 # v1.8.2 + + publish: + runs-on: ubuntu-22.04 + + if: "${{ github.repository == 'dupuy/reliabot' && startsWith(github.ref, 'refs/tags/') && ! contains(needs.build.outputs.commit-tag, '-') }}" + needs: + - draft-release + - test + environment: + name: pypi + url: https://pypi.org/p/reliabot + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + + - name: 'Download release artifacts' + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + name: '${{ needs.draft-release.outputs.dist-artifact-name }}' + path: dist/ + + - name: 'Publish release to PyPI' + uses: pypa/gh-action-pypi-publish@e53eb8b103ffcb59469888563dc324e3c8ba6f06 # v1.8.2 + + test-release: + runs-on: ubuntu-22.04 + + needs: + - draft-release + - test-publish + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + + - name: 'Publish GitHub (pre-)release' + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 + with: + allowUpdates: true + draft: false + omitBodyDuringUpdate: true + omitNameDuringUpdate: true + prerelease: true + replacesArtifacts: false + tag: '${{ github.ref }}' + + release: + runs-on: ubuntu-22.04 + + needs: + - draft-release + - publish + + steps: + - name: 'Harden runner' + uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0 + with: + disable-sudo: true + egress-policy: audit + + - name: 'Publish GitHub release' + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 + with: + allowUpdates: true + draft: false + omitBodyDuringUpdate: true + omitNameDuringUpdate: true + prerelease: false + replacesArtifacts: false + tag: '${{ github.ref }}' + updateOnlyUnreleased: true diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index 098609f..0bc6b66 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -15,7 +15,7 @@ permissions: jobs: stale: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 permissions: issues: write pull-requests: write diff --git a/poetry.lock b/poetry.lock index b8186ef..5e0caea 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,124 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. + +[[package]] +name = "cachetools" +version = "5.3.3" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.3-py3-none-any.whl", hash = "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945"}, + {file = "cachetools-5.3.3.tar.gz", hash = "sha256:ba29e2dfa0b8b556606f097407ed1aa62080ee108ab0dc5ec9d6a723a007d105"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "distlib" +version = "0.3.8" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, +] + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "platformdirs" +version = "4.2.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pyproject-api" +version = "1.6.1" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + +[package.dependencies] +packaging = ">=23.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] [[package]] name = "pyre2" @@ -138,6 +258,64 @@ files = [ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, ] +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "tox" +version = "4.13.0" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tox-4.13.0-py3-none-any.whl", hash = "sha256:1143c7e2489c68026a55d3d4ae84c02c449f073b28e62f80e3e440a3b72a4afa"}, + {file = "tox-4.13.0.tar.gz", hash = "sha256:dd789a554c16c4b532924ba393c92fc8991323c4b3d466712bfecc8c9b9f24f7"}, +] + +[package.dependencies] +cachetools = ">=5.3.2" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.13.1" +packaging = ">=23.2" +platformdirs = ">=4.1" +pluggy = ">=1.3" +pyproject-api = ">=1.6.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.25" + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.25.2)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.11)"] +testing = ["build[virtualenv] (>=1.0.3)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.2)", "devpi-process (>=1)", "diff-cover (>=8.0.2)", "distlib (>=0.3.8)", "flaky (>=3.7)", "hatch-vcs (>=0.4)", "hatchling (>=1.21)", "psutil (>=5.9.7)", "pytest (>=7.4.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-xdist (>=3.5)", "re-assert (>=1.1)", "time-machine (>=2.13)", "wheel (>=0.42)"] + +[[package]] +name = "virtualenv" +version = "20.25.1" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.25.1-py3-none-any.whl", hash = "sha256:961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a"}, + {file = "virtualenv-20.25.1.tar.gz", hash = "sha256:e08e13ecdca7a0bd53798f356d5831434afa5b07b93f0abdf0797b7a06ffe197"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<5" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + [extras] re2 = ["pyre2"] re2-wheels = ["pyre2-updated"] @@ -145,4 +323,4 @@ re2-wheels = ["pyre2-updated"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "ce9e87f85bc36cab5115844de702e0792e15b9074dd404bcca80c960bf249d14" +content-hash = "a69775d7aff74d5cbea494870994d138b40bd886fad83fbe3889b6a6c2d1f3b7" diff --git a/pyproject.toml b/pyproject.toml index 18d3786..37ab719 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -155,6 +155,12 @@ python = "^3.8" # 3.8 end-of-life 2024-10 pyre2 = { version = "^0.3.6", optional = true } pyre2-updated = { version = "^0.3.8", optional = true } +[tool.poetry.group.testing] +optional = true + +[tool.poetry.group.testing.dependencies] +tox = "^4.13.0" + [tool.poetry.extras] re2 = ["pyre2"] re2-wheels = ["pyre2-updated"] diff --git a/release.toml b/release.toml new file mode 100644 index 0000000..ab3ce41 --- /dev/null +++ b/release.toml @@ -0,0 +1,90 @@ +# git-cliff ~ GitHub release notes configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# changelog header +header = """ +## Release notes\n +""" +# template for release notes body +# https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing s +trim = true +# postprocessors +postprocessors = [ + { pattern = '', replace = "https://github.com/dupuy/reliabot/" }, # replace repository URL +] + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # Replace issue numbers + { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))" }, + # Check spelling of the commit with https://github.com/crate-ci/typos + # If the spelling is incorrect, it will be automatically fixed. + # { pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "🚀 Features" }, + { message = "^fix: auto-fixes", skip = true }, + { message = "^fix", group = "🔨 Fixes" }, + { message = "^doc", group = "📚 Documentation" }, + { message = "^perf", group = "⚡ Performance" }, + { message = "^refactor", group = "🚜 Refactor" }, + { message = "^style", skip = true }, + { message = "^test", skip = true }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore: pre-commit", skip = true }, + { message = "^chore|^ci", skip = true }, + { body = ".*security", group = "🛡️ Security" }, + { message = "^revert", group = "⏪️ Revert" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = true +# filter out the commits that are not matched by commit parsers +filter_commits = false +# regex for matching git tags +# tag_pattern = "v[0-9].*" +# regex for skipping tags +# skip_tags = "" +# regex for ignoring tags +ignore_tags = "-(alpha|beta|rc)" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" +# limit the number of commits included in the changelog. +# limit_commits = 42