conventional-release 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.
- conventional_release-0.1.0/.github/dependabot.yml +14 -0
- conventional_release-0.1.0/.github/pull_request_template.md +8 -0
- conventional_release-0.1.0/.github/workflows/ci.yml +38 -0
- conventional_release-0.1.0/.github/workflows/claude-review.yml +174 -0
- conventional_release-0.1.0/.github/workflows/pr-title.yml +36 -0
- conventional_release-0.1.0/.github/workflows/pr.yml +16 -0
- conventional_release-0.1.0/.github/workflows/release.yml +78 -0
- conventional_release-0.1.0/.github/workflows/tag.yml +79 -0
- conventional_release-0.1.0/.gitignore +11 -0
- conventional_release-0.1.0/CHANGELOG.md +34 -0
- conventional_release-0.1.0/CONTRIBUTING.md +23 -0
- conventional_release-0.1.0/LICENSE +202 -0
- conventional_release-0.1.0/Makefile +34 -0
- conventional_release-0.1.0/PKG-INFO +207 -0
- conventional_release-0.1.0/README.md +181 -0
- conventional_release-0.1.0/SECURITY.md +8 -0
- conventional_release-0.1.0/pyproject.toml +65 -0
- conventional_release-0.1.0/src/conventional_release/__init__.py +8 -0
- conventional_release-0.1.0/src/conventional_release/__main__.py +3 -0
- conventional_release-0.1.0/src/conventional_release/cli.py +123 -0
- conventional_release-0.1.0/src/conventional_release/cliff.py +197 -0
- conventional_release-0.1.0/src/conventional_release/config.py +164 -0
- conventional_release-0.1.0/src/conventional_release/git.py +68 -0
- conventional_release-0.1.0/src/conventional_release/py.typed +0 -0
- conventional_release-0.1.0/src/conventional_release/release.py +229 -0
- conventional_release-0.1.0/src/conventional_release/semver.py +30 -0
- conventional_release-0.1.0/src/conventional_release/versionfiles.py +96 -0
- conventional_release-0.1.0/tests/__init__.py +0 -0
- conventional_release-0.1.0/tests/conftest.py +50 -0
- conventional_release-0.1.0/tests/test_release.py +233 -0
- conventional_release-0.1.0/tests/test_versionfiles.py +97 -0
- conventional_release-0.1.0/uv.lock +594 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
17
|
+
- run: make lint typecheck
|
|
18
|
+
|
|
19
|
+
test:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
python: ["3.11", "3.12", "3.13", "3.14"]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python }}
|
|
30
|
+
- run: make tests
|
|
31
|
+
|
|
32
|
+
build:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v7
|
|
36
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
37
|
+
- run: uv build
|
|
38
|
+
- run: uvx twine check --strict dist/*
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
name: claude-review
|
|
2
|
+
|
|
3
|
+
# Two jobs, one action:
|
|
4
|
+
# review — every non-draft PR gets an automatic review, posted as inline comments plus one
|
|
5
|
+
# sticky summary.
|
|
6
|
+
# mention — "@claude <question>" (or "@claude review" after a fix push) in a PR/issue comment
|
|
7
|
+
# gets an answer. Maintainers only: see the `if` on that job.
|
|
8
|
+
#
|
|
9
|
+
# Authenticated with a Claude subscription OAuth token (CLAUDE_CODE_OAUTH_TOKEN, from
|
|
10
|
+
# `claude setup-token`). Until that secret exists the jobs skip with a notice instead of failing:
|
|
11
|
+
# a missing reviewer must not turn a PR red.
|
|
12
|
+
#
|
|
13
|
+
# Public-repo safety:
|
|
14
|
+
# - PRs from forks get no secrets on `pull_request`, so they are skipped with the same notice.
|
|
15
|
+
# Never switch this to `pull_request_target`: that hands the token to code from a stranger's fork.
|
|
16
|
+
# - `issue_comment` runs WITH secrets on any PR, forks included, so the mention job only answers
|
|
17
|
+
# comments from the repo owner, members and collaborators.
|
|
18
|
+
# - The reviewer is read-only on the repo (contents: read). It can comment; it can never push.
|
|
19
|
+
#
|
|
20
|
+
# The action refuses to run a workflow file that differs from the copy on the default branch
|
|
21
|
+
# (anti-tamper), so a change to THIS file must be merged on its own before a PR carrying the
|
|
22
|
+
# same change can be reviewed.
|
|
23
|
+
|
|
24
|
+
on:
|
|
25
|
+
pull_request:
|
|
26
|
+
# Not on every push, because each round uses the plan's quota. After fixes, ask again with
|
|
27
|
+
# "@claude review".
|
|
28
|
+
types: [opened, reopened, ready_for_review]
|
|
29
|
+
issue_comment:
|
|
30
|
+
types: [created]
|
|
31
|
+
pull_request_review_comment:
|
|
32
|
+
types: [created]
|
|
33
|
+
|
|
34
|
+
permissions:
|
|
35
|
+
contents: read
|
|
36
|
+
pull-requests: write
|
|
37
|
+
issues: write
|
|
38
|
+
id-token: write
|
|
39
|
+
actions: read
|
|
40
|
+
|
|
41
|
+
# Keyed on event, number and actor. Without the event, the reviewer's own first inline comment
|
|
42
|
+
# (a pull_request_review_comment) cancels the review that is still running. Without the actor,
|
|
43
|
+
# the mention job's progress comment cancels the run that posted it.
|
|
44
|
+
concurrency:
|
|
45
|
+
group: claude-${{ github.event_name }}-${{ github.event.pull_request.number || github.event.issue.number }}-${{ github.actor }}
|
|
46
|
+
cancel-in-progress: true
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
review:
|
|
50
|
+
name: claude-review
|
|
51
|
+
if: >
|
|
52
|
+
github.event_name == 'pull_request' &&
|
|
53
|
+
github.event.pull_request.draft == false &&
|
|
54
|
+
!startsWith(github.event.pull_request.title, 'chore(release):') &&
|
|
55
|
+
github.actor != 'dependabot[bot]'
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
timeout-minutes: 30
|
|
58
|
+
steps:
|
|
59
|
+
- id: token
|
|
60
|
+
name: Is the reviewer configured?
|
|
61
|
+
env:
|
|
62
|
+
TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
63
|
+
run: |
|
|
64
|
+
if [ -n "$TOKEN" ]; then
|
|
65
|
+
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
|
66
|
+
else
|
|
67
|
+
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
|
68
|
+
echo "::notice title=claude-review skipped::CLAUDE_CODE_OAUTH_TOKEN is not available (not set, or a PR from a fork)."
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
- if: steps.token.outputs.enabled == 'true'
|
|
72
|
+
uses: actions/checkout@v7
|
|
73
|
+
with:
|
|
74
|
+
fetch-depth: 0 # the review needs the base branch to diff against
|
|
75
|
+
|
|
76
|
+
- if: steps.token.outputs.enabled == 'true'
|
|
77
|
+
uses: anthropics/claude-code-action@v1
|
|
78
|
+
with:
|
|
79
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
80
|
+
use_sticky_comment: true
|
|
81
|
+
prompt: |
|
|
82
|
+
REPO: ${{ github.repository }}
|
|
83
|
+
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
84
|
+
|
|
85
|
+
You are reviewing a pull request for conventional-release, a Python CLI and a set of
|
|
86
|
+
reusable GitHub workflows that other projects call to write their CHANGELOG, bump
|
|
87
|
+
versions, tag releases and publish them. Other repositories run this code in their
|
|
88
|
+
release pipelines, so a regression breaks releases we cannot see.
|
|
89
|
+
|
|
90
|
+
Read CONTRIBUTING.md and the README first. They define the contract:
|
|
91
|
+
- The CHANGELOG output is byte-compatible with standard-version: `## X.Y.Z (date)`, two
|
|
92
|
+
blank lines, `### Section`, `* **scope:** subject ([#N](…/issues/N)) ([sha](…))`.
|
|
93
|
+
Any change to the rendered shape (cliff.py templates, section order, link format) is
|
|
94
|
+
a breaking change for users, even if the tests were updated to match.
|
|
95
|
+
- The reusable workflows (.github/workflows/tag.yml, pr-title.yml) are a public API
|
|
96
|
+
called as `@v0`: their inputs, outputs (released, version, tag) and default
|
|
97
|
+
tool-spec must not change incompatibly in a minor release.
|
|
98
|
+
- The CLI's commands, flags, exit codes and config keys (.conventional-release.toml
|
|
99
|
+
and [tool.conventional-release]) are public API too.
|
|
100
|
+
- Version files are edited textually, one line only. Comments and formatting elsewhere
|
|
101
|
+
in the file must survive.
|
|
102
|
+
- PR titles follow Conventional Commits. The title becomes the changelog line.
|
|
103
|
+
|
|
104
|
+
Look for, in this order:
|
|
105
|
+
1. Correctness bugs: version bump rules (breaking → major, feat → minor, fix → patch;
|
|
106
|
+
the first release keeps the version in the file), tag detection after a squash
|
|
107
|
+
merge, git edge cases (no tags, no remote, dirty tree, existing tag or branch).
|
|
108
|
+
2. Breaking changes to the public API above that the title does not mark with `!` and a
|
|
109
|
+
BREAKING CHANGE footer.
|
|
110
|
+
3. Workflow security: secrets reaching fork PRs, `pull_request_target`, untrusted
|
|
111
|
+
GitHub expressions (PR titles, comment bodies) interpolated straight into `run:`
|
|
112
|
+
instead of passed through `env:`, permissions wider than the job needs, or
|
|
113
|
+
publishing without trusted publishing.
|
|
114
|
+
4. New behaviour without a test. Tests build throwaway git repos in tmp_path, see
|
|
115
|
+
tests/conftest.py.
|
|
116
|
+
5. README drift: a changed command, flag, config key or workflow input that the
|
|
117
|
+
README still documents the old way.
|
|
118
|
+
|
|
119
|
+
Do NOT comment on formatting, import order or line length. ruff, mypy --strict and
|
|
120
|
+
actionlint already gate those in CI. Do not restate the PR description back.
|
|
121
|
+
|
|
122
|
+
Use `gh pr diff` and `gh pr view` to see the change. Post specific findings as inline
|
|
123
|
+
comments on the exact lines (mcp__github_inline_comment__create_inline_comment).
|
|
124
|
+
Then post ONE summary comment via `gh pr comment`: a short verdict, the findings
|
|
125
|
+
ranked by severity, and anything you could not verify. If there is nothing
|
|
126
|
+
significant, say so in two sentences. A short honest review beats a long padded one.
|
|
127
|
+
|
|
128
|
+
Budget: you have a hard cap of 60 tool calls, and the run fails if you exceed it. Start
|
|
129
|
+
from `gh pr diff --name-only` and `gh pr diff`. Read a file in full only when the diff
|
|
130
|
+
alone cannot answer the question. Post the summary comment no later than your 45th
|
|
131
|
+
call, and say what you did not get to. An unposted review is worth nothing.
|
|
132
|
+
claude_args: |
|
|
133
|
+
--max-turns 60
|
|
134
|
+
--allowed-tools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Read,Grep,Glob"
|
|
135
|
+
|
|
136
|
+
mention:
|
|
137
|
+
name: claude-mention
|
|
138
|
+
# Maintainers only: issue_comment runs with secrets even on fork PRs, so anyone else could
|
|
139
|
+
# spend the plan's quota. Never react to the bot's own comments, or it talks to itself forever.
|
|
140
|
+
if: >
|
|
141
|
+
(github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment') &&
|
|
142
|
+
contains(github.event.comment.body, '@claude') &&
|
|
143
|
+
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association) &&
|
|
144
|
+
github.actor != 'claude[bot]'
|
|
145
|
+
runs-on: ubuntu-latest
|
|
146
|
+
timeout-minutes: 30
|
|
147
|
+
steps:
|
|
148
|
+
- id: token
|
|
149
|
+
name: Is the reviewer configured?
|
|
150
|
+
env:
|
|
151
|
+
TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
152
|
+
run: |
|
|
153
|
+
if [ -n "$TOKEN" ]; then
|
|
154
|
+
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
|
155
|
+
else
|
|
156
|
+
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
|
157
|
+
echo "::notice title=claude-mention skipped::CLAUDE_CODE_OAUTH_TOKEN is not set."
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
- if: steps.token.outputs.enabled == 'true'
|
|
161
|
+
uses: actions/checkout@v7
|
|
162
|
+
with:
|
|
163
|
+
fetch-depth: 0
|
|
164
|
+
|
|
165
|
+
- if: steps.token.outputs.enabled == 'true'
|
|
166
|
+
uses: anthropics/claude-code-action@v1
|
|
167
|
+
with:
|
|
168
|
+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
|
169
|
+
# No prompt means tag mode: it answers the @claude comment in context. "@claude review"
|
|
170
|
+
# is a full review of the head, so it gets the review job's budget. A question gets 20.
|
|
171
|
+
claude_args: |
|
|
172
|
+
--max-turns ${{ contains(github.event.comment.body, '@claude review') && '60' || '20' }}
|
|
173
|
+
--append-system-prompt "You have a hard cap on tool calls (--max-turns) and the run FAILS the moment you exceed it. Work from `gh pr diff --name-only` and `gh pr diff`; read a file in full only when the diff cannot answer the question. Post your answer (for a review request, one summary comment via `gh pr comment`) by three quarters of that budget at the latest, saying plainly what you did not get to."
|
|
174
|
+
--allowed-tools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh issue view:*),Read,Grep,Glob"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: pr-title
|
|
2
|
+
|
|
3
|
+
# Reusable: the PR title becomes the squash commit subject, and that subject becomes the
|
|
4
|
+
# changelog line — so the title must be a conventional commit. Make this check required.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
workflow_call:
|
|
8
|
+
inputs:
|
|
9
|
+
tool-spec:
|
|
10
|
+
description: "What `uvx --from` installs, e.g. `conventional-release==0.1.0`"
|
|
11
|
+
type: string
|
|
12
|
+
default: "conventional-release>=0.1,<0.2"
|
|
13
|
+
working-directory:
|
|
14
|
+
description: Directory holding the project's conventional-release config
|
|
15
|
+
type: string
|
|
16
|
+
default: "."
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
pr-title:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
steps:
|
|
24
|
+
# For the project's configured types; nothing from the PR is executed.
|
|
25
|
+
- uses: actions/checkout@v7
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
|
|
29
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
30
|
+
|
|
31
|
+
- name: Title is a conventional commit
|
|
32
|
+
working-directory: ${{ inputs.working-directory }}
|
|
33
|
+
env:
|
|
34
|
+
TOOL: ${{ inputs.tool-spec }}
|
|
35
|
+
TITLE: ${{ github.event.pull_request.title }}
|
|
36
|
+
run: uvx --from "$TOOL" conventional-release check-title "$TITLE"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: pr
|
|
2
|
+
|
|
3
|
+
# This repo checks its own PR titles with its own checkout of the tool.
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
pull_request:
|
|
7
|
+
types: [opened, edited, synchronize, reopened]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
pr-title:
|
|
14
|
+
uses: ./.github/workflows/pr-title.yml
|
|
15
|
+
with:
|
|
16
|
+
tool-spec: "."
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# The project releases itself: `make release` opens the release PR; merging it lands here.
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
tag:
|
|
14
|
+
uses: ./.github/workflows/tag.yml
|
|
15
|
+
permissions:
|
|
16
|
+
contents: write
|
|
17
|
+
with:
|
|
18
|
+
tool-spec: "."
|
|
19
|
+
|
|
20
|
+
build:
|
|
21
|
+
needs: tag
|
|
22
|
+
if: needs.tag.outputs.released == 'true'
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v7
|
|
26
|
+
with:
|
|
27
|
+
ref: ${{ needs.tag.outputs.tag }}
|
|
28
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
29
|
+
- run: uv build
|
|
30
|
+
- uses: actions/upload-artifact@v7
|
|
31
|
+
with:
|
|
32
|
+
name: dist
|
|
33
|
+
path: dist/
|
|
34
|
+
|
|
35
|
+
testpypi:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment: testpypi
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write # trusted publishing, no token stored anywhere
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/download-artifact@v8
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
47
|
+
with:
|
|
48
|
+
repository-url: https://test.pypi.org/legacy/
|
|
49
|
+
|
|
50
|
+
pypi:
|
|
51
|
+
needs: [tag, testpypi]
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
environment: pypi # required reviewer: the maintainer
|
|
54
|
+
permissions:
|
|
55
|
+
id-token: write
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/download-artifact@v8
|
|
58
|
+
with:
|
|
59
|
+
name: dist
|
|
60
|
+
path: dist/
|
|
61
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
62
|
+
|
|
63
|
+
# `uses: MdaaaaO/conventional-release/.github/workflows/tag.yml@v0` follows the latest 0.x.
|
|
64
|
+
major-tag:
|
|
65
|
+
needs: [tag, pypi]
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
permissions:
|
|
68
|
+
contents: write
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v7
|
|
71
|
+
with:
|
|
72
|
+
ref: ${{ needs.tag.outputs.tag }}
|
|
73
|
+
- env:
|
|
74
|
+
TAG: ${{ needs.tag.outputs.tag }}
|
|
75
|
+
run: |
|
|
76
|
+
major="${TAG%%.*}"
|
|
77
|
+
git tag -f "$major" "$TAG^{commit}"
|
|
78
|
+
git push -f origin "refs/tags/$major"
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
name: tag
|
|
2
|
+
|
|
3
|
+
# Reusable: the CI half of a release. Call it on every push to the default branch. When the
|
|
4
|
+
# pushed commit is a squash-merged `chore(release): X.Y.Z`, it tags that commit vX.Y.Z and
|
|
5
|
+
# publishes a GitHub Release with the version's CHANGELOG section; otherwise it does nothing.
|
|
6
|
+
#
|
|
7
|
+
# Run your publish jobs *after* it in the same workflow (`needs: tag`, `if: released`): a tag
|
|
8
|
+
# pushed with GITHUB_TOKEN starts no other workflow, so `on: push: tags` would never fire.
|
|
9
|
+
# The caller grants `contents: write`.
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
workflow_call:
|
|
13
|
+
inputs:
|
|
14
|
+
tool-spec:
|
|
15
|
+
description: "What `uvx --from` installs, e.g. `conventional-release==0.1.0`"
|
|
16
|
+
type: string
|
|
17
|
+
default: "conventional-release>=0.1,<0.2"
|
|
18
|
+
working-directory:
|
|
19
|
+
description: Directory of the project inside the repository
|
|
20
|
+
type: string
|
|
21
|
+
default: "."
|
|
22
|
+
github-release:
|
|
23
|
+
description: Publish a GitHub Release with the changelog section
|
|
24
|
+
type: boolean
|
|
25
|
+
default: true
|
|
26
|
+
outputs:
|
|
27
|
+
released:
|
|
28
|
+
description: "'true' when this run created the tag"
|
|
29
|
+
value: ${{ jobs.tag.outputs.released }}
|
|
30
|
+
version:
|
|
31
|
+
description: The released version, e.g. 1.4.0
|
|
32
|
+
value: ${{ jobs.tag.outputs.version }}
|
|
33
|
+
tag:
|
|
34
|
+
description: The tag, e.g. v1.4.0
|
|
35
|
+
value: ${{ jobs.tag.outputs.tag }}
|
|
36
|
+
|
|
37
|
+
jobs:
|
|
38
|
+
tag:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
permissions:
|
|
41
|
+
contents: write
|
|
42
|
+
outputs:
|
|
43
|
+
released: ${{ steps.detect.outputs.released }}
|
|
44
|
+
version: ${{ steps.detect.outputs.version }}
|
|
45
|
+
tag: ${{ steps.detect.outputs.tag }}
|
|
46
|
+
defaults:
|
|
47
|
+
run:
|
|
48
|
+
working-directory: ${{ inputs.working-directory }}
|
|
49
|
+
env:
|
|
50
|
+
TOOL: ${{ inputs.tool-spec }}
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v7
|
|
53
|
+
with:
|
|
54
|
+
fetch-depth: 0
|
|
55
|
+
|
|
56
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
57
|
+
|
|
58
|
+
- id: detect
|
|
59
|
+
name: Is this a release commit?
|
|
60
|
+
run: uvx --from "$TOOL" conventional-release detect --github-output
|
|
61
|
+
|
|
62
|
+
- name: Tag the release commit
|
|
63
|
+
if: steps.detect.outputs.released == 'true'
|
|
64
|
+
env:
|
|
65
|
+
VERSION: ${{ steps.detect.outputs.version }}
|
|
66
|
+
run: |
|
|
67
|
+
git config user.name "github-actions[bot]"
|
|
68
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
69
|
+
uvx --from "$TOOL" conventional-release tag "$VERSION" --push
|
|
70
|
+
|
|
71
|
+
- name: GitHub Release
|
|
72
|
+
if: steps.detect.outputs.released == 'true' && inputs.github-release
|
|
73
|
+
env:
|
|
74
|
+
GH_TOKEN: ${{ github.token }}
|
|
75
|
+
VERSION: ${{ steps.detect.outputs.version }}
|
|
76
|
+
TAG: ${{ steps.detect.outputs.tag }}
|
|
77
|
+
run: |
|
|
78
|
+
uvx --from "$TOOL" conventional-release notes "$VERSION" > "$RUNNER_TEMP/notes.md"
|
|
79
|
+
gh release create "$TAG" --title "$TAG" --notes-file "$RUNNER_TEMP/notes.md" --verify-tag
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. Generated by
|
|
4
|
+
[conventional-release](https://github.com/MdaaaaO/conventional-release) from
|
|
5
|
+
[Conventional Commits](https://www.conventionalcommits.org).
|
|
6
|
+
|
|
7
|
+
## 0.1.0 (2026-09-25)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* standard-version-style changelog and release PRs from conventional commits ([12737d1](https://github.com/MdaaaaO/conventional-release/commit/12737d1e37eda9b5dc2dcd1e090d178a2af90a64))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Documentation
|
|
16
|
+
|
|
17
|
+
* readme, contributing guide and security policy ([3ff7da2](https://github.com/MdaaaaO/conventional-release/commit/3ff7da253f1f06669185f5e7862dc5c771d73ecb))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Tests
|
|
21
|
+
|
|
22
|
+
* changelog shape, version files and the release flow on throwaway repos ([a53ac38](https://github.com/MdaaaaO/conventional-release/commit/a53ac38a4933d831520baa8b35e332ab4d1ee91b))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Build System
|
|
26
|
+
|
|
27
|
+
* make targets for ci, build and release ([29cad9f](https://github.com/MdaaaaO/conventional-release/commit/29cad9fe7e452941b3bee0dc9eb8ed91b6e58c57))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### CI
|
|
31
|
+
|
|
32
|
+
* reusable tag and pr-title workflows; the project releases itself to PyPI ([a23b86b](https://github.com/MdaaaaO/conventional-release/commit/a23b86bcb75c1ece841d201128ee123887aacd45))
|
|
33
|
+
* pin astral-sh/setup-uv to v10.2.0 ([#1](https://github.com/MdaaaaO/conventional-release/issues/1)) ([9ba8212](https://github.com/MdaaaaO/conventional-release/commit/9ba821294387fe13173dbfb50cae0ebc731b26dc))
|
|
34
|
+
* claude review on pull requests ([#2](https://github.com/MdaaaaO/conventional-release/issues/2)) ([dbacb35](https://github.com/MdaaaaO/conventional-release/commit/dbacb3580efb2a94378b7b71db0c92cdf56a8b68))
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping. The short version:
|
|
4
|
+
|
|
5
|
+
- **Open an issue first** for anything bigger than a typo, so we agree on the change before you write it.
|
|
6
|
+
- **PR titles are [Conventional Commits](https://www.conventionalcommits.org).** PRs are
|
|
7
|
+
squash-merged, the title becomes the commit, and the commit becomes the changelog line. The
|
|
8
|
+
`pr-title` check enforces this (`feat(cli): add --json`, `fix: …`, `docs: …`). Put `!` after
|
|
9
|
+
the type or scope for a breaking change, and explain it in a `BREAKING CHANGE:` footer in the
|
|
10
|
+
PR description.
|
|
11
|
+
- **`make ci` passes locally** before you push. It runs ruff, `mypy --strict`, pytest with branch
|
|
12
|
+
coverage, and actionlint. You need [uv](https://docs.astral.sh/uv/). Run `make install` once.
|
|
13
|
+
- An automated Claude review comments on each PR from this repo's branches. It is advisory; a
|
|
14
|
+
maintainer decides. Maintainers can ask it again after a fix push with `@claude review`.
|
|
15
|
+
- New behaviour comes with a test. The tests build throwaway git repos in `tmp_path`; see
|
|
16
|
+
`tests/conftest.py`.
|
|
17
|
+
|
|
18
|
+
## Releasing (maintainers)
|
|
19
|
+
|
|
20
|
+
`make release` (or `make release ARGS=minor`) opens the `chore(release): X.Y.Z` PR. Squash-merge
|
|
21
|
+
it with the title unchanged. `release.yml` then tags the merge commit, publishes the GitHub
|
|
22
|
+
Release, publishes to TestPyPI and then to PyPI (the `pypi` environment waits for approval), and
|
|
23
|
+
moves the `v0` major tag. `make release-dry` shows what would ship.
|