authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-01 20:13:24-08:00
committergravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-01 20:13:24-08:00
logae235f715589216ed9747d46d0b1894482353e12
tree14d99eaf3867d268670fb31a1e81e6e17695f90a
parenta356cd0d0f4e1908d8acf22438b9ba0d8be9ed81

feat(ci): add release workflow_dispatch version tagging

Co-authored-by: codex <codex@users.noreply.github.com>

1 files changed, 93 insertions(+), 6 deletions(-)

.github/workflows/release.yml+93-6
...@@ -4,6 +4,12 @@ on:...@@ -4,6 +4,12 @@ on:
4 push:4 push:
5 tags:5 tags:
6 - "v*.*.*"6 - "v*.*.*"
7 workflow_dispatch:
8 inputs:
9 version:
10 description: "Release version (for example 1.2.3 or v1.2.3)"
11 required: true
12 type: string
713
8permissions:14permissions:
9 contents: write15 contents: write
...@@ -14,10 +20,33 @@ jobs:...@@ -14,10 +20,33 @@ jobs:
14 name: Preflight20 name: Preflight
15 runs-on: ubuntu-24.0421 runs-on: ubuntu-24.04
16 outputs:22 outputs:
17 version: ${{ steps.version.outputs.value }}23 version: ${{ steps.release_meta.outputs.version }}
24 tag: ${{ steps.release_meta.outputs.tag }}
25 ref: ${{ steps.release_ref.outputs.value }}
18 steps:26 steps:
19 - name: Checkout27 - name: Checkout
20 uses: actions/checkout@v428 uses: actions/checkout@v4
29 with:
30 fetch-depth: 0
31
32 - id: release_meta
33 name: Resolve release version
34 shell: bash
35 run: |
36 if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
37 raw="${{ github.event.inputs.version }}"
38 else
39 raw="${GITHUB_REF_NAME}"
40 fi
41
42 version="${raw#v}"
43 if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
44 echo "Invalid release version: $raw" >&2
45 exit 1
46 fi
47
48 echo "version=$version" >> "$GITHUB_OUTPUT"
49 echo "tag=v$version" >> "$GITHUB_OUTPUT"
2150
22 - name: Setup Bun51 - name: Setup Bun
23 uses: oven-sh/setup-bun@v252 uses: oven-sh/setup-bun@v2
...@@ -29,6 +58,65 @@ jobs:...@@ -29,6 +58,65 @@ jobs:
29 with:58 with:
30 node-version-file: package.json59 node-version-file: package.json
3160
61 - name: Update version strings
62 if: github.event_name == 'workflow_dispatch'
63 env:
64 RELEASE_VERSION: ${{ steps.release_meta.outputs.version }}
65 run: |
66 node --input-type=module -e '
67 import { readFileSync, writeFileSync } from "node:fs";
68
69 const files = [
70 "apps/server/package.json",
71 "apps/desktop/package.json",
72 "apps/web/package.json",
73 "packages/contracts/package.json",
74 ];
75
76 for (const file of files) {
77 const packageJson = JSON.parse(readFileSync(file, "utf8"));
78 packageJson.version = process.env.RELEASE_VERSION;
79 writeFileSync(file, `${JSON.stringify(packageJson, null, 2)}\n`);
80 }
81 '
82
83 - name: Refresh lockfile
84 if: github.event_name == 'workflow_dispatch'
85 run: bun install
86
87 - name: Commit and push release version + tag
88 if: github.event_name == 'workflow_dispatch'
89 shell: bash
90 env:
91 RELEASE_TAG: ${{ steps.release_meta.outputs.tag }}
92 run: |
93 if git ls-remote --exit-code --tags origin "$RELEASE_TAG" >/dev/null 2>&1; then
94 echo "Tag $RELEASE_TAG already exists on origin." >&2
95 exit 1
96 fi
97
98 git config user.name "github-actions[bot]"
99 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
100
101 if ! git diff --quiet -- apps/server/package.json apps/desktop/package.json apps/web/package.json packages/contracts/package.json bun.lock; then
102 git add apps/server/package.json apps/desktop/package.json apps/web/package.json packages/contracts/package.json bun.lock
103 git commit -m "chore(release): prepare $RELEASE_TAG" -m "Co-authored-by: codex <codex@users.noreply.github.com>"
104 fi
105
106 git tag "$RELEASE_TAG"
107 git push origin "HEAD:${GITHUB_REF_NAME}"
108 git push origin "refs/tags/$RELEASE_TAG"
109
110 - id: release_ref
111 name: Resolve source ref
112 shell: bash
113 run: |
114 if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
115 echo "value=refs/tags/${{ steps.release_meta.outputs.tag }}" >> "$GITHUB_OUTPUT"
116 else
117 echo "value=${GITHUB_SHA}" >> "$GITHUB_OUTPUT"
118 fi
119
32 - name: Install dependencies120 - name: Install dependencies
33 run: bun install --frozen-lockfile121 run: bun install --frozen-lockfile
34122
...@@ -41,10 +129,6 @@ jobs:...@@ -41,10 +129,6 @@ jobs:
41 - name: Test129 - name: Test
42 run: bun run test130 run: bun run test
43131
44 - id: version
45 name: Resolve release version
46 run: echo "value=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
47
48 build:132 build:
49 name: Build ${{ matrix.label }}133 name: Build ${{ matrix.label }}
50 needs: preflight134 needs: preflight
...@@ -76,6 +160,9 @@ jobs:...@@ -76,6 +160,9 @@ jobs:
76 steps:160 steps:
77 - name: Checkout161 - name: Checkout
78 uses: actions/checkout@v4162 uses: actions/checkout@v4
163 with:
164 ref: ${{ needs.preflight.outputs.ref }}
165 fetch-depth: 0
79166
80 - name: Setup Bun167 - name: Setup Bun
81 uses: oven-sh/setup-bun@v2168 uses: oven-sh/setup-bun@v2
...@@ -215,7 +302,7 @@ jobs:...@@ -215,7 +302,7 @@ jobs:
215 - name: Publish release302 - name: Publish release
216 uses: softprops/action-gh-release@v2303 uses: softprops/action-gh-release@v2
217 with:304 with:
218 tag_name: ${{ github.ref_name }}305 tag_name: ${{ needs.preflight.outputs.tag }}
219 name: T3 Code v${{ needs.preflight.outputs.version }}306 name: T3 Code v${{ needs.preflight.outputs.version }}
220 generate_release_notes: true307 generate_release_notes: true
221 files: release-assets/*308 files: release-assets/*