Skip to content

Commit dd215bb

Browse files
authored
Merge pull request #227 from shanejbrown/version-fix2
Make version bump manual and add PR version check
2 parents 3a10e91 + 51a7498 commit dd215bb

4 files changed

Lines changed: 80 additions & 36 deletions

File tree

.github/workflows/build.yaml

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,8 @@ jobs:
5757
check_name: "Test Results ${{ matrix.python-version }}"
5858
github_retries: 10
5959
secondary_rate_limit_wait_seconds: 60.0
60-
# Version source of truth: pyproject.toml [project] version.
61-
# - Patch: CI bumps patch on every push to main (and commits it).
62-
# - Minor/major: Update version in pyproject.toml (e.g. uv version 3.22.0 or uv version --bump minor),
63-
# merge with message "Release 3.22.0"; CI will use that version as-is and tag it.
60+
# Version source of truth: pyproject.toml [project] version. User must update it before merging to main.
61+
# PRs are checked so that version differs from main. On push to main, CI tags and publishes that version.
6462
get-version:
6563
if: github.repository == 'adobe/buildrunner'
6664
runs-on: ubuntu-latest
@@ -69,7 +67,6 @@ jobs:
6967
contents: write
7068
outputs:
7169
current-version: ${{ steps.version-number.outputs.CURRENT_VERSION }}
72-
should-tag: ${{ steps.tag-decision.outputs.should_tag }}
7370
steps:
7471
- uses: actions/checkout@v2
7572
with:
@@ -80,31 +77,74 @@ jobs:
8077
python-version: 3.9
8178
- name: Install dependencies
8279
run: uv sync --locked
83-
- name: Bump version (patch only when not the bot’s bump commit)
84-
id: bump
85-
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'Bump version to')
86-
run: uv version --bump patch
8780
- name: Get current version
8881
id: version-number
8982
run: echo "CURRENT_VERSION=$(uv version --short)" >> $GITHUB_OUTPUT
9083
- name: Print current version
9184
run: echo CURRENT_VERSION ${{ steps.version-number.outputs.CURRENT_VERSION }}
92-
- name: Set tag/publish decision
93-
id: tag-decision
94-
run: |
95-
if [ "${{ steps.bump.outcome }}" = "success" ]; then echo "should_tag=true" >> $GITHUB_OUTPUT; exit 0; fi
96-
echo "should_tag=false" >> $GITHUB_OUTPUT
97-
- name: Print tag decision
98-
run: echo "should_tag=${{ steps.tag-decision.outputs.should_tag }}"
99-
- name: Commit and push version bump
100-
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'Bump version to')
85+
# PR check: version must differ from main and be strictly greater (semver: major.minor.patch).
86+
# MAJOR may not decrease; MINOR may not decrease unless MAJOR increased; PATCH may not decrease unless MAJOR or MINOR changed.
87+
version-changed:
88+
if: github.repository == 'adobe/buildrunner' && github.event_name == 'pull_request'
89+
runs-on: ubuntu-latest
90+
steps:
91+
- uses: actions/checkout@v2
92+
with:
93+
fetch-depth: 0
94+
- name: Install uv
95+
uses: astral-sh/setup-uv@v6
96+
with:
97+
python-version: 3.9
98+
- name: Check version increased from main
10199
run: |
102-
git config user.name "github-actions[bot]"
103-
git config user.email "github-actions[bot]@users.noreply.github.com"
104-
git add pyproject.toml uv.lock
105-
git diff --staged --quiet || (git commit -m "Bump version to ${{ steps.version-number.outputs.CURRENT_VERSION }}" && git push)
100+
PR_VERSION=$(uv version --short)
101+
git fetch origin main
102+
MAIN_VERSION=$(git show origin/main:pyproject.toml | sed -n 's/^version *= *"\(.*\)".*/\1/p' | tr -d ' ')
103+
if [ -z "$MAIN_VERSION" ]; then
104+
echo "Could not read version from main's pyproject.toml"
105+
exit 1
106+
fi
107+
# Parse major.minor.patch (default missing to 0; e.g. "3" -> 3.0.0, "3.22" -> 3.22.0)
108+
main_major=$(echo "$MAIN_VERSION" | cut -d. -f1)
109+
main_minor=$(echo "$MAIN_VERSION" | cut -d. -f2)
110+
main_patch=$(echo "$MAIN_VERSION" | cut -d. -f3)
111+
[ -z "$main_minor" ] && main_minor=0
112+
[ -z "$main_patch" ] && main_patch=0
113+
pr_major=$(echo "$PR_VERSION" | cut -d. -f1)
114+
pr_minor=$(echo "$PR_VERSION" | cut -d. -f2)
115+
pr_patch=$(echo "$PR_VERSION" | cut -d. -f3)
116+
[ -z "$pr_minor" ] && pr_minor=0
117+
[ -z "$pr_patch" ] && pr_patch=0
118+
# Require PR version strictly greater than main (at least one component increased, none decreased per semver rules)
119+
fail_msg="Version must be strictly greater than main ($MAIN_VERSION). Rules: MAJOR may not decrease; MINOR may not decrease unless MAJOR increased; PATCH may not decrease unless MAJOR or MINOR changed. Bump with e.g. \`uv version --bump patch\`."
120+
if [ "$pr_major" -lt "$main_major" ]; then
121+
echo "::error::MAJOR decreased ($main_major → $pr_major). $fail_msg"
122+
exit 1
123+
fi
124+
if [ "$pr_major" -gt "$main_major" ]; then
125+
echo "Version OK: $MAIN_VERSION → $PR_VERSION"
126+
exit 0
127+
fi
128+
if [ "$pr_minor" -lt "$main_minor" ]; then
129+
echo "::error::MINOR decreased ($main_minor → $pr_minor) without MAJOR increase. $fail_msg"
130+
exit 1
131+
fi
132+
if [ "$pr_minor" -gt "$main_minor" ]; then
133+
echo "Version OK: $MAIN_VERSION → $PR_VERSION"
134+
exit 0
135+
fi
136+
if [ "$pr_patch" -lt "$main_patch" ]; then
137+
echo "::error::PATCH decreased ($main_patch → $pr_patch) without MAJOR or MINOR change. $fail_msg"
138+
exit 1
139+
fi
140+
if [ "$pr_patch" -gt "$main_patch" ]; then
141+
echo "Version OK: $MAIN_VERSION → $PR_VERSION"
142+
exit 0
143+
fi
144+
echo "::error::Version unchanged ($MAIN_VERSION). $fail_msg"
145+
exit 1
106146
tag-commit:
107-
if: github.repository == 'adobe/buildrunner' && github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.get-version.outputs.should-tag == 'true'
147+
if: github.repository == 'adobe/buildrunner' && github.event_name == 'push' && github.ref == 'refs/heads/main'
108148
runs-on: ubuntu-latest
109149
needs: [test, get-version]
110150
steps:
@@ -115,7 +155,7 @@ jobs:
115155
- name: Tag commit
116156
run: git tag ${{ needs.get-version.outputs.current-version }} && git push --tags
117157
publish-pypi:
118-
if: github.repository == 'adobe/buildrunner' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.get-version.outputs.should-tag == 'true'))
158+
if: github.repository == 'adobe/buildrunner' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
119159
runs-on: ubuntu-latest
120160
needs: [test, get-version]
121161
steps:
@@ -142,7 +182,7 @@ jobs:
142182
user: __token__
143183
password: ${{ secrets.ADOBE_BOT_PYPI_TOKEN }}
144184
publish-docker:
145-
if: github.repository == 'adobe/buildrunner' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.get-version.outputs.should-tag == 'true'))
185+
if: github.repository == 'adobe/buildrunner' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main'))
146186
runs-on: ubuntu-latest
147187
needs: [test, get-version]
148188
steps:

VERSIONING.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
# Versioning
22

33
The **source of truth** for the version is `pyproject.toml``[project]``version`.
4-
CI uses that value and the resulting git tag as the release version.
4+
You are responsible for updating it for every release. CI tags and publishes whatever version is on `main` when you push.
55

66
## Where to update version
77

8-
- **Single place:** `pyproject.toml` — set `version = "X.Y.Z"` (e.g. `"3.21"` or `"3.21.0"`).
8+
- **Single place:** `pyproject.toml` — set `version = "X.Y.Z"` (e.g. `"3.22.0"`). You can use `uv version 3.22.0` or `uv version --bump patch` (etc.) and commit the change.
99

10-
## How versions are produced
10+
## Releasing (patch, minor, or major)
1111

1212
| You want | What to do |
1313
|----------|------------|
14-
| **Patch** (e.g. 3.21.0 → 3.21.1) | Nothing. Push to `main`; CI bumps patch, commits it, tags that version, and publishes. |
15-
| **Minor** (e.g. 3.21 → 3.22.0) | Update version in `pyproject.toml` (e.g. `uv version 3.22.0` or `uv version --bump minor`). Commit with message **`Release 3.22.0`** and merge to `main`. CI will use that version as-is (no bump), tag it, and publish. |
16-
| **Major** (e.g. 3.21 → 4.0.0) | Same as minor: set `version = "4.0.0"` in `pyproject.toml`, commit **`Release 4.0.0`**, merge to `main`. |
14+
| **Patch** (e.g. 3.22.0 → 3.22.1) | Run `uv version --bump patch` (or set `version = "3.22.1"` in `pyproject.toml`). Commit, open a PR to `main`, merge. CI will tag and publish. |
15+
| **Minor** (e.g. 3.22 → 3.23.0) | Run `uv version 3.23.0` or `uv version --bump minor`. Commit, open a PR to `main`, merge. CI will tag and publish. |
16+
| **Major** (e.g. 3.x → 4.0.0) | Set `version = "4.0.0"` in `pyproject.toml` (or `uv version 4.0.0`). Commit, open a PR to `main`, merge. CI will tag and publish. |
17+
18+
## PR check: version must increase
19+
20+
For every **pull request targeting `main`**, CI runs a check that the version in `pyproject.toml` is **strictly greater** than the version on `main`: at least one of major.minor.patch must increase, and none may decrease (except MINOR/PATCH may reset when MAJOR increases, or PATCH when MINOR increases). MAJOR may never decrease; MINOR may not decrease unless MAJOR increased; PATCH may not decrease unless MAJOR or MINOR changed. If the version is unchanged or violates these rules, the check fails.
1721

1822
## Summary
1923

20-
- **Track/update** major.minor.patch in **`pyproject.toml`**.
21-
- **Patch releases:** automatic on every push to `main` (CI bumps and commits).
22-
- **Minor/major releases:** set the version in `pyproject.toml` and use a commit message starting with **`Release X.Y.Z`** so CI does not bump again and tags that version.
24+
- **You** update the version in **`pyproject.toml`** for every release (patch, minor, or major).
25+
- Open a PR to `main`; CI will fail the “version changed” check until the version is updated.
26+
- After you merge to `main`, CI tags that version and publishes to PyPI and the container registry.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "uv_build"
44

55
[project]
66
name = "buildrunner"
7-
version = "3.22"
7+
version = "3.22.1"
88
description = "Docker-based build tool"
99
readme = "README.rst"
1010
requires-python = ">=3.9"

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)