Skip to content

chore: pre-commit.ci autoupdate #218

chore: pre-commit.ci autoupdate

chore: pre-commit.ci autoupdate #218

Workflow file for this run

# This workflow runs for pull requests and pushes (merge/squash/rebase or tags).
# The TESTS job always runs, installing Python Poetry dependencies, building a
# distribution and running tests on a matrix of Python versions. It also
# computes several outputs for use by other jobs, often in 'if' conditions.
#
# The first output (VERSION_TAG) describes the intended Reliabot version, which
# can be the current tag, but is usually a desired (pre-)release tag for this
# workflow to apply, or the "left over" version of the most recent release tag.
# All outputs are set as environment variables in the jobs that use them, but
# this one uses underscore '_' rather than hyphen '-' in its name so that shell
#'run' scripts can use it as an environment variable rather than as a '${{ }}'
# substitution that would be vulnerable to shell meta-characters in the value.
# Although TESTS uses `poetry version` to get this value from 'pyproject.toml',
# and poetry rejects metacharacters in the version, it's still worth having
# m shell-compatible name to protect against a compromised action or workflow
# exploiting this environment variable by overriding the poetry-computed value.
#
# THe TESTS job uses `git describe` to compute another variable (COMMIT_TAG)
# that is not an output. Its value can be the current VERSION_TAG ("v1.2.3") or
# a previous VERSION_TAG followed by '-', the number of commits made since, and
# a short commit hash, like this: 'v1.2.3-13-ca11ab1e'. The latter indicates an
# "interim" (untagged) commit, and can be distinguished from a pre-release tag
# like `v1.2.3-rc.5' by the presence of a second '-'.
#
# The TESTS job uses these two variables to determine the type of push (merge)
# or pull request the workflow is handling, and creates "pr-*" outputs for other
# jobs to use in 'if' conditions to enable execution of various job steps.
#
# * pr-commit :: COMMIT_TAG != VERSION_TAG
# * pr-release :: VERSION_TAG has no '-'
# * pr-tag :: COMMIT_TAG does not start with VERSION_TAG + '-'
#
# [The pr-tag test uses '-' to prevent 'v1.2.10' starts with 'v1.2.1' mistakes.]
#
# - Tag push: pr-commit=false pr-release=false pr-tag=false (take no action)
# - "Interim" PR: pr-commit=true pr-release=false pr-tag=false (no tag/release)
# - Pre-release: pr-commit=true pr-release=false pr-tag=true (tag + TestPyPI)
# - Release: pr-commit=true pr-release=true pr-tag=true (annotated + PyPI)
#
# [Only releases use annotated tags so `git describe` ignores pre-releases.]
# [Also note pr-tag=true implies pr-commit=true so latter test may be omitted.]
#
# The TESTS job also computes two other outputs to coordinate (upload/download)
# between the pull_request and push workflows, and the jobs within them:
#
# - artifact-name - GitHub artifact containing dist/ release for publishing
# - release-name - GitHub title of release or pre-release
# Since only the last matrix instance output is available, and there's no way to
# know which one that is, all matrix instances compute the outputs.
#
# All other jobs run only on one or the other of pull_request or push events:
#
# pull_request: build → draft-release, test-publish
# push: pre-release || ( publish → release )
# The BUILD job creates a Python package release, release notes, and a full
# changelog, uploading them as artifacts for other pull_request and push jobs.
# The lifetime of these artifacts is linked to the "stale" workflow that closes
# inactive PRs. By closing PRs before their artifacts expire, the stale workflow
# prevents push workflow failures. The pull_request workflow runs on "reopen"
# or "ready for review" events, recreating expired artifacts before any "push".
# The DRAFT-RELEASE job creates a draft GitHub release (or pre-release, if the
# version tag contains a '-').
# The TEST-PUBLISH job publishes the Python package from the uploaded build
# artifact to TestPyPI; it does this for both pre-release and release builds.
# The jobs that run on push events are different for pre-releases and releases:
# The PRE-RELEASE job removes the draft status from the GitHub release, and
# creates and pushes a corresponding non-annotated tag for the pre-release.
#
# The PUBLISH job runs for release versions and publishes the Python package
# from the uploaded build artifact to PyPI. It also creates and pushes an
# annotated tag for the release.
# The RELEASE job only removes the draft status from the GitHub release,
name: 'Test, build, release, upload, publish, and tag Python Poetry app'
env:
OUTPUT: dist/release-notes.md # from release.toml
on:
push:
branches: ['main']
pull_request:
branches: ['main']
types:
- opened
- ready_for_review
- reopened
- synchronize
permissions:
contents: read
jobs:
tests:
runs-on: ubuntu-22.04
outputs:
VERSION_TAG: ${{ steps.computed.outputs.VERSION_TAG }}
artifact-name: ${{ steps.computed.outputs.artifact-name }}
pr-commit: ${{ steps.computed.outputs.pr-commit }}
pr-release: ${{ steps.computed.outputs.pr-release }}
pr-tag: ${{ steps.computed.outputs.pr-tag }}
release-name: ${{ steps.computed.outputs.release-name }}
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@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
files.pythonhosted.org:443
github.com:443
pypi.org:443
- name: 'Checkout repository'
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
# The `git describe` COMMIT_TAG output requires these fetch-* options.
fetch-depth: 0
fetch-tags: true
persist-credentials: false
- name: 'Install Poetry'
run: 'pipx install poetry'
- name: 'Compute outputs for other jobs'
id: computed
run: >
{
COMMIT_TAG=$(git describe) &&
echo "COMMIT_TAG=$COMMIT_TAG" >&2 ;
VERSION_TAG="v`poetry version --short |
sed -e 's/a/-alpha./' -e 's/b/-beta./' -e 's/rc/-rc./'`" &&
echo "VERSION_TAG=$VERSION_TAG" ;
case "$COMMIT_TAG" in
*-[abr]*-[1-9]*-*)
exec >&2
echo "The COMMIT_TAG that 'git describe' created is based on" ;
echo "a pre-release tag, which prevents proper generation" ;
echo "of new releases!" ;
echo "Make sure git describe is not using --tags, and use" ;
echo "'git show' to check if the pre-release base tag is" ;
echo "an annotated tag like release tags."
exit 1 ;;
${VERSION_TAG})
echo "artifact-name=" ;
echo "pr-commit=false" ; echo "pr-tag=false" ;
echo "pr-release=false" ; echo "release-name=" ;;
${VERSION_TAG}-*)
echo "artifact-name=" ;
echo "pr-commit=true" ; echo "pr-tag=false" ;
echo "pr-release=false" ; echo "release-name=" ;;
*)
echo "artifact-name=dist-reliabot-$VERSION_TAG" ;
echo "pr-commit=true" ; echo "pr-tag=true" ;
case "$VERSION_TAG" in
*-*)
echo "pr-release=false" ;
echo "release-name=Pre-release $VERSION_TAG" ;;
*)
echo "pr-release=true" ;
echo "release-name=Release $VERSION_TAG" ;;
esac ;
esac ;
} | tee -a "$GITHUB_OUTPUT"
- name: 'Set up Python'
if: steps.computed.outputs.pr-commit == 'true'
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
with:
python-version: '${{ matrix.python-version }}'
cache: 'poetry'
- name: 'Install dependencies'
if: steps.computed.outputs.pr-commit == 'true'
run: 'poetry install --extras re2-wheels --with testing'
- name: 'Run tests with coverage'
if: steps.computed.outputs.pr-commit == 'true'
run: 'poetry run tox -e py'
build:
runs-on: ubuntu-22.04
# No build for push events, which use artifacts from pull_request
if: github.event_name == 'pull_request'
env:
VERSION_TAG: ${{ needs.tests.outputs.VERSION_TAG }}
artifact-name: ${{ needs.tests.outputs.artifact-name }}
pr-commit: ${{ needs.tests.outputs.pr-commit }}
pr-release: ${{ needs.tests.outputs.pr-release }}
pr-tag: ${{ needs.tests.outputs.pr-tag }}
needs:
- tests
steps:
- name: 'Harden runner'
if: env.pr-commit == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
files.pythonhosted.org:443
github.com:443
pypi.org:443
- name: 'Checkout repository'
if: env.pr-commit == 'true'
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
# The `git-cliff` release notes action requires these fetch-* options.
fetch-depth: 0
fetch-tags: true
persist-credentials: false
- name: 'Install Poetry'
if: env.pr-commit == 'true'
run: 'pipx install poetry'
- name: 'Set up Python'
if: env.pr-commit == 'true'
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
with:
python-version: '>=3.9 <3.13'
cache: 'poetry'
- name: 'Build distribution packages'
if: env.pr-commit == 'true'
run: 'poetry build'
- name: 'Generate release notes'
if: env.pr-tag == 'true'
uses: orhun/git-cliff-action@8b17108aad4d9362649a5dae020746c2a767c90d # v3.0.2
with:
args: >
'--unreleased'
'--tag=${{ env.VERSION_TAG }}'
config: release.toml
- name: 'Generate "unreleased" notes'
if: env.pr-commit == 'true' && env.pr-tag == 'false'
uses: orhun/git-cliff-action@8b17108aad4d9362649a5dae020746c2a767c90d # v3.0.2
with:
args: '--unreleased'
config: release.toml
- name: 'Upload distribution package as an artifact'
if: github.repository == 'dupuy/reliabot' && env.pr-tag == 'true'
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
if-no-files-found: error
name: '${{ env.artifact-name }}'
overwrite: true
path: 'dist/*'
retention-days: 90 # stale + close + 13 <= artifact retention (90 max)
draft-release:
runs-on: ubuntu-22.04
# No draft for push; that uses artifact and draft release from pull_request.
if: >
github.event_name == 'pull_request' &&
github.repository == 'dupuy/reliabot'
env:
VERSION_TAG: ${{ needs.tests.outputs.VERSION_TAG }}
artifact-name: ${{ needs.tests.outputs.artifact-name }}
pr-release: ${{ needs.tests.outputs.pr-release }}
pr-tag: ${{ needs.tests.outputs.pr-tag }}
release-name: ${{ needs.tests.outputs.release-name }}
needs:
- build
- tests
permissions:
contents: write
steps:
- name: 'Harden runner'
if: env.pr-tag == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
uploads.github.com:443
- name: 'Download release artifacts'
if: env.pr-tag == 'true'
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: '${{ env.artifact-name }}'
path: dist/
- name: 'Create draft release and upload artifacts'
if: env.pr-tag == 'true'
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with:
allowUpdates: true
artifactErrorsFailBuild: true
artifacts: dist/*
bodyFile: '${{ env.OUTPUT }}'
draft: true
name: '${{ env.release-name }}'
prerelease: "${{ env.pr-release && 'false' || 'true' }}"
tag: '${{ env.VERSION_TAG }}'
updateOnlyUnreleased: true
test-publish:
runs-on: ubuntu-22.04
if: >
github.event_name == 'pull_request' &&
github.repository == 'dupuy/reliabot'
env:
artifact-name: ${{ needs.tests.outputs.artifact-name }}
pr-tag: ${{ needs.tests.outputs.pr-tag }}
needs:
- build
- tests
environment:
name: test-pypi
url: https://test.pypi.org/p/reliabot
permissions:
id-token: write # IMPORTANT: trusted publishing requires this permission
steps:
- name: 'Harden runner'
if: env.pr-tag == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: audit
allowed-endpoints: >
upload.pypi.org:443
- name: 'Download release artifacts'
if: env.pr-tag == 'true'
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: '${{ env.artifact-name }}'
path: dist/
- name: 'Publish (pre-)release to TestPyPI'
if: env.pr-tag == 'true'
uses: pypa/gh-action-pypi-publish@81e9d935c883d0b210363ab89cf05f3894778450 # v1.8.14
publish:
runs-on: ubuntu-22.04
if: github.event_name == 'push' && github.repository == 'dupuy/reliabot'
env:
VERSION_TAG: ${{ needs.tests.outputs.VERSION_TAG }}
artifact-name: ${{ needs.tests.outputs.artifact-name }}
pr-release: ${{ needs.tests.outputs.pr-release }}
environment:
name: pypi
url: https://pypi.org/p/reliabot
needs:
- tests
permissions:
contents: write # Needed for annotated tag push
id-token: write # IMPORTANT: trusted publishing requires this permission
steps:
- name: 'Harden runner'
if: env.pr-release == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: audit
allowed-endpoints: >
github.com:443
upload.pypi.org:443
- name: 'Checkout repository'
if: env.pr-release == 'true'
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
# The Git repository is only necessary for tagging and pushing.
fetch-depth: 1
fetch-tags: true
persist-credentials: true
- name: 'Download release artifacts'
if: env.pr-release == 'true'
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: '${{ env.artifact-name }}'
path: dist/
- name: 'Create annotated tag for release'
if: env.pr-release == 'true'
run: |
git tag "$VERSION_TAG" -F "$OUTPUT" --cleanup=whitespace
git push --tags
- name: 'Publish release to PyPI'
if: env.pr-release == 'true'
uses: pypa/gh-action-pypi-publish@81e9d935c883d0b210363ab89cf05f3894778450 # v1.8.14
pre-release:
runs-on: ubuntu-22.04
if: github.event_name == 'push' && github.repository == 'dupuy/reliabot'
env:
VERSION_TAG: ${{ needs.tests.outputs.VERSION_TAG }}
pr-release: ${{ needs.tests.outputs.pr-release }}
pr-tag: ${{ needs.tests.outputs.pr-tag }}
needs:
- tests
permissions:
contents: write
steps:
- name: 'Harden runner'
if: env.pr-release == 'false' && env.pr-tag == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
- name: 'Publish GitHub pre-release'
if: env.pr-release == 'false' && env.pr-tag == 'true'
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with:
allowUpdates: true
commit: '${{ github.ref }}' # This only generates a non-annotated tag.
draft: false
omitBodyDuringUpdate: true
omitNameDuringUpdate: true
prerelease: true
replacesArtifacts: false
tag: '${{ env.VERSION_TAG }}'
updateOnlyUnreleased: true
release:
runs-on: ubuntu-22.04
if: github.event_name == 'push' && github.repository == 'dupuy/reliabot'
env:
VERSION_TAG: ${{ needs.tests.outputs.VERSION_TAG }}
pr-release: ${{ needs.tests.outputs.pr-release }}
pr-tag: ${{ needs.tests.outputs.pr-tag }}
needs:
- tests
permissions:
contents: write
steps:
- name: 'Harden runner'
if: env.pr-release == 'true'
uses: step-security/harden-runner@a4aa98b93cab29d9b1101a6143fb8bce00e2eac4 # v2.7.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
- name: 'Publish GitHub release'
if: env.pr-release == 'true'
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
with:
allowUpdates: true
# Don't set commit, publish job creates an annotated tag.
draft: false
omitBodyDuringUpdate: true
omitNameDuringUpdate: true
prerelease: false
replacesArtifacts: false
tag: '${{ env.VERSION_TAG }}'
updateOnlyUnreleased: true