Skip to content

Commit 561f5af

Browse files
committed
CI: idempotent release with gh CLI; flatten artifacts; fix 404 updates
1 parent 817a2b7 commit 561f5af

1 file changed

Lines changed: 58 additions & 18 deletions

File tree

.github/workflows/build-and-release.yml

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Build & Release CAN Tool
22

33
on:
4-
# Run on tags like v1.2.3, and allow manual runs.
4+
# Only build on tags like v1.2.3 (and allow manual runs from Actions tab)
55
push:
66
tags:
77
- 'v*'
@@ -20,19 +20,19 @@ jobs:
2020
os: [ubuntu-latest, windows-latest, macos-latest]
2121

2222
steps:
23-
# 1) Check out code
23+
# 1) Check out repo
2424
- name: Checkout
2525
uses: actions/checkout@v4
2626

27-
# 2) Setup Node 20 + npm cache based on the frontend lockfile
27+
# 2) Setup Node 20 + enable npm cache keyed by frontend lockfile
2828
- name: Setup Node
2929
uses: actions/setup-node@v4
3030
with:
3131
node-version: 20
3232
cache: npm
3333
cache-dependency-path: frontend/package-lock.json
3434

35-
# 3) Setup Python 3.12 (for PyInstaller build)
35+
# 3) Setup Python 3.12 (needed for PyInstaller)
3636
- name: Setup Python
3737
uses: actions/setup-python@v5
3838
with:
@@ -44,8 +44,9 @@ jobs:
4444
working-directory: frontend
4545
run: npm ci
4646

47-
# 5) Ensure Rollup has the correct native binary for this OS
48-
# This fixes the "Cannot find module @rollup/rollup-<platform>" error.
47+
# 5) Ensure Rollup has the right native binary for THIS runner OS.
48+
# This fixes:
49+
# "Cannot find module @rollup/rollup-<platform>"
4950
- name: Ensure Rollup native binary for this OS
5051
shell: bash
5152
working-directory: frontend
@@ -68,28 +69,29 @@ jobs:
6869
working-directory: frontend
6970
run: npm run build
7071

71-
# 7) Copy built frontend into backend/static for packaging
72+
# 7) Copy built frontend into backend/static so the backend can serve it
7273
- name: Stage frontend assets into backend/static
7374
shell: bash
7475
run: |
7576
mkdir -p backend/static
7677
cp -r frontend/dist/* backend/static/
7778
78-
# 8) Install backend deps and PyInstaller
79+
# 8) Install backend deps + PyInstaller
7980
- name: Install backend deps
8081
run: |
8182
python -m pip install --upgrade pip
8283
pip install -r backend/requirements.txt
8384
pip install pyinstaller
8485
85-
# 9) Build the executable with PyInstaller spec
86+
# 9) Build the executable via your PyInstaller spec
8687
- name: PyInstaller build
8788
run: pyinstaller can-tool.spec
8889

89-
# 10) Upload the per-OS build output as artifacts
90+
# 10) Upload each OS build output as an artifact
9091
- name: Upload artifacts
9192
uses: actions/upload-artifact@v4
9293
with:
94+
# Artifact name includes OS + commit so each runner uploads a unique bundle
9395
name: can-tool-${{ matrix.os }}-${{ github.sha }}
9496
path: dist/*
9597
if-no-files-found: error
@@ -98,17 +100,55 @@ jobs:
98100
name: Create Release
99101
needs: build
100102
runs-on: ubuntu-latest
103+
permissions:
104+
contents: write # explicit here too
105+
101106
steps:
102-
# 11) Download all artifacts from the matrix builds
107+
# 11) Download ALL artifacts from the matrix builds into one folder.
108+
# merge-multiple: true flattens artifacts into ./dist/
103109
- name: Download all artifacts
104110
uses: actions/download-artifact@v4
105111
with:
106-
path: ./dist
112+
path: dist
113+
merge-multiple: true
107114

108-
# 12) Create (or update) a GitHub Release for the pushed tag and attach the files
109-
- name: Create GitHub Release
110-
uses: softprops/action-gh-release@v2
111-
with:
112-
files: ./dist/**/* # upload everything we just downloaded
115+
- name: List downloaded files
116+
shell: bash
117+
run: |
118+
echo "Files in dist/:"
119+
ls -lah dist
120+
121+
# 12) Create or update the GitHub Release & upload assets idempotently.
122+
# - If the release for this tag exists, we just upload/overwrite assets.
123+
# - If it doesn't, we create it then upload.
124+
- name: Create or update release (idempotent) and upload assets
125+
shell: bash
113126
env:
114-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
127+
GH_TOKEN: ${{ github.token }} # auth for gh cli
128+
TAG: ${{ github.ref_name }} # e.g. v0.0.3
129+
run: |
130+
set -euo pipefail
131+
132+
echo "Using tag: $TAG"
133+
134+
if gh release view "$TAG" >/dev/null 2>&1; then
135+
echo "Release $TAG already exists. Will upload and overwrite assets as needed."
136+
else
137+
echo "Creating new release $TAG"
138+
gh release create "$TAG" \
139+
--title "$TAG" \
140+
--notes "Automated release for $TAG"
141+
fi
142+
143+
shopt -s nullglob
144+
files=(dist/*)
145+
if (( ${#files[@]} == 0 )); then
146+
echo "No files found in dist/ — failing."
147+
exit 1
148+
fi
149+
150+
echo "Uploading ${#files[@]} file(s) to release $TAG:"
151+
printf ' - %s\n' "${files[@]}"
152+
153+
# --clobber overwrites assets with the same filename (idempotent)
154+
gh release upload "$TAG" "${files[@]}" --clobber

0 commit comments

Comments
 (0)