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.
- release_creator-0.1.0/.github/dependabot.yaml +20 -0
- release_creator-0.1.0/.github/workflows/check.yaml +104 -0
- release_creator-0.1.0/.github/workflows/prepare-release.yaml +125 -0
- release_creator-0.1.0/.github/workflows/release.yaml +88 -0
- release_creator-0.1.0/.gitignore +10 -0
- release_creator-0.1.0/.pre-commit-config.yaml +56 -0
- release_creator-0.1.0/.readthedocs.yaml +8 -0
- release_creator-0.1.0/CONTRIBUTING.md +32 -0
- release_creator-0.1.0/LICENSE +18 -0
- release_creator-0.1.0/PKG-INFO +97 -0
- release_creator-0.1.0/README.md +69 -0
- release_creator-0.1.0/docs/__init__.py +1 -0
- release_creator-0.1.0/docs/_static/custom.css +11 -0
- release_creator-0.1.0/docs/_static/favicon.png +0 -0
- release_creator-0.1.0/docs/_static/logo-128.png +0 -0
- release_creator-0.1.0/docs/changelog.md +38 -0
- release_creator-0.1.0/docs/conf.py +78 -0
- release_creator-0.1.0/docs/explanation/release-data.rst +51 -0
- release_creator-0.1.0/docs/how-to/link-fragments.rst +62 -0
- release_creator-0.1.0/docs/how-to/render-notes.rst +114 -0
- release_creator-0.1.0/docs/how-to/select-release-tag.rst +61 -0
- release_creator-0.1.0/docs/index.rst +64 -0
- release_creator-0.1.0/docs/reference/cli.rst +10 -0
- release_creator-0.1.0/docs/reference/formats.rst +53 -0
- release_creator-0.1.0/docs/tutorial/first-release.rst +160 -0
- release_creator-0.1.0/pyproject.toml +112 -0
- release_creator-0.1.0/src/release_creator/__init__.py +1 -0
- release_creator-0.1.0/src/release_creator/__main__.py +6 -0
- release_creator-0.1.0/src/release_creator/cli.py +38 -0
- release_creator-0.1.0/src/release_creator/fragments/__init__.py +1 -0
- release_creator-0.1.0/src/release_creator/fragments/cli.py +32 -0
- release_creator-0.1.0/src/release_creator/fragments/git.py +39 -0
- release_creator-0.1.0/src/release_creator/fragments/links.py +75 -0
- release_creator-0.1.0/src/release_creator/fragments/template.jinja2 +20 -0
- release_creator-0.1.0/src/release_creator/notes/__init__.py +1 -0
- release_creator-0.1.0/src/release_creator/notes/cli.py +42 -0
- release_creator-0.1.0/src/release_creator/notes/render.py +341 -0
- release_creator-0.1.0/src/release_creator/py.typed +0 -0
- release_creator-0.1.0/src/release_creator/tags/__init__.py +1 -0
- release_creator-0.1.0/src/release_creator/tags/cli.py +57 -0
- release_creator-0.1.0/src/release_creator/tags/select.py +119 -0
- release_creator-0.1.0/tests/release_creator/fragments/test_cli.py +120 -0
- release_creator-0.1.0/tests/release_creator/fragments/test_links.py +66 -0
- release_creator-0.1.0/tests/release_creator/notes/test_cli.py +112 -0
- release_creator-0.1.0/tests/release_creator/notes/test_render.py +197 -0
- release_creator-0.1.0/tests/release_creator/tags/test_cli.py +75 -0
- release_creator-0.1.0/tests/release_creator/tags/test_select.py +89 -0
- release_creator-0.1.0/tests/release_creator/test_cli.py +31 -0
- 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,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,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
|
+

|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/release-creator/)
|
|
34
|
+
[](https://pypi.org/project/release-creator/)
|
|
35
|
+
[](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
|
+

|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/release-creator/)
|
|
6
|
+
[](https://pypi.org/project/release-creator/)
|
|
7
|
+
[](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."""
|
|
Binary file
|
|
Binary file
|