Skip to content

Commit b2a147f

Browse files
committed
Update release process, move to Github Action
1 parent ba5373e commit b2a147f

4 files changed

Lines changed: 141 additions & 114 deletions

File tree

.github/workflows/python-package.yml

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ permissions:
88
on:
99
push:
1010
branches:
11-
- master
12-
pull_request:
13-
tags:
14-
- 'v*'
11+
- master
12+
pull_request:
13+
1514
jobs:
1615
build:
1716

@@ -23,13 +22,6 @@ jobs:
2322

2423
steps:
2524
- uses: actions/checkout@v4
26-
- if: startsWith(github.ref, 'refs/tags/v')
27-
# Assume all tags starting with a v are version tags.
28-
name: Check if versiontag matches pyproject.toml
29-
run: |
30-
VERSION_NUMBER="${GITHUB_REF_NAME:1}"
31-
echo Version $VERSION_NUMBER extracted from $GITHUB_REF_NAME
32-
grep "version = \"$VERSION_NUMBER\"" pyproject.toml
3325
- name: Set up Python ${{ matrix.python-version }}
3426
uses: actions/setup-python@v5
3527
with:

.github/workflows/release.yml

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'New version number (e.g. 6.3.0)'
8+
required: true
9+
type: string
10+
11+
jobs:
12+
validate:
13+
name: Validate version
14+
runs-on: ubuntu-latest
15+
outputs:
16+
version: ${{ steps.check.outputs.version }}
17+
steps:
18+
- uses: actions/checkout@v4
19+
- name: Check version is valid and greater than current
20+
id: check
21+
run: |
22+
NEW="${{ inputs.version }}"
23+
24+
# Must match semver X.Y.Z
25+
if ! echo "$NEW" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
26+
echo "::error::Version '$NEW' is not valid semver (expected X.Y.Z)"
27+
exit 1
28+
fi
29+
30+
CURRENT=$(grep -E '^version\s*=\s*"[0-9]+' pyproject.toml | head -n1 \
31+
| sed -E 's/.*version\s*=\s*"([^"]+)".*/\1/')
32+
33+
echo "Current version: $CURRENT"
34+
echo "Requested version: $NEW"
35+
36+
version_key() {
37+
echo "$1" | awk -F. '{ printf "%05d%05d%05d", $1, $2, $3 }'
38+
}
39+
40+
if [ "$(version_key "$NEW")" -le "$(version_key "$CURRENT")" ]; then
41+
echo "::error::New version ($NEW) must be greater than current version ($CURRENT)"
42+
exit 1
43+
fi
44+
45+
echo "version=$NEW" >> "$GITHUB_OUTPUT"
46+
47+
test:
48+
name: Test (Python ${{ matrix.python-version }})
49+
needs: validate
50+
runs-on: ubuntu-latest
51+
strategy:
52+
fail-fast: true
53+
matrix:
54+
python-version: ["3.11", "3.12", "3.13", "3.14"]
55+
steps:
56+
- uses: actions/checkout@v4
57+
- name: Set up Python ${{ matrix.python-version }}
58+
uses: actions/setup-python@v5
59+
with:
60+
python-version: ${{ matrix.python-version }}
61+
cache: 'pip'
62+
- name: Install dependencies
63+
run: |
64+
python -m pip install --upgrade pip
65+
python -m pip install flake8
66+
pip install . .[dev]
67+
- name: Lint with flake8
68+
run: |
69+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
70+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
71+
- name: Check typing with mypy
72+
run: mypy src/ynca --check-untyped-defs
73+
- name: Test with pytest
74+
run: pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=ynca --cov-report=xml --cov-report=html
75+
76+
release:
77+
name: Bump, tag and create draft release
78+
needs: test
79+
runs-on: ubuntu-latest
80+
permissions:
81+
contents: write
82+
steps:
83+
- name: Generate GitHub App token
84+
id: app-token
85+
uses: actions/create-github-app-token@v1
86+
with:
87+
app-id: ${{ secrets.GH_APP_ID }}
88+
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
89+
90+
- uses: actions/checkout@v4
91+
with:
92+
token: ${{ steps.app-token.outputs.token }}
93+
ref: master
94+
95+
- name: Bump version in pyproject.toml
96+
run: |
97+
NEW="${{ needs.validate.outputs.version }}"
98+
awk -v newver="$NEW" '
99+
BEGIN{inproj=0;done=0}
100+
/^\[project\]/{inproj=1}
101+
inproj && !done && /version\s*=/{sub(/version\s*=\s*"[^"]+"/, "version = \"" newver "\""); done=1}
102+
{print}
103+
' pyproject.toml > pyproject.toml.tmp && mv pyproject.toml.tmp pyproject.toml
104+
105+
- name: Commit, tag and push
106+
run: |
107+
NEW="${{ needs.validate.outputs.version }}"
108+
git config user.name "github-actions[bot]"
109+
git config user.email "github-actions[bot]@users.noreply.github.com"
110+
git add pyproject.toml
111+
git commit -m "Bump ynca version to $NEW"
112+
git tag -a "v$NEW" -m "Version $NEW"
113+
git push --follow-tags
114+
115+
- name: Create draft release
116+
env:
117+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
118+
run: |
119+
NEW="${{ needs.validate.outputs.version }}"
120+
gh release create "v$NEW" \
121+
--draft \
122+
--generate-notes \
123+
--title "v$NEW"

bump_version.sh

Lines changed: 0 additions & 94 deletions
This file was deleted.

docs/DEVELOPING.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,27 @@ CI is a bit barebones, but it does:
2525

2626
* Run mypy
2727
* Run tests
28-
* When pushing a version tag a sanity check is done against the version number in `pyproject.toml` to make sure they match
2928
* When a release is made it gets automatically uploaded to PyPi.
3029

3130
For details see the task files under `.github/workflows`
3231

3332
## Releasing
3433

35-
Releasing is not difficult, but could be a bit more automated.
34+
Releasing is triggered from GitHub Actions — no local steps required.
3635

37-
* Do any tests you want to do before release, e.g. run `coverage.sh`
38-
* Run `bump_version.sh` script and follow the prompts. When completed a version tag has been created and pushed to Github
39-
* Wait a bit until [the actions](https://github.com/mvdwetering/ynca/actions) are all done without errors
40-
* [On Github](https://github.com/mvdwetering/ynca/tags) create a release from the tag that was pushed
41-
* Release title is the version e.g. v5.27.0
42-
* Write the release notes and save
43-
* The package will be automatically uploaded to PyPi
36+
1. Go to [Actions → Release](https://github.com/mvdwetering/ynca/actions/workflows/release.yml) and click **Run workflow**
37+
2. Enter the new version number (e.g. `6.3.0`) and confirm
38+
3. The workflow validates the version, runs the full test matrix, bumps `pyproject.toml`, commits, tags, and creates a **draft** GitHub Release with auto-generated notes
39+
4. Open the draft release, edit the notes to highlight breaking changes or exciting features, then click **Publish release**
40+
* Publishing automatically uploads the package to PyPI
41+
42+
### Prerequisites (one-time setup)
43+
44+
The workflow uses a GitHub App token to push to the branch-protected `master` branch.
45+
The following repository secrets must be configured:
46+
47+
* `GH_APP_ID` — the App ID of the release GitHub App
48+
* `GH_APP_PRIVATE_KEY` — the private key (`.pem` contents) of that App
4449

4550
## Adding Commands
4651

@@ -49,6 +54,7 @@ Releasing is not difficult, but could be a bit more automated.
4954
> The format can just be some logging.
5055
>
5156
> Example prompt that generated the implementation in [#63](https://github.com/mvdwetering/ynca/pull/63) (and a follow-up prompt to add the other variants)
57+
>
5258
> ```text
5359
> Add a command based on this data: "3618651.006055 Received: @sys:SPPATTERN1SWFR1CNFG=None","3618657.598930 Received: @sys:SPPATTERN1SWFR1CNFG=Use",
5460
>```

0 commit comments

Comments
 (0)