diff --git a/.copier-answers.yml b/.copier-answers.yml index 57d15e9..1647786 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,6 +1,6 @@ # Autogenerated. Do not edit this by hand, use `copier update`. --- -_commit: 0.5.0 +_commit: 0.6.0 _src_path: https://github.com/salt-extensions/salt-extension-copier author: jeanluc author_email: lkubb@protonmail.com @@ -22,7 +22,7 @@ os_support: - Windows package_name: pushover project_name: pushover -python_requires: '3.8' +python_requires: '3.9' relax_pylint: false salt_version: '3006' source_url: https://github.com/salt-extensions/saltext-pushover diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7b529c1..e6298d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,13 +47,53 @@ jobs: - pre-commit uses: ./.github/workflows/docs-action.yml + check-prepare-release: + name: Check if we can prepare release PR + if: >- + github.event_name == 'push' && + github.ref == format('refs/heads/{0}', github.event.repository.default_branch) + needs: + - docs + - test + runs-on: ubuntu-24.04 + outputs: + news-fragments-available: ${{ steps.check-available.outputs.available }} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Check if news fragments are available + id: check-available + run: | + if [ -n "$(find changelog -type f -not -name '.*' -print -quit)" ]; then + echo "available=1" >> "$GITHUB_OUTPUT" + else + echo "available=0" >> "$GITHUB_OUTPUT" + fi + + prepare-release: + name: Prepare Release PR + if: ${{ needs.check-prepare-release.outputs.news-fragments-available == '1' }} + needs: + - check-prepare-release + - docs + - test + permissions: + contents: write + pull-requests: write + uses: ./.github/workflows/prepare-release-action.yml + deploy-docs: name: Deploy Docs uses: ./.github/workflows/deploy-docs-action.yml - # Only build doc deployments from the default branch of the repo and never for PRs. + # Only build doc deployments from the default branch of the repo and never for PRs, + # unless the triggering event was the release PR being merged. if: >- - github.event_name != 'pull_request' && inputs.deploy-docs && + ( + github.event_name != 'pull_request' || + inputs.release + ) && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) needs: - docs diff --git a/.github/workflows/deploy-docs-action.yml b/.github/workflows/deploy-docs-action.yml index d4bf10d..4a935b5 100644 --- a/.github/workflows/deploy-docs-action.yml +++ b/.github/workflows/deploy-docs-action.yml @@ -71,7 +71,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }} path: exitstatus diff --git a/.github/workflows/deploy-package-action.yml b/.github/workflows/deploy-package-action.yml index 9f1d6ba..3a702d7 100644 --- a/.github/workflows/deploy-package-action.yml +++ b/.github/workflows/deploy-package-action.yml @@ -30,7 +30,7 @@ jobs: path: dist - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@c44d2f0e52f028349e3ecafbf7f32561da677277 # v1.10.3 + uses: pypa/gh-action-pypi-publish@1bb664cc2ddedbbfdde43d4ac135d5836b7bf40f # v1.11.0 if: ${{ inputs.test }} with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} @@ -41,14 +41,14 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create "$GITHUB_REF_NAME" \ + gh release create "v${{ inputs.version }}" \ --repo="$GITHUB_REPOSITORY" \ --title="${GITHUB_REPOSITORY#*/} ${{ inputs.version }}" \ --generate-notes \ dist/* - name: Publish distribution to PyPI - uses: pypa/gh-action-pypi-publish@c44d2f0e52f028349e3ecafbf7f32561da677277 # v1.10.3 + uses: pypa/gh-action-pypi-publish@1bb664cc2ddedbbfdde43d4ac135d5836b7bf40f # v1.11.0 if: ${{ !inputs.test }} with: password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/docs-action.yml b/.github/workflows/docs-action.yml index 8a5c751..9e7775d 100644 --- a/.github/workflows/docs-action.yml +++ b/.github/workflows/docs-action.yml @@ -10,12 +10,12 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - name: Set up Python 3.10 For Nox - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: "3.10" @@ -35,7 +35,7 @@ jobs: nox --force-color -e docs - name: Upload built docs as artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: html-docs path: docs/_build/html @@ -48,7 +48,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }} path: exitstatus diff --git a/.github/workflows/get-changed-files.yml b/.github/workflows/get-changed-files.yml index 3e568c0..79e9498 100644 --- a/.github/workflows/get-changed-files.yml +++ b/.github/workflows/get-changed-files.yml @@ -17,7 +17,7 @@ jobs: changed-files: ${{ toJSON(steps.changed-files.outputs) }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get Changed Files id: changed-files diff --git a/.github/workflows/package-action.yml b/.github/workflows/package-action.yml index 818b1aa..472fa18 100644 --- a/.github/workflows/package-action.yml +++ b/.github/workflows/package-action.yml @@ -14,12 +14,12 @@ jobs: runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 - name: Set up Python 3.10 - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: "3.10" @@ -38,7 +38,7 @@ jobs: run: python -m build --outdir dist/ - name: Upload build artifacts - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 if: always() with: name: salt-extension-${{ inputs.version }}-packages @@ -53,7 +53,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }} path: exitstatus diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 403a722..64a9470 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -10,8 +10,42 @@ on: pull_request: jobs: + # After merging the release PR, we don't want to trigger + # this workflow in addition to the Tagged Releases one. + # This pauses CI on pushes to the main branch completely. + check_release_in_progress: + name: Skip CI While Releasing + runs-on: ubuntu-24.04 + if: github.event_name == 'push' + outputs: + count: ${{ steps.workflow_count.outputs.count }} + + steps: + - name: Count Running Release Workflows Triggered by Automated PR + id: workflow_count + env: + GH_TOKEN: ${{ github.token }} + run: | + count="$(gh run list \ + --repo "$GITHUB_REPOSITORY" \ + --event pull_request \ + --branch release/auto \ + --workflow 'Tagged Releases' \ + --json status \ + --jq 'map(select(.status == ("queued","in_progress"))) | length')" + echo "count=$count" >> "$GITHUB_OUTPUT" + call_central_workflow: name: CI + needs: + - check_release_in_progress + if: > + always() && + github.event_name != 'push' || + ( + needs.check_release_in_progress.result == 'success' && + needs.check_release_in_progress.outputs.count == '0' + ) uses: ./.github/workflows/ci.yml with: deploy-docs: true @@ -19,4 +53,4 @@ jobs: contents: write id-token: write pages: write - pull-requests: read + pull-requests: write diff --git a/.github/workflows/pre-commit-action.yml b/.github/workflows/pre-commit-action.yml index ebf639a..813992c 100644 --- a/.github/workflows/pre-commit-action.yml +++ b/.github/workflows/pre-commit-action.yml @@ -14,7 +14,7 @@ jobs: name: Pre-Commit runs-on: ubuntu-24.04 container: - image: docker.io/library/python:3.10.15-slim-bookworm@sha256:1eb5d76bf3e9e612176ebf5eadf8f27ec300b7b4b9a99f5856f8232fd33aa16e + image: docker.io/library/python:3.10.15-slim-bookworm@sha256:eb9ca77b1a0ffbde84c1dc333beb3490a2638813cc25a339f8575668855b9ff1 steps: - name: Install System Deps @@ -23,7 +23,7 @@ jobs: apt-get install -y enchant-2 git gcc make zlib1g-dev libc-dev libffi-dev g++ libxml2 libxml2-dev libxslt-dev libcurl4-openssl-dev libssl-dev libgnutls28-dev git config --global --add safe.directory "$(pwd)" - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install Pre-Commit run: | @@ -49,7 +49,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }} path: exitstatus diff --git a/.github/workflows/prepare-release-action.yml b/.github/workflows/prepare-release-action.yml new file mode 100644 index 0000000..f3c8f83 --- /dev/null +++ b/.github/workflows/prepare-release-action.yml @@ -0,0 +1,65 @@ +--- +name: Prepare Release PR + +on: + workflow_call: + workflow_dispatch: + inputs: + version: + description: Override the autogenerated version. + required: false + default: '' + type: string + +jobs: + update-release: + name: Render changelog and create/update PR + runs-on: ubuntu-24.04 + if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Set up Python 3.10 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + with: + python-version: '3.10' + + - name: Install project + run: | + python -m pip install --upgrade pip + python -m pip install '.[changelog]' pre-commit + + - name: Get next version + if: github.event_name == 'push' || inputs.version == '' + id: next-version + run: echo "version=$(python tools/version.py next)" >> "$GITHUB_OUTPUT" + + - name: Update CHANGELOG.md + env: + NEXT_VERSION: ${{ (github.event_name == 'workflow_dispatch' && inputs.version != '') && inputs.version || steps.next-version.outputs.version }} + run: towncrier build --yes --version "${NEXT_VERSION}" + + - name: Run pre-commit once to remove trailing whitespace + run: | + python -m pre_commit run --files=CHANGELOG.md || true + + - name: Create/update release PR + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5 + with: + commit-message: Release v${{ (github.event_name == 'workflow_dispatch' && inputs.version != '') && inputs.version || steps.next-version.outputs.version }} + branch: release/auto + sign-commits: true + title: Release v${{ (github.event_name == 'workflow_dispatch' && inputs.version != '') && inputs.version || steps.next-version.outputs.version }} + body: | + This automated PR builds the latest changelog. When merged, a new release is published automatically. + + Before merging, please ensure it's based on the most recent default branch HEAD. + + If you want to rebuild this PR with a custom version or the current date, you can also trigger the corresponding workflow manually in `Actions` > `Prepare Release PR` > `Run workflow`. + + You can still follow the manual release procedure outlined in: https://salt-extensions.github.io/salt-extension-copier/topics/publishing.html diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 33eded8..d673287 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -5,30 +5,124 @@ on: push: tags: - "v*" # Only tags starting with "v" for "v1.0.0", etc. + pull_request: + types: + - closed + paths: + - CHANGELOG.md jobs: - get_tag_version: + get_version_tag: + name: Extract version from tag runs-on: ubuntu-24.04 + if: github.event_name == 'push' outputs: - version: ${{ steps.get_version.outputs.version }} + version: ${{ steps.get_version_tag.outputs.version }} + steps: - name: Checkout code - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Extract tag name - id: get_version + id: get_version_tag run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" + - name: Ensure changelog was rendered + run: | + test "${{ steps.get_version_tag.outputs.version }}" = "$(python tools/version.py)" && \ + test -z "$(find changelog -type f -not -name '.*' -print -quit)" + + close_autopr_on_tag: + name: Close release PR on manual tag + runs-on: ubuntu-24.04 + if: github.event_name == 'push' + needs: + - get_version_tag + + steps: + - name: Find Pull Request + uses: juliangruber/find-pull-request-action@2f36c5fe1abfda4745dfab4f38217ebad8ded4eb # v1.9.0 + id: find-pull-request + with: + branch: release/auto + base: ${{ github.event.repository.default_branch }} + state: open + + - name: Close release PR + if: steps.find-pull-request.outputs.number != '' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr close \ + --comment "This release was triggered manually as v${{ needs.get_version_tag.outputs.version }}" \ + --delete-branch \ + --repo "$GITHUB_REPOSITORY" \ + "${{ steps.find-pull-request.outputs.number }}" + + get_version_pr: + name: Extract version from merged release PR + runs-on: ubuntu-24.04 + permissions: + contents: write # To push the new tag. This does not cause a tag event. + + # Only trigger this on closed pull requests if: + # - The originating branch is from the same repository as the one running this workflow. + # - The originating branch is called `release/auto` + # - The PR was merged, not just closed. + # - The PR targeted the default branch of the repository this workflow is running from. + if: >- + github.event_name == 'pull_request' && + github.repository == github.event.pull_request.head.repo.full_name && + github.head_ref == 'release/auto' && + github.event.pull_request.merged == true && + github.base_ref == github.event.repository.default_branch + + outputs: + version: ${{ steps.get_version_pr.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Extract version of merged release PR + id: get_version_pr + run: echo "version=$(python tools/version.py)" >> "$GITHUB_OUTPUT" + + - name: Ensure no news fragments are left + run: test -z "$(find changelog -type f -not -path '*/.*' -print -quit)" + + - name: Check extracted version matches PR title + env: + TITLE: ${{ github.event.pull_request.title }} + run: >- + [[ "$TITLE" == "Release v${{ steps.get_version_pr.outputs.version }}" ]] || exit 1 + + - name: Create tag for release + uses: mathieudutour/github-tag-action@d28fa2ccfbd16e871a4bdf35e11b3ad1bd56c0c1 # v6.2 + with: + github_token: ${{ github.token }} + custom_tag: ${{ steps.get_version_pr.outputs.version }} + create_annotated_tag: true + call_central_workflow: - needs: get_tag_version + # Only call the central workflow if either of the above jobs report success. + if: >- + always() && + ( + needs.get_version_tag.result == 'success' || + needs.get_version_pr.result == 'success' + ) + needs: + - get_version_tag + - get_version_pr uses: ./.github/workflows/ci.yml with: deploy-docs: true release: true - version: ${{ needs.get_tag_version.outputs.version }} + version: ${{ github.event_name == 'push' && needs.get_version_tag.outputs.version || needs.get_version_pr.outputs.version }} permissions: contents: write id-token: write pages: write - pull-requests: read + pull-requests: write secrets: inherit diff --git a/.github/workflows/test-action.yml b/.github/workflows/test-action.yml index 88242f3..e257bf4 100644 --- a/.github/workflows/test-action.yml +++ b/.github/workflows/test-action.yml @@ -12,21 +12,20 @@ jobs: strategy: fail-fast: false - max-parallel: 4 + max-parallel: 3 matrix: include: - - {salt-version: "3006.9", python-version: "3.8"} - {salt-version: "3006.9", python-version: "3.9"} - {salt-version: "3006.9", python-version: "3.10"} - {salt-version: "3007.1", python-version: "3.10"} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 # coverage: Issue detecting commit SHA - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: ${{ matrix.python-version }} @@ -63,7 +62,7 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},project name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-project use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Tests Code Coverage uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 @@ -74,11 +73,11 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},tests name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-tests use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Logs if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: runtests-${{ runner.os }}-py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}.log path: artifacts/runtests-*.log @@ -91,7 +90,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }} path: exitstatus @@ -106,31 +105,19 @@ jobs: max-parallel: 2 matrix: include: - - {salt-version: "3006.9", python-version: "3.8"} - - {salt-version: "3007.1", python-version: "3.8"} + - {salt-version: "3006.9", python-version: "3.9"} + - {salt-version: "3007.1", python-version: "3.9"} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: ${{ matrix.python-version }} - - name: Download libeay32.dll - run: | - PY_LOC="$(which python.exe)" - export PY_LOC - echo "${PY_LOC}" - PY_DIR="$(dirname "${PY_LOC}")" - export PY_DIR - echo "${PY_DIR}" - curl https://repo.saltproject.io/windows/dependencies/64/libeay32.dll --output "${PY_DIR}/libeay32.dll" - ls -l "${PY_DIR}" - shell: bash - - name: Install Nox run: | python -m pip install --upgrade pip @@ -169,7 +156,7 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},project name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-project use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Tests Code Coverage uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 @@ -180,11 +167,11 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},tests name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-tests use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Logs if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: runtests-${{ runner.os }}-py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}.log path: artifacts/runtests-*.log @@ -197,7 +184,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }} path: exitstatus @@ -212,16 +199,16 @@ jobs: max-parallel: 2 matrix: include: - - {salt-version: "3006.9", python-version: "3.9"} + - {salt-version: "3006.9", python-version: "3.10"} - {salt-version: "3007.1", python-version: "3.10"} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 with: python-version: ${{ matrix.python-version }} @@ -258,7 +245,7 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},project name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-project use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Tests Code Coverage uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 @@ -269,11 +256,11 @@ jobs: flags: ${{ steps.codecov-flags.outputs.flags }},tests name: ${{ runner.os }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}-tests use_oidc: true - version: v0.7.5 + version: v0.8.0 - name: Upload Logs if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: runtests-${{ runner.os }}-py${{ matrix.python-version }}-Salt${{ matrix.salt-version }}.log path: artifacts/runtests-*.log @@ -286,7 +273,7 @@ jobs: - name: Upload Exit Status if: always() - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: exitstatus-${{ github.job }}-Py${{ matrix.python-version }}-Salt${{ matrix.salt-version }} path: exitstatus diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a26ad54..d8262cf 100755 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,9 +59,9 @@ repos: rev: 32151ac97cbfd7f9dcd22e49516fb32266db45b4 # v3.16.0 hooks: - id: pyupgrade - name: Rewrite Code to be Py3.8+ + name: Rewrite Code to be Py3.9+ args: [ - --py38-plus, + --py39-plus, ] exclude: src/saltext/pushover/version.py @@ -70,25 +70,25 @@ repos: hooks: - id: isort args: [ - --py 38, + --py 39, ] exclude: src/saltext/pushover/(__init__|version).py - repo: https://github.com/psf/black - rev: b965c2a5026f8ba399283ba3e01898b012853c79 # 24.8.0 + rev: 1b2427a2b785cc4aac97c19bb4b9a0de063f9547 # 24.10.0 hooks: - id: black args: [-l 100] exclude: src/saltext/pushover/version.py - repo: https://github.com/adamchainz/blacken-docs - rev: 4c97c4a0d921007af6fefae92d8447cfbf63720b # 1.18.0 + rev: 78a9dcbecf4f755f65d1f3dec556bc249d723600 # 1.19.1 hooks: - id: blacken-docs args: [--skip-errors] files: ^(docs/.*\.rst|src/saltext/pushover/.*\.py)$ additional_dependencies: - - black==24.8.0 + - black==24.10.0 # <---- Formatting ----------------------------------------------------------------------------- # ----- Security ------------------------------------------------------------------------------> @@ -123,8 +123,8 @@ repos: files: ^((setup|noxfile)|src/.*)\.py$ require_serial: true additional_dependencies: - - nox==2024.4.15 - - uv==0.4.18 # Makes this hook much faster + - nox==2024.10.9 + - uv==0.4.29 # Makes this hook much faster - id: nox alias: lint-tests @@ -134,8 +134,8 @@ repos: files: ^tests/.*\.py$ require_serial: true additional_dependencies: - - nox==2024.4.15 - - uv==0.4.18 # Makes this hook much faster + - nox==2024.10.9 + - uv==0.4.29 # Makes this hook much faster - repo: https://github.com/Mateusz-Grzelinski/actionlint-py rev: 27445053da613c660ed5895d9616662059a53ca7 # v1.7.3.17 diff --git a/.pylintrc b/.pylintrc index b304cb9..9891565 100755 --- a/.pylintrc +++ b/.pylintrc @@ -93,7 +93,7 @@ prefer-stubs=no # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.8 +py-version=3.9 # Discover python modules and packages in the file system subtree. recursive=no diff --git a/noxfile.py b/noxfile.py index db57e0a..0d4551e 100755 --- a/noxfile.py +++ b/noxfile.py @@ -21,7 +21,7 @@ nox.options.default_venv_backend = "uv|virtualenv" # Python versions to test against -PYTHON_VERSIONS = ("3", "3.8", "3.9", "3.10") +PYTHON_VERSIONS = ("3", "3.9", "3.10") # Be verbose when running under a CI context CI_RUN = ( os.environ.get("JENKINS_URL") or os.environ.get("CI") or os.environ.get("DRONE") is not None @@ -30,7 +30,7 @@ SKIP_REQUIREMENTS_INSTALL = os.environ.get("SKIP_REQUIREMENTS_INSTALL", "0") == "1" EXTRA_REQUIREMENTS_INSTALL = os.environ.get("EXTRA_REQUIREMENTS_INSTALL") -COVERAGE_REQUIREMENT = os.environ.get("COVERAGE_REQUIREMENT") or "coverage==7.6.1" +COVERAGE_REQUIREMENT = os.environ.get("COVERAGE_REQUIREMENT") or "coverage==7.6.4" SALT_REQUIREMENT = os.environ.get("SALT_REQUIREMENT") or "salt>=3006" if SALT_REQUIREMENT == "salt==master": SALT_REQUIREMENT = "git+https://github.com/saltstack/salt.git@master" @@ -72,8 +72,8 @@ def _get_session_python_version_info(session): def _get_pydir(session): version_info = _get_session_python_version_info(session) - if version_info < (3, 8): - session.error("Only Python >= 3.8 is supported") + if version_info < (3, 9): + session.error("Only Python >= 3.9 is supported") return f"py{version_info[0]}.{version_info[1]}" diff --git a/pyproject.toml b/pyproject.toml index 8717665..f1c8031 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,14 +25,13 @@ classifiers = [ "Programming Language :: Cython", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", ] -requires-python = ">= 3.8" +requires-python = ">= 3.9" dynamic = ["version"] dependencies = [ "salt>=3006", @@ -117,6 +116,11 @@ underlines = ["", "", ""] title_format = "## {version} ({project_date})" issue_format = "[#{issue}](https://github.com/salt-extensions/saltext-pushover/issues/{issue})" +[[tool.towncrier.type]] +directory = "breaking" +name = "Breaking changes" +showcontent = true + [[tool.towncrier.type]] directory = "removed" name = "Removed" diff --git a/tools/version.py b/tools/version.py new file mode 100644 index 0000000..d79b1f7 --- /dev/null +++ b/tools/version.py @@ -0,0 +1,92 @@ +""" +Very simple heuristic to generate the next version number +based on the current changelog news fragments. + +This looks for the most recent version by parsing the +CHANGELOG.md file and increments a specific part, +depending on the fragment types present and their contents. + +Major bumps are caused by: + * files named `.removed.md` + * files named `.breaking.md` + * files containing `BREAKING:` + +Minor bumps are caused by: + * files named `.added.md` + +Otherwise, only the patch version is bumped. +""" + +import re +import sys +from pathlib import Path + +PROJECT_ROOT = Path(".").resolve() +CHANGELOG_DIR = PROJECT_ROOT / "changelog" +CHANGELOG_FILE = PROJECT_ROOT / "CHANGELOG.md" + + +class Version: + def __init__(self, version): + match = re.search(r"v?(?P[0-9]+(?:\.[0-9]+)*)", version) + if not match: + raise ValueError(f"Invalid version: '{version}'") + self.release = tuple(int(i) for i in match.group("release").split(".")) + + @property + def major(self): + return self._ret(0) + + @property + def minor(self): + return self._ret(1) + + @property + def patch(self): + return self._ret(2) + + def __str__(self): + return ".".join(str(i) for i in self.release) + + def _ret(self, cnt): + try: + return self.release[cnt] + except IndexError: + return 0 + + +def last_release(): + for line in CHANGELOG_FILE.read_text(encoding="utf-8").splitlines(): + if line.startswith("## "): + return Version(line.split(" ")[1]) + return Version("0.0.0") + + +def get_next_version(last): + major = minor = False + + for fragment in CHANGELOG_DIR.glob("[!.]*"): + name = fragment.name.lower() + if ".added" in name: + minor = True + elif ".breaking" in name or ".removed" in name: + major = True + break + if "breaking:" in fragment.read_text(encoding="utf-8").lower(): + major = True + break + if major: + return Version(f"{last.major + 1}.0.0") + if minor: + return Version(f"{last.major}.{last.minor + 1}.0") + return Version(f"{last.major}.{last.minor}.{last.patch + 1}") + + +if __name__ == "__main__": + try: + if sys.argv[1] == "next": + print(get_next_version(last_release())) + raise SystemExit(0) + except IndexError: + pass + print(last_release())