1- name : Create Release
1+ name : Release and Publish PyPI
22
33on :
4- push :
5- branches :
6- - master
7- paths-ignore :
8- - README.md
9- - .gitignore
4+ push :
5+ branches :
6+ - main
7+ - master
8+ paths :
9+ - src/**
10+ - pyproject.toml
11+ - uv.lock
12+ workflow_dispatch :
13+
14+ permissions :
15+ contents : write
16+
17+ concurrency :
18+ group : release-${{ github.ref }}
19+ cancel-in-progress : false
1020
1121jobs :
12- release :
13- name : Create Release
14- runs-on : ubuntu-latest
15-
16- steps :
17- - name : Check out the repo
18- uses : actions/checkout@v4.1.7
19- with :
20- token : ${{ secrets.RELEASE_GIT_TOKEN }}
21- - name : Update version in pyproject.toml
22- id : version_bump
23- run : |
24- OLD_VERSION=$(awk -F ' = ' '/^version =/ {gsub(/"/, "", $2); print $2}' pyproject.toml)
25-
26- IFS='.' read -r -a V_PARTS <<< "$OLD_VERSION"
27- V_PARTS[2]=$((V_PARTS[2] + 1))
28- NEW_VERSION="${V_PARTS[0]}.${V_PARTS[1]}.${V_PARTS[2]}"
29-
30- # Using awk for safer replacement
31- awk -v old="version = \"$OLD_VERSION\"" -v new="version = \"$NEW_VERSION\"" '{gsub(old, new)}1' pyproject.toml > pyproject.toml.tmp && mv pyproject.toml.tmp pyproject.toml
32-
33- echo "New version: $NEW_VERSION"
34- echo "VERSION=$NEW_VERSION" >> "$GITHUB_OUTPUT"
35- - name : Commit and push changes
36- run : |
37- git config --global user.email "github@actions.com"
38- git config --global user.name "GitHub Actions"
39- git add pyproject.toml
40- if [[ -n "$(git diff --cached)" ]]; then
41- git commit -m "Bump version to ${{ steps.version_bump.outputs.VERSION }} [skip ci]"
42- git push
43- else
44- echo "No changes to commit"
45- fi
46- - name : Extract version from pyproject.toml
47- id : extract_metadata
48- run : |
49- VERSION=$(awk -F ' = ' '/^version =/ {gsub(/"/, "", $2); print $2}' ./pyproject.toml)
50- echo "version=$VERSION" >> "$GITHUB_OUTPUT"
51- shell : bash
52- - name : Release New Version
53- uses : softprops/action-gh-release@v1
54- with :
55- name : v${{ steps.extract_metadata.outputs.version }}
56- tag_name : v${{ steps.extract_metadata.outputs.version }}
57- token : ${{ secrets.RELEASE_GIT_TOKEN }}
22+ release :
23+ name : Set CalVer and create GitHub release
24+ if : github.actor != 'github-actions[bot]'
25+ runs-on : ubuntu-latest
26+
27+ outputs :
28+ version : ${{ steps.version.outputs.version }}
29+ tag : ${{ steps.version.outputs.tag }}
30+
31+ steps :
32+ - name : Check out the repository
33+ uses : actions/checkout@v4
34+ with :
35+ fetch-depth : 0
36+
37+ - name : Set up uv
38+ uses : astral-sh/setup-uv@v6
39+ with :
40+ python-version : " 3.12"
41+ enable-cache : true
42+ cache-dependency-glob : uv.lock
43+
44+ - name : Compute and set CalVer in pyproject.toml
45+ id : version
46+ shell : bash
47+ run : |
48+ set -euo pipefail
49+
50+ git fetch --tags --force
51+
52+ OLD_VERSION="$(uv version --short)"
53+ YEAR="$(date -u +%Y)"
54+ MONTH="$((10#$(date -u +%m)))"
55+ DAY="$((10#$(date -u +%d)))"
56+ CALVER_PREFIX="${YEAR}.${MONTH}.${DAY}"
57+
58+ NEXT_BUILD=1
59+ while read -r TAG_LINE; do
60+ BUILD="${TAG_LINE#v${CALVER_PREFIX}.}"
61+ if [[ "${BUILD}" =~ ^[0-9]+$ ]] && (( BUILD >= NEXT_BUILD )); then
62+ NEXT_BUILD=$((BUILD + 1))
63+ fi
64+ done < <(git tag --list "v${CALVER_PREFIX}.*")
65+
66+ NEW_VERSION="${CALVER_PREFIX}.${NEXT_BUILD}"
67+ uv version "${NEW_VERSION}" --frozen
68+
69+ TAG="v${NEW_VERSION}"
70+
71+ echo "old_version=${OLD_VERSION}" >> "${GITHUB_OUTPUT}"
72+ echo "version=${NEW_VERSION}" >> "${GITHUB_OUTPUT}"
73+ echo "tag=${TAG}" >> "${GITHUB_OUTPUT}"
74+
75+ - name : Commit version bump and push
76+ shell : bash
77+ run : |
78+ set -euo pipefail
79+ git config --global user.name "github-actions[bot]"
80+ git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
81+
82+ git add pyproject.toml
83+ if git diff --cached --quiet; then
84+ echo "No version changes detected"
85+ else
86+ git commit -m "release: bump version to ${{ steps.version.outputs.tag }} [skip ci]"
87+ git push origin HEAD:${GITHUB_REF_NAME}
88+ fi
89+
90+ if git rev-parse "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then
91+ echo "Tag ${{ steps.version.outputs.tag }} already exists"
92+ else
93+ git tag "${{ steps.version.outputs.tag }}"
94+ git push origin "${{ steps.version.outputs.tag }}"
95+ fi
96+
97+ - name : Create GitHub release
98+ uses : softprops/action-gh-release@v2
99+ with :
100+ name : ${{ steps.version.outputs.tag }}
101+ tag_name : ${{ steps.version.outputs.tag }}
102+ generate_release_notes : true
103+ env :
104+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
105+
106+ publish :
107+ name : Build and publish to PyPI
108+ runs-on : ubuntu-latest
109+ needs : release
110+
111+ steps :
112+ - uses : actions/checkout@v4
113+ with :
114+ ref : ${{ needs.release.outputs.tag }}
115+
116+ - name : Set up uv
117+ uses : astral-sh/setup-uv@v6
118+ with :
119+ python-version : " 3.12"
120+ enable-cache : true
121+ cache-dependency-glob : uv.lock
122+
123+ - name : Build
124+ run : uv build
125+
126+ - name : Publish
127+ run : uv publish --token ${{ secrets.PYPI_TOKEN }}
0 commit comments