@@ -3,6 +3,10 @@ name: treemapper CD
33
44permissions : {}
55
6+ concurrency :
7+ group : release
8+ cancel-in-progress : false
9+
610' on ' :
711 workflow_dispatch :
812 inputs :
@@ -28,12 +32,12 @@ jobs:
2832 commit_sha : ${{ steps.commit_version.outputs.commit_sha }}
2933 steps :
3034 - name : Checkout Code
31- uses : actions/checkout@v6
35+ uses : actions/checkout@v4
3236 with :
3337 fetch-depth : 0 # Need full history for git bundle
3438
3539 - name : Set up Python
36- uses : actions/setup-python@v6
40+ uses : actions/setup-python@v5
3741 with :
3842 python-version : ' 3.11'
3943
@@ -46,14 +50,33 @@ jobs:
4650 exit 1
4751 fi
4852
49- - name : Validate version format
53+ - name : Validate version format (PEP 440)
5054 run : |
5155 VERSION="${{ github.event.inputs.version }}"
52- if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
53- echo "Error: Invalid version format '$VERSION'. Expected semver like 1.0.0 or 1.0.0-rc1"
56+ # PEP 440: X.Y.Z with optional pre-release (a1, b1, rc1) or dev/post suffix
57+ if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?(\.dev[0-9]+)?(\.post[0-9]+)?$ ]]; then
58+ echo "Error: Invalid version format '$VERSION'."
59+ echo "Expected PEP 440 format: 1.0.0, 1.0.0a1, 1.0.0b1, 1.0.0rc1, 1.0.0.dev1, 1.0.0.post1"
60+ exit 1
61+ fi
62+ echo "Version format valid (PEP 440): $VERSION"
63+
64+ - name : Check version is not already set
65+ env :
66+ VERSION : ${{ github.event.inputs.version }}
67+ run : |
68+ CURRENT=$(python -c "
69+ import re
70+ content = open('src/treemapper/version.py').read()
71+ m = re.search(r'__version__\s*=\s*[\"'\'']([^\"'\'']+)[\"'\'']', content)
72+ print(m.group(1) if m else '')
73+ ")
74+ if [ "$CURRENT" = "$VERSION" ]; then
75+ echo "Error: version.py already contains version $VERSION"
76+ echo "Nothing to release - version is already set."
5477 exit 1
5578 fi
56- echo "Version format valid : $VERSION"
79+ echo "Current version: $CURRENT -> New version : $VERSION"
5780
5881 - name : Set version in version.py
5982 env :
@@ -112,7 +135,7 @@ jobs:
112135 git bundle create repo.bundle --all
113136
114137 - name : Upload bundle as artifact
115- uses : actions/upload-artifact@v6
138+ uses : actions/upload-artifact@v4
116139 with :
117140 name : git-repo-bundle
118141 path : repo.bundle
@@ -143,7 +166,7 @@ jobs:
143166 runs-on : ${{ matrix.os }}
144167 steps :
145168 - name : Download git bundle
146- uses : actions/download-artifact@v7
169+ uses : actions/download-artifact@v4
147170 with :
148171 name : git-repo-bundle
149172
@@ -164,18 +187,11 @@ jobs:
164187 ls -la src/treemapper/ || echo "ERROR: src/treemapper not found!"
165188
166189 - name : Set up Python
167- uses : actions/setup-python@v6
190+ uses : actions/setup-python@v5
168191 with :
169192 python-version : ${{ matrix.python-version }}
170-
171- - name : Cache pip Dependencies
172- uses : actions/cache@v5
173- with :
174- path : ~/.cache/pip
175- key : ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
176- restore-keys : |
177- ${{ runner.os }}-pip-${{ matrix.python-version }}-
178- ${{ runner.os }}-pip-
193+ cache : ' pip'
194+ cache-dependency-path : ' ./repo/pyproject.toml'
179195
180196 - name : Install Dependencies (including PyInstaller)
181197 shell : bash
@@ -194,8 +210,9 @@ jobs:
194210 shell : bash
195211 working-directory : ./repo
196212 run : |
197- # Ensure PyInstaller can find the modules
198- export PYTHONPATH="${PWD}/src:${PYTHONPATH}"
213+ # Ensure PyInstaller can find the modules (use correct path separator for OS)
214+ SEP=$(python -c "import os; print(os.pathsep)")
215+ export PYTHONPATH="${PWD}/src${SEP}${PYTHONPATH:-}"
199216 echo "PYTHONPATH: $PYTHONPATH"
200217
201218 # Run PyInstaller with explicit paths
@@ -234,7 +251,7 @@ jobs:
234251 fi
235252
236253 - name : Upload artifact
237- uses : actions/upload-artifact@v6
254+ uses : actions/upload-artifact@v4
238255 with :
239256 name : ${{ matrix.asset_name }}-binary
240257 path : ./repo/dist/treemapper-*
@@ -252,7 +269,7 @@ jobs:
252269 id-token : write
253270 steps :
254271 - name : Download git bundle
255- uses : actions/download-artifact@v7
272+ uses : actions/download-artifact@v4
256273 with :
257274 name : git-repo-bundle
258275
@@ -273,7 +290,7 @@ jobs:
273290 ls -la src/treemapper/ || echo "ERROR: src/treemapper not found!"
274291
275292 - name : Set up Python
276- uses : actions/setup-python@v6
293+ uses : actions/setup-python@v5
277294 with :
278295 python-version : ' 3.11'
279296
@@ -319,7 +336,7 @@ jobs:
319336 contents : write
320337 steps :
321338 - name : Download git bundle
322- uses : actions/download-artifact@v7
339+ uses : actions/download-artifact@v4
323340 with :
324341 name : git-repo-bundle
325342
@@ -337,16 +354,28 @@ jobs:
337354 # Set up remote to point to the actual GitHub repository
338355 git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git"
339356
340- # Verify remote is set up correctly
341- git remote -v
342-
343357 - name : Push commit and tag to main
344358 working-directory : ./repo
345359 run : |
346360 git config user.name "github-actions[bot]"
347361 # 41898282 is GitHub's bot user ID for github-actions[bot]
348362 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
349363
364+ # Fetch latest state of remote main
365+ git fetch origin main
366+
367+ # Check that remote main hasn't moved since we started the release
368+ # Our commit should be based on the current remote main HEAD
369+ REMOTE_MAIN=$(git rev-parse origin/main)
370+ OUR_PARENT=$(git rev-parse HEAD^)
371+ if [ "$REMOTE_MAIN" != "$OUR_PARENT" ]; then
372+ echo "Error: Remote main has changed since release started."
373+ echo "Expected parent: $OUR_PARENT"
374+ echo "Remote main: $REMOTE_MAIN"
375+ echo "Please re-run the release workflow."
376+ exit 1
377+ fi
378+
350379 # Push the version bump commit to main
351380 git push origin HEAD:main
352381
@@ -356,7 +385,7 @@ jobs:
356385 echo "Successfully pushed version commit and tag"
357386
358387 - name : Download all build artifacts
359- uses : actions/download-artifact@v7
388+ uses : actions/download-artifact@v4
360389 with :
361390 path : ./artifacts
362391
0 commit comments