1- name : Release Desktop
1+ name : Release
22
33on :
44 push :
55 tags :
66 - " v*.*.*"
7+ schedule :
8+ - cron : " 0 9 * * *"
79 workflow_dispatch :
810 inputs :
11+ channel :
12+ description : " Release channel"
13+ required : false
14+ default : stable
15+ type : choice
16+ options :
17+ - stable
18+ - nightly
919 version :
1020 description : " Release version (for example 1.2.3 or v1.2.3)"
11- required : true
21+ required : false
1222 type : string
1323
1424permissions :
@@ -21,40 +31,21 @@ jobs:
2131 runs-on : ubuntu-24.04
2232 timeout-minutes : 10
2333 outputs :
34+ release_channel : ${{ steps.release_meta.outputs.release_channel }}
2435 version : ${{ steps.release_meta.outputs.version }}
2536 tag : ${{ steps.release_meta.outputs.tag }}
37+ release_name : ${{ steps.release_meta.outputs.name }}
38+ short_sha : ${{ steps.release_meta.outputs.short_sha }}
39+ previous_tag : ${{ steps.previous_tag.outputs.previous_tag }}
40+ cli_dist_tag : ${{ steps.release_meta.outputs.cli_dist_tag }}
2641 is_prerelease : ${{ steps.release_meta.outputs.is_prerelease }}
2742 make_latest : ${{ steps.release_meta.outputs.make_latest }}
2843 ref : ${{ github.sha }}
2944 steps :
3045 - name : Checkout
3146 uses : actions/checkout@v6
32-
33- - id : release_meta
34- name : Resolve release version
35- shell : bash
36- run : |
37- if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
38- raw="${{ github.event.inputs.version }}"
39- else
40- raw="${GITHUB_REF_NAME}"
41- fi
42-
43- version="${raw#v}"
44- if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
45- echo "Invalid release version: $raw" >&2
46- exit 1
47- fi
48-
49- echo "version=$version" >> "$GITHUB_OUTPUT"
50- echo "tag=v$version" >> "$GITHUB_OUTPUT"
51- if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
52- echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
53- echo "make_latest=true" >> "$GITHUB_OUTPUT"
54- else
55- echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
56- echo "make_latest=false" >> "$GITHUB_OUTPUT"
57- fi
47+ with :
48+ fetch-depth : 0
5849
5950 - name : Setup Bun
6051 uses : oven-sh/setup-bun@v2
6960 - name : Install dependencies
7061 run : bun install --frozen-lockfile
7162
63+ - id : release_meta
64+ name : Resolve release version
65+ shell : bash
66+ env :
67+ DISPATCH_CHANNEL : ${{ github.event.inputs.channel }}
68+ DISPATCH_VERSION : ${{ github.event.inputs.version }}
69+ NIGHTLY_DATE : ${{ github.run_started_at }}
70+ NIGHTLY_SHA : ${{ github.sha }}
71+ NIGHTLY_RUN_NUMBER : ${{ github.run_number }}
72+ run : |
73+ if [[ "${GITHUB_EVENT_NAME}" == "schedule" || ( "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && "${DISPATCH_CHANNEL:-stable}" == "nightly" ) ]]; then
74+ nightly_date="$(date -u -d "$NIGHTLY_DATE" +%Y%m%d)"
75+
76+ node scripts/resolve-nightly-release.ts \
77+ --date "$nightly_date" \
78+ --run-number "$NIGHTLY_RUN_NUMBER" \
79+ --sha "$NIGHTLY_SHA" \
80+ --github-output
81+
82+ echo "release_channel=nightly" >> "$GITHUB_OUTPUT"
83+ echo "cli_dist_tag=nightly" >> "$GITHUB_OUTPUT"
84+ echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
85+ echo "make_latest=false" >> "$GITHUB_OUTPUT"
86+ else
87+ if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
88+ raw="${DISPATCH_VERSION}"
89+ if [[ -z "$raw" ]]; then
90+ echo "workflow_dispatch stable releases require the version input." >&2
91+ exit 1
92+ fi
93+ else
94+ raw="${GITHUB_REF_NAME}"
95+ fi
96+
97+ version="${raw#v}"
98+ if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
99+ echo "Invalid release version: $raw" >&2
100+ exit 1
101+ fi
102+
103+ echo "release_channel=stable" >> "$GITHUB_OUTPUT"
104+ echo "version=$version" >> "$GITHUB_OUTPUT"
105+ echo "tag=v$version" >> "$GITHUB_OUTPUT"
106+ echo "name=T3 Code v$version" >> "$GITHUB_OUTPUT"
107+ echo "cli_dist_tag=latest" >> "$GITHUB_OUTPUT"
108+ if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
109+ echo "is_prerelease=false" >> "$GITHUB_OUTPUT"
110+ echo "make_latest=true" >> "$GITHUB_OUTPUT"
111+ else
112+ echo "is_prerelease=true" >> "$GITHUB_OUTPUT"
113+ echo "make_latest=false" >> "$GITHUB_OUTPUT"
114+ fi
115+ fi
116+
72117 - name : Lint
73118 run : bun run lint
74119
@@ -78,6 +123,14 @@ jobs:
78123 - name : Test
79124 run : bun run test
80125
126+ - id : previous_tag
127+ name : Resolve previous release tag
128+ run : |
129+ node scripts/resolve-previous-release-tag.ts \
130+ --channel "${{ steps.release_meta.outputs.release_channel }}" \
131+ --current-tag "${{ steps.release_meta.outputs.tag }}" \
132+ --github-output
133+
81134 build :
82135 name : Build ${{ matrix.label }}
83136 needs : preflight
@@ -206,16 +259,17 @@ jobs:
206259 "release/*.AppImage" \
207260 "release/*.exe" \
208261 "release/*.blockmap" \
209- "release/latest *.yml"; do
262+ "release/*.yml"; do
210263 for file in $pattern; do
211264 cp "$file" release-publish/
212265 done
213266 done
214267
215268 if [[ "${{ matrix.platform }}" == "mac" && "${{ matrix.arch }}" != "arm64" ]]; then
216- if [[ -f release-publish/latest-mac.yml ]]; then
217- mv release-publish/latest-mac.yml "release-publish/latest-mac-${{ matrix.arch }}.yml"
218- fi
269+ shopt -s nullglob
270+ for manifest in release-publish/*-mac.yml; do
271+ mv "$manifest" "${manifest%.yml}-${{ matrix.arch }}.yml"
272+ done
219273 fi
220274
221275 - name : Upload build artifacts
@@ -257,7 +311,7 @@ jobs:
257311 run : bun run build --filter=@t3tools/web --filter=t3
258312
259313 - name : Publish CLI package
260- run : node apps/server/scripts/cli.ts publish --tag latest --app-version "${{ needs.preflight.outputs.version }}" --verbose
314+ run : node apps/server/scripts/cli.ts publish --tag "${{ needs.preflight.outputs.cli_dist_tag }}" --app-version "${{ needs.preflight.outputs.version }}" --verbose
261315
262316 release :
263317 name : Publish GitHub Release
@@ -284,17 +338,42 @@ jobs:
284338
285339 - name : Merge macOS updater manifests
286340 run : |
287- node scripts/merge-mac-update-manifests.ts \
288- release-assets/latest-mac.yml \
289- release-assets/latest-mac-x64.yml
290- rm -f release-assets/latest-mac-x64.yml
341+ shopt -s nullglob
342+ for x64_manifest in release-assets/*-mac-x64.yml; do
343+ arm64_manifest="${x64_manifest%-x64.yml}.yml"
344+ if [[ -f "$arm64_manifest" ]]; then
345+ node scripts/merge-mac-update-manifests.ts "$arm64_manifest" "$x64_manifest"
346+ rm -f "$x64_manifest"
347+ fi
348+ done
291349
292350 - name : Publish release
351+ if : needs.preflight.outputs.previous_tag != ''
352+ uses : softprops/action-gh-release@v2
353+ with :
354+ tag_name : ${{ needs.preflight.outputs.tag }}
355+ target_commitish : ${{ needs.preflight.outputs.ref }}
356+ name : ${{ needs.preflight.outputs.release_name }}
357+ generate_release_notes : true
358+ previous_tag : ${{ needs.preflight.outputs.previous_tag }}
359+ prerelease : ${{ needs.preflight.outputs.is_prerelease }}
360+ make_latest : ${{ needs.preflight.outputs.make_latest }}
361+ files : |
362+ release-assets/*.dmg
363+ release-assets/*.zip
364+ release-assets/*.AppImage
365+ release-assets/*.exe
366+ release-assets/*.blockmap
367+ release-assets/*.yml
368+ fail_on_unmatched_files : true
369+
370+ - name : Publish first release
371+ if : needs.preflight.outputs.previous_tag == ''
293372 uses : softprops/action-gh-release@v2
294373 with :
295374 tag_name : ${{ needs.preflight.outputs.tag }}
296375 target_commitish : ${{ needs.preflight.outputs.ref }}
297- name : T3 Code v ${{ needs.preflight.outputs.version }}
376+ name : ${{ needs.preflight.outputs.release_name }}
298377 generate_release_notes : true
299378 prerelease : ${{ needs.preflight.outputs.is_prerelease }}
300379 make_latest : ${{ needs.preflight.outputs.make_latest }}
@@ -304,11 +383,12 @@ jobs:
304383 release-assets/*.AppImage
305384 release-assets/*.exe
306385 release-assets/*.blockmap
307- release-assets/latest *.yml
386+ release-assets/*.yml
308387 fail_on_unmatched_files : true
309388
310389 finalize :
311390 name : Finalize release
391+ if : needs.preflight.outputs.release_channel == 'stable'
312392 needs : [preflight, release]
313393 runs-on : ubuntu-24.04
314394 timeout-minutes : 10
0 commit comments