release-creator 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. release_creator-0.1.0/.github/dependabot.yaml +20 -0
  2. release_creator-0.1.0/.github/workflows/check.yaml +104 -0
  3. release_creator-0.1.0/.github/workflows/prepare-release.yaml +125 -0
  4. release_creator-0.1.0/.github/workflows/release.yaml +88 -0
  5. release_creator-0.1.0/.gitignore +10 -0
  6. release_creator-0.1.0/.pre-commit-config.yaml +56 -0
  7. release_creator-0.1.0/.readthedocs.yaml +8 -0
  8. release_creator-0.1.0/CONTRIBUTING.md +32 -0
  9. release_creator-0.1.0/LICENSE +18 -0
  10. release_creator-0.1.0/PKG-INFO +97 -0
  11. release_creator-0.1.0/README.md +69 -0
  12. release_creator-0.1.0/docs/__init__.py +1 -0
  13. release_creator-0.1.0/docs/_static/custom.css +11 -0
  14. release_creator-0.1.0/docs/_static/favicon.png +0 -0
  15. release_creator-0.1.0/docs/_static/logo-128.png +0 -0
  16. release_creator-0.1.0/docs/changelog.md +38 -0
  17. release_creator-0.1.0/docs/conf.py +78 -0
  18. release_creator-0.1.0/docs/explanation/release-data.rst +51 -0
  19. release_creator-0.1.0/docs/how-to/link-fragments.rst +62 -0
  20. release_creator-0.1.0/docs/how-to/render-notes.rst +114 -0
  21. release_creator-0.1.0/docs/how-to/select-release-tag.rst +61 -0
  22. release_creator-0.1.0/docs/index.rst +64 -0
  23. release_creator-0.1.0/docs/reference/cli.rst +10 -0
  24. release_creator-0.1.0/docs/reference/formats.rst +53 -0
  25. release_creator-0.1.0/docs/tutorial/first-release.rst +160 -0
  26. release_creator-0.1.0/pyproject.toml +112 -0
  27. release_creator-0.1.0/src/release_creator/__init__.py +1 -0
  28. release_creator-0.1.0/src/release_creator/__main__.py +6 -0
  29. release_creator-0.1.0/src/release_creator/cli.py +38 -0
  30. release_creator-0.1.0/src/release_creator/fragments/__init__.py +1 -0
  31. release_creator-0.1.0/src/release_creator/fragments/cli.py +32 -0
  32. release_creator-0.1.0/src/release_creator/fragments/git.py +39 -0
  33. release_creator-0.1.0/src/release_creator/fragments/links.py +75 -0
  34. release_creator-0.1.0/src/release_creator/fragments/template.jinja2 +20 -0
  35. release_creator-0.1.0/src/release_creator/notes/__init__.py +1 -0
  36. release_creator-0.1.0/src/release_creator/notes/cli.py +42 -0
  37. release_creator-0.1.0/src/release_creator/notes/render.py +341 -0
  38. release_creator-0.1.0/src/release_creator/py.typed +0 -0
  39. release_creator-0.1.0/src/release_creator/tags/__init__.py +1 -0
  40. release_creator-0.1.0/src/release_creator/tags/cli.py +57 -0
  41. release_creator-0.1.0/src/release_creator/tags/select.py +119 -0
  42. release_creator-0.1.0/tests/release_creator/fragments/test_cli.py +120 -0
  43. release_creator-0.1.0/tests/release_creator/fragments/test_links.py +66 -0
  44. release_creator-0.1.0/tests/release_creator/notes/test_cli.py +112 -0
  45. release_creator-0.1.0/tests/release_creator/notes/test_render.py +197 -0
  46. release_creator-0.1.0/tests/release_creator/tags/test_cli.py +75 -0
  47. release_creator-0.1.0/tests/release_creator/tags/test_select.py +89 -0
  48. release_creator-0.1.0/tests/release_creator/test_cli.py +31 -0
  49. release_creator-0.1.0/tox.toml +59 -0
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ cooldown:
8
+ default-days: 7
9
+ labels:
10
+ - dependencies
11
+ - skip news
12
+ - package-ecosystem: uv
13
+ directory: /
14
+ schedule:
15
+ interval: weekly
16
+ cooldown:
17
+ default-days: 7
18
+ labels:
19
+ - dependencies
20
+ - skip news
@@ -0,0 +1,104 @@
1
+ name: check
2
+ on:
3
+ workflow_dispatch:
4
+ push:
5
+ branches: ["main"]
6
+ tags-ignore: ["**"]
7
+ pull_request:
8
+ types: [opened, synchronize, reopened, labeled, unlabeled]
9
+ schedule:
10
+ - cron: "0 8 * * *"
11
+ permissions:
12
+ contents: read
13
+ concurrency:
14
+ group: check-${{ github.ref }}
15
+ cancel-in-progress: true
16
+ jobs:
17
+ test:
18
+ name: test ${{ matrix.py }} on ${{ matrix.os.name }}
19
+ runs-on: ${{ matrix.os.image }}
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ py: ["3.15"]
24
+ os:
25
+ - {image: ubuntu-26.04, name: ubuntu}
26
+ - {image: windows-2025, name: windows}
27
+ - {image: macos-26, name: macos}
28
+ steps:
29
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ with:
31
+ fetch-depth: 0
32
+ persist-credentials: false
33
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
34
+ with:
35
+ python-version: "3.15"
36
+ enable-cache: false
37
+ - name: Add uv tools to the Windows path
38
+ if: runner.os == 'Windows'
39
+ shell: bash
40
+ run: echo "$USERPROFILE/.local/bin" >> "$GITHUB_PATH"
41
+ - run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv
42
+ - run: uv python install ${{ matrix.py }}
43
+ - run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.py }}
44
+ - run: tox run --skip-pkg-install -e ${{ matrix.py }}
45
+ env:
46
+ DIFF_AGAINST: ${{ github.event.pull_request.base.sha || 'HEAD' }}
47
+ check:
48
+ name: tox env ${{ matrix.tox_env }}
49
+ runs-on: ubuntu-26.04
50
+ strategy:
51
+ fail-fast: false
52
+ matrix:
53
+ tox_env: ["type", "pkg_meta", "docs", "dev"]
54
+ steps:
55
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
56
+ with:
57
+ persist-credentials: false
58
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
59
+ with:
60
+ python-version: "3.15"
61
+ enable-cache: false
62
+ - run: uv tool install --python-preference only-managed --python 3.15 tox --with tox-uv
63
+ - run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.tox_env }}
64
+ - run: tox run --skip-pkg-install -e ${{ matrix.tox_env }}
65
+ changelog:
66
+ if: github.event_name == 'pull_request'
67
+ runs-on: ubuntu-26.04
68
+ steps:
69
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
70
+ with:
71
+ fetch-depth: 0
72
+ persist-credentials: false
73
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
74
+ with:
75
+ python-version: "3.15"
76
+ enable-cache: false
77
+ - name: Check release note requirement
78
+ env:
79
+ SKIP_NEWS: ${{ contains(github.event.pull_request.labels.*.name, 'skip news') }}
80
+ BOT_AUTHOR: ${{ github.event.pull_request.user.type == 'Bot' }}
81
+ run: |
82
+ set -euo pipefail
83
+ if git diff --name-only "origin/${GITHUB_BASE_REF}...HEAD" -- 'changelog.d/*.md' | grep -q .; then
84
+ uv run --no-default-groups --group release towncrier check --compare-with "origin/${GITHUB_BASE_REF}"
85
+ elif [[ "$SKIP_NEWS" != true && "$BOT_AUTHOR" != true ]]; then
86
+ echo '::error::add a changelog fragment or apply the skip news label'
87
+ exit 1
88
+ fi
89
+ gate:
90
+ name: Required checks pass
91
+ if: always()
92
+ needs: [test, check, changelog]
93
+ runs-on: ubuntu-26.04
94
+ steps:
95
+ - env:
96
+ NEEDS_JSON: ${{ toJSON(needs) }}
97
+ run: |
98
+ jq -e '
99
+ all(
100
+ to_entries[];
101
+ .value.result == "success" or
102
+ (.key == "changelog" and .value.result == "skipped")
103
+ )
104
+ ' <<< "$NEEDS_JSON"
@@ -0,0 +1,125 @@
1
+ name: Prepare release
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ bump:
6
+ description: Version bump type
7
+ required: true
8
+ type: choice
9
+ options:
10
+ - auto
11
+ - major
12
+ - minor
13
+ - patch
14
+ - calver
15
+ default: auto
16
+ permissions: {}
17
+ concurrency:
18
+ group: prepare-release
19
+ cancel-in-progress: false
20
+ jobs:
21
+ assemble:
22
+ if: github.ref == 'refs/heads/main'
23
+ runs-on: ubuntu-26.04
24
+ permissions:
25
+ contents: read
26
+ outputs:
27
+ version: ${{ steps.version.outputs.version }}
28
+ steps:
29
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30
+ with:
31
+ fetch-depth: 0
32
+ persist-credentials: false
33
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
34
+ with:
35
+ python-version: "3.15"
36
+ enable-cache: false
37
+ - name: Calculate next version
38
+ id: version
39
+ env:
40
+ BUMP: ${{ inputs.bump }}
41
+ run: |
42
+ set -euo pipefail
43
+ version=$(git tag --list | uv run --no-default-groups release-creator tags --next "$BUMP")
44
+ echo "Next version: $version"
45
+ echo "version=$version" >> "$GITHUB_OUTPUT"
46
+ - name: Build release patch
47
+ env:
48
+ VERSION: ${{ steps.version.outputs.version }}
49
+ run: |
50
+ set -euo pipefail
51
+ git tag --list | uv run --no-default-groups release-creator tags "$VERSION" --require-newer
52
+ uv run --no-default-groups release-creator fragments --repository "$GITHUB_REPOSITORY" --git
53
+ uv run --no-default-groups --group release towncrier build --yes --version "$VERSION"
54
+ uvx prek exec mdformat -- mdformat --wrap 120 docs/changelog.md
55
+ uvx prek run --all-files
56
+ git diff HEAD --binary > "$RUNNER_TEMP/release.patch"
57
+ test -s "$RUNNER_TEMP/release.patch"
58
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
59
+ with:
60
+ name: release-patch
61
+ path: ${{ runner.temp }}/release.patch
62
+ if-no-files-found: error
63
+ push:
64
+ needs: assemble
65
+ runs-on: ubuntu-26.04
66
+ environment: release-auth
67
+ permissions:
68
+ contents: read
69
+ steps:
70
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
71
+ with:
72
+ fetch-depth: 0
73
+ persist-credentials: false
74
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
75
+ with:
76
+ name: release-patch
77
+ path: ${{ runner.temp }}/release-patch
78
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
79
+ with:
80
+ python-version: "3.15"
81
+ enable-cache: false
82
+ - name: Validate release patch
83
+ env:
84
+ VERSION: ${{ needs.assemble.outputs.version }}
85
+ run: |
86
+ set -euo pipefail
87
+ git fetch origin main
88
+ if [[ $(git rev-parse origin/main) != "$GITHUB_SHA" ]]; then
89
+ echo "::error::main changed during release preparation; dispatch again"
90
+ exit 1
91
+ fi
92
+ git reset --hard origin/main
93
+ git apply --check "$RUNNER_TEMP/release-patch/release.patch"
94
+ git apply --index "$RUNNER_TEMP/release-patch/release.patch"
95
+ while IFS= read -r path; do
96
+ case "$path" in
97
+ docs/changelog.md|changelog.d/*.md) ;;
98
+ *) echo "::error::unexpected release path: $path"; exit 1 ;;
99
+ esac
100
+ done < <(git diff --cached --name-only)
101
+ grep -Fq "## $VERSION (" docs/changelog.md
102
+ git diff --cached --check
103
+ uvx prek run --all-files
104
+ - id: token
105
+ uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
106
+ with:
107
+ client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
108
+ private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
109
+ owner: ${{ github.repository_owner }}
110
+ repositories: ${{ github.event.repository.name }}
111
+ permission-contents: write
112
+ - name: Commit and tag the release
113
+ env:
114
+ VERSION: ${{ needs.assemble.outputs.version }}
115
+ GH_TOKEN: ${{ steps.token.outputs.token }}
116
+ APP_SLUG: ${{ steps.token.outputs.app-slug }}
117
+ run: |
118
+ set -euo pipefail
119
+ app_user_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
120
+ git config user.name "${APP_SLUG}[bot]"
121
+ git config user.email "${app_user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
122
+ git commit -m "release $VERSION"
123
+ git tag "$VERSION"
124
+ gh auth setup-git --hostname github.com --force
125
+ git push --atomic origin HEAD:main "refs/tags/$VERSION"
@@ -0,0 +1,88 @@
1
+ name: Release to PyPI
2
+ on:
3
+ push:
4
+ tags: ["*"]
5
+ permissions:
6
+ contents: read
7
+ env:
8
+ dists-artifact-name: python-package-distributions
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-26.04
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
15
+ with:
16
+ fetch-depth: 0
17
+ persist-credentials: false
18
+ - name: Install the latest version of uv
19
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
20
+ with:
21
+ python-version: "3.15"
22
+ cache-dependency-glob: "pyproject.toml"
23
+ enable-cache: false
24
+ - name: Require a changelog section for the tag
25
+ env:
26
+ TAG: ${{ github.ref_name }}
27
+ run: |
28
+ uv run --no-default-groups release-creator tags "$TAG"
29
+ if ! grep -qF "## $TAG (" docs/changelog.md; then
30
+ echo "::error::docs/changelog.md has no section for $TAG"
31
+ exit 1
32
+ fi
33
+ - name: Check the tagged source
34
+ run: uvx prek run --all-files
35
+ - name: Build package
36
+ run: uv build --python 3.15 --python-preference only-managed --sdist --wheel . --out-dir dist
37
+ - name: Store the distribution packages
38
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
39
+ with:
40
+ name: ${{ env.dists-artifact-name }}
41
+ path: dist/*
42
+ release:
43
+ needs:
44
+ - build
45
+ runs-on: ubuntu-26.04
46
+ environment:
47
+ name: release
48
+ url: https://pypi.org/project/release-creator/${{ github.ref_name }}
49
+ permissions:
50
+ id-token: write
51
+ steps:
52
+ - name: Download all the dists
53
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
54
+ with:
55
+ name: ${{ env.dists-artifact-name }}
56
+ path: dist/
57
+ - name: Publish to PyPI
58
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
59
+ with:
60
+ attestations: true
61
+ github-release:
62
+ needs: release
63
+ runs-on: ubuntu-26.04
64
+ permissions:
65
+ contents: write
66
+ steps:
67
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
68
+ with:
69
+ fetch-depth: 0
70
+ persist-credentials: false
71
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
72
+ with:
73
+ python-version: "3.15"
74
+ enable-cache: false
75
+ - name: Publish GitHub Release
76
+ env:
77
+ GH_TOKEN: ${{ github.token }}
78
+ TAG: ${{ github.ref_name }}
79
+ run: |
80
+ set -euo pipefail
81
+ previous=$(git tag --list | uv run --no-default-groups release-creator tags "$TAG" --previous)
82
+ args=()
83
+ if [[ -n "$previous" ]]; then
84
+ args+=(--previous "$previous")
85
+ fi
86
+ gh api -X POST "repos/${GITHUB_REPOSITORY}/releases/generate-notes" -f tag_name="$TAG" --jq .body > "$RUNNER_TEMP/generated-notes.md"
87
+ uv run --no-default-groups release-creator notes --changelog docs/changelog.md --tag "$TAG" --repository "$GITHUB_REPOSITORY" --artifact-url "https://pypi.org/project/release-creator/${TAG}/" --generated-notes "$RUNNER_TEMP/generated-notes.md" "${args[@]}" > "$RUNNER_TEMP/release-notes.md"
88
+ gh release create "$TAG" --verify-tag --title "v$TAG" --notes-file "$RUNNER_TEMP/release-notes.md"
@@ -0,0 +1,10 @@
1
+ /.coverage
2
+ /.pytest_cache
3
+ /.ruff_cache
4
+ /.tox
5
+ /.venv
6
+ /dist
7
+ /htmlcov
8
+ *.egg-info/
9
+ __pycache__/
10
+ /uv.lock
@@ -0,0 +1,56 @@
1
+ default_language_version:
2
+ python: python3.15
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v6.0.0
6
+ hooks:
7
+ - id: end-of-file-fixer
8
+ - id: trailing-whitespace
9
+ - repo: https://github.com/python-jsonschema/check-jsonschema
10
+ rev: 0.38.2
11
+ hooks:
12
+ - id: check-github-workflows
13
+ args: ["--verbose"]
14
+ - repo: https://github.com/codespell-project/codespell
15
+ rev: v2.4.3
16
+ hooks:
17
+ - id: codespell
18
+ - repo: https://github.com/tox-dev/pyproject-fmt
19
+ rev: v2.30.3
20
+ hooks:
21
+ - id: pyproject-fmt
22
+ - repo: https://github.com/abravalheri/validate-pyproject
23
+ rev: "0.26"
24
+ hooks:
25
+ - id: validate-pyproject
26
+ - repo: https://github.com/astral-sh/ruff-pre-commit
27
+ rev: "v0.17.0"
28
+ hooks:
29
+ - id: ruff-check
30
+ args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
31
+ - id: ruff-format
32
+ - repo: https://github.com/asottile/blacken-docs
33
+ rev: 1.20.0
34
+ hooks:
35
+ - id: blacken-docs
36
+ additional_dependencies: [black==26.1]
37
+ - repo: https://github.com/google/yamlfmt
38
+ rev: "v0.21.0"
39
+ hooks:
40
+ - id: yamlfmt
41
+ - repo: local
42
+ hooks:
43
+ - id: mdformat
44
+ name: mdformat
45
+ entry: mdformat --wrap 120
46
+ language: python
47
+ types: [markdown]
48
+ additional_dependencies: ["mdformat-gfm>=1"]
49
+ - repo: https://github.com/zizmorcore/zizmor-pre-commit
50
+ rev: v1.30.1
51
+ hooks:
52
+ - id: zizmor
53
+ - repo: meta
54
+ hooks:
55
+ - id: check-hooks-apply
56
+ - id: check-useless-excludes
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ build:
3
+ os: ubuntu-26.04
4
+ tools: {}
5
+ commands:
6
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
7
+ - ~/.local/bin/uv tool install tox --with tox-uv -p 3.15 --managed-python
8
+ - ~/.local/bin/tox run -e docs -- "$READTHEDOCS_OUTPUT/html"
@@ -0,0 +1,32 @@
1
+ # Contributing to release-creator
2
+
3
+ Run `tox -e dev` to create `.tox/dev`. Run `tox -e 3.15,type,pkg_meta,docs` and `prek run --all-files` before pushing a
4
+ PR. CI tests Python 3.15 on Linux, macOS, and Windows.
5
+
6
+ ## Release notes
7
+
8
+ Add a `changelog.d/+short-name.<type>.md` fragment for each user-visible change. No issue or PR number is needed when
9
+ opening the PR. Use `feature` for additions, `change` for changed behavior, `bugfix` for fixes, or `doc` for
10
+ documentation. Other types are `breaking`, `security`, `performance`, `deprecation`, `removal`, and `packaging`. Keep
11
+ separate changes in separate fragments.
12
+
13
+ Write a complete sentence and credit verified human authors:
14
+
15
+ ```markdown
16
+ Render GitHub notes without wrapped bullets by [@gaborbernat](https://github.com/gaborbernat).
17
+ ```
18
+
19
+ For multiple authors, join linked handles with `by x, y and z`. Do not credit reviewers or bots. Bot PRs need no
20
+ fragment unless they supply a user-facing change; a bot-only fragment may omit `by`. Apply `skip news` to maintenance
21
+ work. This label may be added after opening the PR, and it does not suppress checks for a supplied fragment.
22
+
23
+ ## Release process
24
+
25
+ The `Prepare release` workflow reads the PR number from each fragment's squash commit, assembles a Towncrier changelog
26
+ patch, runs `prek`, then uses the repository-scoped release App to commit and tag on `main`. The tag workflow runs
27
+ `prek` again, builds the package, publishes to PyPI through trusted publishing, and creates a GitHub Release using the
28
+ tagged `release-creator` source. Set up the App, `release-auth` environment, and PyPI trusted publisher before
29
+ dispatching it.
30
+
31
+ PR documentation builds show the branch's fragments in an `Unreleased` section on the changelog page. Towncrier adds
32
+ them to `docs/changelog.md` only during release preparation.
@@ -0,0 +1,18 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a
2
+ copy of this software and associated documentation files (the
3
+ "Software"), to deal in the Software without restriction, including
4
+ without limitation the rights to use, copy, modify, merge, publish,
5
+ distribute, sublicense, and/or sell copies of the Software, and to
6
+ permit persons to whom the Software is furnished to do so, subject to
7
+ the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included
10
+ in all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
13
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
16
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
17
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.5
2
+ Name: release-creator
3
+ Version: 0.1.0
4
+ Summary: Release preparation tools for changelogs and GitHub
5
+ Project-URL: Documentation, https://release-creator.readthedocs.io/
6
+ Project-URL: Source, https://github.com/tox-dev/release-creator
7
+ Project-URL: Tracker, https://github.com/tox-dev/release-creator/issues
8
+ Author-email: Bernát Gábor <gaborjbernat@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: GitHub releases,changelog,release automation,release notes,towncrier
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.15
20
+ Classifier: Topic :: Documentation
21
+ Classifier: Topic :: Software Development :: Build Tools
22
+ Classifier: Topic :: Software Development :: Version Control :: Git
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.15
25
+ Requires-Dist: mdformat-gfm<2,>=1
26
+ Requires-Dist: mdformat<2,>=1
27
+ Description-Content-Type: text/markdown
28
+
29
+ # release-creator
30
+
31
+ ![release-creator logo](https://raw.githubusercontent.com/tox-dev/release-creator/main/docs/_static/logo-128.png)
32
+
33
+ [![PyPI](https://img.shields.io/pypi/v/release-creator?style=flat-square)](https://pypi.org/project/release-creator/)
34
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/release-creator.svg)](https://pypi.org/project/release-creator/)
35
+ [![check](https://github.com/tox-dev/release-creator/actions/workflows/check.yaml/badge.svg)](https://github.com/tox-dev/release-creator/actions/workflows/check.yaml)
36
+
37
+ Release preparation tools for Python projects. The `notes` command renders a tagged changelog section for a GitHub
38
+ Release. Other release tasks can use separate commands.
39
+
40
+ The [documentation](https://release-creator.readthedocs.io/) has a tutorial, how-to guides, a generated command
41
+ reference, and an explanation of the changelog format.
42
+
43
+ ## Render GitHub Release notes
44
+
45
+ Run the current release from PyPI:
46
+
47
+ ```bash
48
+ uvx --from 'release-creator' release-creator notes \
49
+ --changelog docs/changelog.md \
50
+ --tag 1.2.3 \
51
+ --repository tox-dev/example \
52
+ --previous 1.2.2 \
53
+ --artifact-url https://pypi.org/project/example/1.2.3/ > release-notes.md
54
+ ```
55
+
56
+ For automation, replace `release-creator` after `--from` with a tested `release-creator==VERSION`. The command reads the
57
+ tagged section, maps `Added` to `Features` and `Fixed` to `Bug fixes`, changes linked author handles to GitHub mentions,
58
+ and leaves bullets unwrapped. It keeps stable category anchors, omits empty categories when they are absent from the
59
+ source, and adds artifact and comparison links. Use `--artifact-label` for an ecosystem other than PyPI; omit
60
+ `--artifact-url` when there is no external artifact.
61
+
62
+ The command also accepts a `.rst` changelog with the same category names. For projects whose `:issue:` role points at
63
+ PRs, pass `--issue-role pull`:
64
+
65
+ ```bash
66
+ uvx --from 'release-creator' release-creator notes \
67
+ --changelog docs/changelog.rst \
68
+ --tag 1.2.3 \
69
+ --repository tox-dev/example \
70
+ --previous 1.2.2 \
71
+ --issue-role pull \
72
+ --artifact-url https://pypi.org/project/example/1.2.3/ > release-notes.md
73
+ ```
74
+
75
+ The changelog is the source of truth. The command does not infer changes from commits or generate an author list. Add
76
+ verified human credits to changelog entries before release; omit bot credits. The GitHub Release may add a
77
+ `New Contributors` section by passing `--generated-notes` with the body from GitHub's generate-notes API. Only handles
78
+ credited in the changelog are kept; the generated-notes banner and other generated sections are discarded.
79
+
80
+ Named Towncrier fragments need no issue or PR number. Before Towncrier builds the changelog, run
81
+ `release-creator fragments --repository owner/repo --git`. The command reads each fragment's introducing squash commit,
82
+ adds its PR link, and fails if the subject does not end in `(#number)`. For a checkout without Git history, pass a
83
+ tab-separated subject map with `--commit-map commits.tsv` instead.
84
+
85
+ The `tags` command calculates a version from pending fragments, validates numeric tags, and selects the preceding tag
86
+ for GitHub comparisons:
87
+
88
+ ```bash
89
+ git tag --list | uvx --from 'release-creator' release-creator tags --next auto
90
+ git tag --list | uvx --from 'release-creator' release-creator tags 1.2.3 --require-newer
91
+ git tag --list | uvx --from 'release-creator' release-creator tags 1.2.3 --previous
92
+ ```
93
+
94
+ ## Development and releases
95
+
96
+ See [contributing](https://github.com/tox-dev/release-creator/blob/main/CONTRIBUTING.md) for the fragment format and release process. The package uses the same `notes`
97
+ command for its own GitHub Releases. Run `tox -e 3.15,type,pkg_meta,docs` and `prek run --all-files` before a PR.
@@ -0,0 +1,69 @@
1
+ # release-creator
2
+
3
+ ![release-creator logo](docs/_static/logo-128.png)
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/release-creator?style=flat-square)](https://pypi.org/project/release-creator/)
6
+ [![Supported Python versions](https://img.shields.io/pypi/pyversions/release-creator.svg)](https://pypi.org/project/release-creator/)
7
+ [![check](https://github.com/tox-dev/release-creator/actions/workflows/check.yaml/badge.svg)](https://github.com/tox-dev/release-creator/actions/workflows/check.yaml)
8
+
9
+ Release preparation tools for Python projects. The `notes` command renders a tagged changelog section for a GitHub
10
+ Release. Other release tasks can use separate commands.
11
+
12
+ The [documentation](https://release-creator.readthedocs.io/) has a tutorial, how-to guides, a generated command
13
+ reference, and an explanation of the changelog format.
14
+
15
+ ## Render GitHub Release notes
16
+
17
+ Run the current release from PyPI:
18
+
19
+ ```bash
20
+ uvx --from 'release-creator' release-creator notes \
21
+ --changelog docs/changelog.md \
22
+ --tag 1.2.3 \
23
+ --repository tox-dev/example \
24
+ --previous 1.2.2 \
25
+ --artifact-url https://pypi.org/project/example/1.2.3/ > release-notes.md
26
+ ```
27
+
28
+ For automation, replace `release-creator` after `--from` with a tested `release-creator==VERSION`. The command reads the
29
+ tagged section, maps `Added` to `Features` and `Fixed` to `Bug fixes`, changes linked author handles to GitHub mentions,
30
+ and leaves bullets unwrapped. It keeps stable category anchors, omits empty categories when they are absent from the
31
+ source, and adds artifact and comparison links. Use `--artifact-label` for an ecosystem other than PyPI; omit
32
+ `--artifact-url` when there is no external artifact.
33
+
34
+ The command also accepts a `.rst` changelog with the same category names. For projects whose `:issue:` role points at
35
+ PRs, pass `--issue-role pull`:
36
+
37
+ ```bash
38
+ uvx --from 'release-creator' release-creator notes \
39
+ --changelog docs/changelog.rst \
40
+ --tag 1.2.3 \
41
+ --repository tox-dev/example \
42
+ --previous 1.2.2 \
43
+ --issue-role pull \
44
+ --artifact-url https://pypi.org/project/example/1.2.3/ > release-notes.md
45
+ ```
46
+
47
+ The changelog is the source of truth. The command does not infer changes from commits or generate an author list. Add
48
+ verified human credits to changelog entries before release; omit bot credits. The GitHub Release may add a
49
+ `New Contributors` section by passing `--generated-notes` with the body from GitHub's generate-notes API. Only handles
50
+ credited in the changelog are kept; the generated-notes banner and other generated sections are discarded.
51
+
52
+ Named Towncrier fragments need no issue or PR number. Before Towncrier builds the changelog, run
53
+ `release-creator fragments --repository owner/repo --git`. The command reads each fragment's introducing squash commit,
54
+ adds its PR link, and fails if the subject does not end in `(#number)`. For a checkout without Git history, pass a
55
+ tab-separated subject map with `--commit-map commits.tsv` instead.
56
+
57
+ The `tags` command calculates a version from pending fragments, validates numeric tags, and selects the preceding tag
58
+ for GitHub comparisons:
59
+
60
+ ```bash
61
+ git tag --list | uvx --from 'release-creator' release-creator tags --next auto
62
+ git tag --list | uvx --from 'release-creator' release-creator tags 1.2.3 --require-newer
63
+ git tag --list | uvx --from 'release-creator' release-creator tags 1.2.3 --previous
64
+ ```
65
+
66
+ ## Development and releases
67
+
68
+ See [contributing](CONTRIBUTING.md) for the fragment format and release process. The package uses the same `notes`
69
+ command for its own GitHub Releases. Run `tox -e 3.15,type,pkg_meta,docs` and `prek run --all-files` before a PR.
@@ -0,0 +1 @@
1
+ """Documentation configuration package."""
@@ -0,0 +1,11 @@
1
+ article .highlight pre,
2
+ article pre.literal-block {
3
+ white-space: pre-wrap;
4
+ overflow-wrap: anywhere;
5
+ }
6
+
7
+ figure pre.mermaid > svg {
8
+ width: auto;
9
+ height: auto;
10
+ max-width: 100% !important;
11
+ }