diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e7d1d6..58e6b18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,9 @@ name: CI on: + workflow_dispatch: push: - branches: [main, master] + branches: [main] pull_request: permissions: read-all @@ -18,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml index e59adee..b9f0db9 100644 --- a/.github/workflows/prepare_release.yml +++ b/.github/workflows/prepare_release.yml @@ -3,48 +3,18 @@ on: workflow_dispatch: inputs: version: - description: 'The version to prepare for release' + description: The version to prepare for release required: true permissions: contents: read - pull-requests: write jobs: prepare_release: - name: Prepare Release v${{ github.event.inputs.version }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - ssh-key: ${{ secrets.SSH_DEPLOY_KEY }} - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - cache: pip - python-version: 3.x - - name: Install dependencies - run: pip install packaging - - name: Prepare Git Variables - run: | - git config --global author.email ${{ github.actor }}@users.noreply.github.com - git config --global author.name ${{ github.actor }} - git config --global committer.email noreply@github.com - git config --global committer.name GitHub - - name: Set desired version - run: | - tools/set_version.py ${{ github.event.inputs.version }} > tmp_version - echo "version=$(cat tmp_version)" >> $GITHUB_ENV - - name: Commit desired version - run: git commit -am "Bump to v${{ env.version }}" - - name: Set development version - run: | - tools/set_version.py Unreleased > tmp_version - echo "dev_version=$(cat tmp_version)" >> $GITHUB_ENV - rm tmp_version - - name: Commit development version - run: git commit -am "Set development version v${{ env.dev_version }}" - - name: Create Pull Request - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 - with: - body: - branch: prepare_release_v${{ env.version }} - draft: false - title: Release v${{ env.version }} + name: Prepare Release + secrets: + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + uses: praw-dev/.github/.github/workflows/prepare_release.yml@9ff8957d0cab4cf8c9d7cb5592aedb3d456cc058 # v1.4.0 + with: + package: codesorter + version: ${{ inputs.version }} + version_file: const.py diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index fe0778f..1632c93 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -8,7 +8,7 @@ on: schedule: - cron: '36 1 * * 3' push: - branches: ["main", "master"] + branches: ["main"] permissions: read-all jobs: analysis: diff --git a/.github/workflows/tag_release.yml b/.github/workflows/tag_release.yml new file mode 100644 index 0000000..ca406a9 --- /dev/null +++ b/.github/workflows/tag_release.yml @@ -0,0 +1,10 @@ +name: Tag Release +on: + push: + branches: [main] +permissions: + contents: write +jobs: + tag_release: + name: Tag Release + uses: praw-dev/.github/.github/workflows/tag_release.yml@9ff8957d0cab4cf8c9d7cb5592aedb3d456cc058 # v1.4.0 diff --git a/CHANGES.rst b/CHANGES.rst index 0ba324f..6516a86 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,8 @@ Change Log ############ +codesorter follows `semantic versioning `_. + ************ Unreleased ************ diff --git a/pyproject.toml b/pyproject.toml index ef1041b..395502b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Code Generators", "Topic :: Software Development :: Quality Assurance", "Topic :: Utilities" @@ -175,28 +176,13 @@ ban-relative-imports = "all" "S101", # pytest tests use assert "SLF001" ] -"tools/*.py" = [ - "ANN", # release scripts are short procedural shell-style code - "D", # release scripts are not part of the public docs surface - "DTZ", # naive dates are intentional (changelog dates) - "EM", # release scripts speak directly to stderr - "INP", # tools/ is a script folder, not a package - "PLR", # release scripts have simple linear flow - "PLW1514", # default encoding is fine for release scripts - "PTH", # plain open() is fine for release scripts - "RET503", # implicit None return is fine for release scripts - "RUF", # release scripts intentionally use simple constructs - "S", # subprocess/asserts are fine in maintenance scripts - "T20", # print is the script's primary output channel - "TRY" # release scripts use simple error reporting -] [tool.tomlsort] sort_inline_tables = true sort_table_keys = true [tool.tox] -envlist = ["py310", "py311", "py312", "py313", "pre-commit", "type"] +envlist = ["py310", "py311", "py312", "py313", "py314", "pre-commit", "type"] minversion = "4.22" [tool.tox.env.pre-commit] diff --git a/tools/__init__.py b/tools/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tools/bump_version.py b/tools/bump_version.py deleted file mode 100755 index 1fc0d1c..0000000 --- a/tools/bump_version.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 -"""Extract the version string from a 'Bump to v' commit message on stdin.""" - -import sys - -COMMIT_PREFIX = "Bump to v" - - -def main(): - line = sys.stdin.readline() - if not line.startswith(COMMIT_PREFIX): - sys.stderr.write(f"Commit message does not begin with `{COMMIT_PREFIX}`.\nMessage:\n\n{line}") - return 1 - print(line[len(COMMIT_PREFIX) : -1]) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/set_version.py b/tools/set_version.py deleted file mode 100755 index f78dad2..0000000 --- a/tools/set_version.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -"""Set or bump the package version. - -Usage: - tools/set_version.py # release: write the given version and date - tools/set_version.py Unreleased # post-release: add Unreleased header and bump dev - -""" - -import re -import sys -from datetime import date - -import packaging.version - -CHANGELOG_HEADER = "############\n Change Log\n############\n\n" -UNRELEASED_HEADER = "************\n Unreleased\n************\n\n" -VERSION_FILE = "codesorter/const.py" - - -def add_unreleased_to_changelog(): - with open("CHANGES.rst") as fp: - content = fp.read() - - if not content.startswith(CHANGELOG_HEADER): - sys.stderr.write("Unexpected CHANGES.rst header\n") - return False - new_header = f"{CHANGELOG_HEADER}{UNRELEASED_HEADER}" - if content.startswith(new_header): - sys.stderr.write("CHANGES.rst already contains Unreleased header\n") - return False - - with open("CHANGES.rst", "w") as fp: - fp.write(f"{new_header}{content[len(CHANGELOG_HEADER) :]}") - return True - - -def handle_unreleased(): - return add_unreleased_to_changelog() and increment_development_version() - - -def handle_version(version): - version = valid_version(version) - if not version: - return False - return update_changelog(version) and update_package(version) - - -def increment_development_version(): - with open(VERSION_FILE) as fp: - version = re.search('__version__ = "([^"]+)"', fp.read()).group(1) - - parsed_version = valid_version(version) - if not parsed_version: - return False - - if parsed_version.is_devrelease: - pre = "".join(str(x) for x in parsed_version.pre) if parsed_version.pre else "" - new_version = f"{parsed_version.base_version}{pre}.dev{parsed_version.dev + 1}" - elif parsed_version.is_prerelease: - new_version = f"{parsed_version}.dev0" - else: - assert parsed_version.base_version == version - new_version = f"{parsed_version.major}.{parsed_version.minor}.{parsed_version.micro + 1}.dev0" - - assert valid_version(new_version) - return update_package(new_version) - - -def main(): - if len(sys.argv) != 2: - sys.stderr.write(f"Usage: {sys.argv[0]} VERSION\n") - return 1 - if sys.argv[1] == "Unreleased": - return not handle_unreleased() - return not handle_version(sys.argv[1]) - - -def update_changelog(version): - with open("CHANGES.rst") as fp: - content = fp.read() - - expected_header = f"{CHANGELOG_HEADER}{UNRELEASED_HEADER}" - if not content.startswith(expected_header): - sys.stderr.write("CHANGES.rst does not contain Unreleased header.\n") - return False - - date_string = date.today().strftime("%Y/%m/%d") - version_line = f" {version} ({date_string})\n" - version_header = f"{'*' * len(version_line)}\n{version_line}{'*' * len(version_line)}\n\n" - - with open("CHANGES.rst", "w") as fp: - fp.write(f"{CHANGELOG_HEADER}{version_header}{content[len(expected_header) :]}") - return True - - -def update_package(version): - with open(VERSION_FILE) as fp: - content = fp.read() - - updated = re.sub('__version__ = "([^"]+)"', f'__version__ = "{version}"', content) - if content == updated: - sys.stderr.write("Package version string not changed\n") - return False - - with open(VERSION_FILE, "w") as fp: - fp.write(updated) - - print(version) - return True - - -def valid_version(version): - parsed_version = packaging.version.parse(version) - if parsed_version.local or parsed_version.is_postrelease or parsed_version.epoch: - sys.stderr.write("epoch, local postrelease version parts are not supported") - return False - return parsed_version - - -if __name__ == "__main__": - sys.exit(main())