11name : Build & Release CAN Tool
22
33on :
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 :
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