| ... | ... | @@ -4,6 +4,12 @@ on: |
| 4 | 4 | push: |
| 5 | 5 | tags: |
| 6 | 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 |
| 7 | 13 | |
| 8 | 14 | permissions: |
| 9 | 15 | contents: write |
| ... | ... | @@ -14,10 +20,33 @@ jobs: |
| 14 | 20 | name: Preflight |
| 15 | 21 | runs-on: ubuntu-24.04 |
| 16 | 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 | 26 | steps: |
| 19 | 27 | - name: Checkout |
| 20 | 28 | 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" |
| 21 | 50 | |
| 22 | 51 | - name: Setup Bun |
| 23 | 52 | uses: oven-sh/setup-bun@v2 |
| ... | ... | @@ -29,6 +58,65 @@ jobs: |
| 29 | 58 | with: |
| 30 | 59 | node-version-file: package.json |
| 31 | 60 | |
| 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 | 120 | - name: Install dependencies |
| 33 | 121 | run: bun install --frozen-lockfile |
| 34 | 122 | |
| ... | ... | @@ -41,10 +129,6 @@ jobs: |
| 41 | 129 | - name: Test |
| 42 | 130 | run: bun run test |
| 43 | 131 | |
| 44 | | - id: version |
| 45 | | name: Resolve release version |
| 46 | | run: echo "value=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" |
| 47 | | |
| 48 | 132 | build: |
| 49 | 133 | name: Build ${{ matrix.label }} |
| 50 | 134 | needs: preflight |
| ... | ... | @@ -76,6 +160,9 @@ jobs: |
| 76 | 160 | steps: |
| 77 | 161 | - name: Checkout |
| 78 | 162 | uses: actions/checkout@v4 |
| 163 | with: |
| 164 | ref: ${{ needs.preflight.outputs.ref }} |
| 165 | fetch-depth: 0 |
| 79 | 166 | |
| 80 | 167 | - name: Setup Bun |
| 81 | 168 | uses: oven-sh/setup-bun@v2 |
| ... | ... | @@ -215,7 +302,7 @@ jobs: |
| 215 | 302 | - name: Publish release |
| 216 | 303 | uses: softprops/action-gh-release@v2 |
| 217 | 304 | with: |
| 218 | | tag_name: ${{ github.ref_name }} |
| 305 | tag_name: ${{ needs.preflight.outputs.tag }} |
| 219 | 306 | name: T3 Code v${{ needs.preflight.outputs.version }} |
| 220 | 307 | generate_release_notes: true |
| 221 | 308 | files: release-assets/* |