1- name : Desktop Release
1+ name : Release
22
33on :
44 push :
1111 required : false
1212 default : " master"
1313 tag :
14- description : " Release tag to upload assets to (for example: v4.14.6)"
14+ description : " Release tag to publish assets to (for example: v4.14.6)"
1515 required : false
1616
1717permissions :
1818 contents : write
1919
2020jobs :
21+ build-dashboard :
22+ name : Build Dashboard
23+ runs-on : ubuntu-24.04
24+ steps :
25+ - name : Checkout repository
26+ uses : actions/checkout@v6
27+ with :
28+ fetch-depth : 0
29+ ref : ${{ inputs.ref || github.ref }}
30+
31+ - name : Resolve tag
32+ id : tag
33+ shell : bash
34+ run : |
35+ if [ "${{ github.event_name }}" = "push" ]; then
36+ tag="${GITHUB_REF_NAME}"
37+ elif [ -n "${{ inputs.tag }}" ]; then
38+ tag="${{ inputs.tag }}"
39+ else
40+ tag="$(git describe --tags --abbrev=0)"
41+ fi
42+ if [ -z "$tag" ]; then
43+ echo "Failed to resolve tag." >&2
44+ exit 1
45+ fi
46+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
47+
48+ - name : Setup pnpm
49+ uses : pnpm/action-setup@v4
50+ with :
51+ version : 10.28.2
52+
53+ - name : Setup Node.js
54+ uses : actions/setup-node@v6
55+ with :
56+ node-version : 20
57+ cache : " pnpm"
58+ cache-dependency-path : dashboard/pnpm-lock.yaml
59+
60+ - name : Build dashboard dist
61+ shell : bash
62+ run : |
63+ pnpm --dir dashboard install --frozen-lockfile
64+ pnpm --dir dashboard run build
65+ echo "${{ steps.tag.outputs.tag }}" > dashboard/dist/assets/version
66+ cd dashboard
67+ zip -r "AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip" dist
68+
69+ - name : Upload dashboard artifact
70+ uses : actions/upload-artifact@v6
71+ with :
72+ name : Dashboard-${{ steps.tag.outputs.tag }}
73+ if-no-files-found : error
74+ path : dashboard/AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip
75+
76+ - name : Upload dashboard package to Cloudflare R2
77+ if : ${{ secrets.R2_ACCOUNT_ID != '' && secrets.R2_ACCESS_KEY_ID != '' && secrets.R2_SECRET_ACCESS_KEY != '' }}
78+ env :
79+ R2_ACCOUNT_ID : ${{ secrets.R2_ACCOUNT_ID }}
80+ R2_ACCESS_KEY_ID : ${{ secrets.R2_ACCESS_KEY_ID }}
81+ R2_SECRET_ACCESS_KEY : ${{ secrets.R2_SECRET_ACCESS_KEY }}
82+ R2_BUCKET_NAME : " astrbot"
83+ R2_OBJECT_NAME : " astrbot-webui-latest.zip"
84+ VERSION_TAG : ${{ steps.tag.outputs.tag }}
85+ shell : bash
86+ run : |
87+ curl https://rclone.org/install.sh | sudo bash
88+
89+ mkdir -p ~/.config/rclone
90+ cat <<EOF > ~/.config/rclone/rclone.conf
91+ [r2]
92+ type = s3
93+ provider = Cloudflare
94+ access_key_id = $R2_ACCESS_KEY_ID
95+ secret_access_key = $R2_SECRET_ACCESS_KEY
96+ endpoint = https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com
97+ EOF
98+
99+ cp "dashboard/AstrBot-${VERSION_TAG}-dashboard.zip" "dashboard/${R2_OBJECT_NAME}"
100+ rclone copy "dashboard/${R2_OBJECT_NAME}" "r2:${R2_BUCKET_NAME}" --progress
101+ cp "dashboard/AstrBot-${VERSION_TAG}-dashboard.zip" "dashboard/astrbot-webui-${VERSION_TAG}.zip"
102+ rclone copy "dashboard/astrbot-webui-${VERSION_TAG}.zip" "r2:${R2_BUCKET_NAME}" --progress
103+
21104 build-desktop :
22105 name : Build ${{ matrix.name }}
23106 runs-on : ${{ matrix.runner }}
@@ -58,6 +141,23 @@ jobs:
58141 fetch-depth : 0
59142 ref : ${{ inputs.ref || github.ref }}
60143
144+ - name : Resolve tag
145+ id : tag
146+ shell : bash
147+ run : |
148+ if [ "${{ github.event_name }}" = "push" ]; then
149+ tag="${GITHUB_REF_NAME}"
150+ elif [ -n "${{ inputs.tag }}" ]; then
151+ tag="${{ inputs.tag }}"
152+ else
153+ tag="$(git describe --tags --abbrev=0)"
154+ fi
155+ if [ -z "$tag" ]; then
156+ echo "Failed to resolve tag." >&2
157+ exit 1
158+ fi
159+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
160+
61161 - name : Setup uv
62162 uses : astral-sh/setup-uv@v6
63163
@@ -81,36 +181,21 @@ jobs:
81181 desktop/pnpm-lock.yaml
82182
83183 - name : Install dependencies
184+ shell : bash
84185 run : |
85186 uv sync
86187 pnpm --dir dashboard install --frozen-lockfile
87188 pnpm --dir desktop install --frozen-lockfile
88189
89190 - name : Build desktop package
191+ shell : bash
90192 run : |
91193 pnpm --dir dashboard run build
92194 pnpm --dir desktop run build:webui
93195 pnpm --dir desktop run build:backend
94196 pnpm --dir desktop run sync:version
95197 pnpm --dir desktop exec electron-builder --publish never
96198
97- - name : Resolve artifact tag
98- id : tag
99- shell : bash
100- run : |
101- if [ "${{ github.event_name }}" = "push" ]; then
102- tag="${GITHUB_REF_NAME}"
103- elif [ -n "${{ inputs.tag }}" ]; then
104- tag="${{ inputs.tag }}"
105- else
106- tag="$(git describe --tags --abbrev=0)"
107- fi
108- if [ -z "$tag" ]; then
109- echo "Failed to resolve artifact tag." >&2
110- exit 1
111- fi
112- echo "tag=$tag" >> "$GITHUB_OUTPUT"
113-
114199 - name : Normalize artifact names
115200 shell : bash
116201 env :
@@ -160,17 +245,19 @@ jobs:
160245 path : desktop/dist/release/*
161246
162247 publish-release :
163- name : Publish Release Assets
248+ name : Publish GitHub Release
164249 runs-on : ubuntu-24.04
165- needs : build-desktop
250+ needs :
251+ - build-dashboard
252+ - build-desktop
166253 steps :
167254 - name : Checkout repository
168255 uses : actions/checkout@v6
169256 with :
170257 fetch-depth : 0
171258 ref : ${{ inputs.ref || github.ref }}
172259
173- - name : Resolve release tag
260+ - name : Resolve tag
174261 id : tag
175262 shell : bash
176263 run : |
@@ -182,29 +269,46 @@ jobs:
182269 tag="$(git describe --tags --abbrev=0)"
183270 fi
184271 if [ -z "$tag" ]; then
185- echo "Failed to resolve release tag." >&2
272+ echo "Failed to resolve tag." >&2
186273 exit 1
187274 fi
188275 echo "tag=$tag" >> "$GITHUB_OUTPUT"
189276
190- - name : Download built artifacts
277+ - name : Download dashboard artifact
278+ uses : actions/download-artifact@v6
279+ with :
280+ name : Dashboard-${{ steps.tag.outputs.tag }}
281+ path : release-assets
282+
283+ - name : Download desktop artifacts
191284 uses : actions/download-artifact@v6
192285 with :
193286 pattern : AstrBot-${{ steps.tag.outputs.tag }}-*
194287 path : release-assets
195288 merge-multiple : true
196289
290+ - name : Resolve release notes
291+ id : notes
292+ shell : bash
293+ run : |
294+ note_file="changelogs/${{ steps.tag.outputs.tag }}.md"
295+ if [ ! -f "$note_file" ]; then
296+ note_file="$(mktemp)"
297+ echo "Release ${{ steps.tag.outputs.tag }}" > "$note_file"
298+ fi
299+ echo "file=$note_file" >> "$GITHUB_OUTPUT"
300+
197301 - name : Ensure release exists
198302 env :
199303 GH_TOKEN : ${{ github.token }}
200304 shell : bash
201305 run : |
202306 tag="${{ steps.tag.outputs.tag }}"
203307 if ! gh release view "$tag" >/dev/null 2>&1; then
204- gh release create "$tag" --title "$tag" --notes " "
308+ gh release create "$tag" --title "$tag" --notes-file "${{ steps.notes.outputs.file }} "
205309 fi
206310
207- - name : Remove stale desktop assets from release
311+ - name : Remove stale assets from release
208312 env :
209313 GH_TOKEN : ${{ github.token }}
210314 shell : bash
@@ -225,3 +329,33 @@ jobs:
225329 run : |
226330 tag="${{ steps.tag.outputs.tag }}"
227331 gh release upload "$tag" release-assets/* --clobber
332+
333+ publish-pypi :
334+ name : Publish PyPI
335+ runs-on : ubuntu-24.04
336+ needs : publish-release
337+ steps :
338+ - name : Checkout repository
339+ uses : actions/checkout@v6
340+ with :
341+ fetch-depth : 0
342+ ref : ${{ inputs.ref || github.ref }}
343+
344+ - name : Set up Python
345+ uses : actions/setup-python@v6
346+ with :
347+ python-version : " 3.10"
348+
349+ - name : Install uv
350+ shell : bash
351+ run : python -m pip install uv
352+
353+ - name : Build package
354+ shell : bash
355+ run : uv build
356+
357+ - name : Publish to PyPI
358+ env :
359+ UV_PUBLISH_TOKEN : ${{ secrets.PYPI_TOKEN }}
360+ shell : bash
361+ run : uv publish
0 commit comments