| ... | @@ -6,7 +6,8 @@ on: | ... | @@ -6,7 +6,8 @@ on: |
| 6 | - "v*.*.*" | 6 | - "v*.*.*" |
| 7 | - "!v*-nightly.*" | 7 | - "!v*-nightly.*" |
| 8 | schedule: | 8 | schedule: |
| 9 | - cron: "0 */3 * * *" | 9 | # Off minute zero: GitHub delays scheduled runs most at the top of the hour. |
| | 10 | - cron: "7 */3 * * *" |
| 10 | workflow_dispatch: | 11 | workflow_dispatch: |
| 11 | inputs: | 12 | inputs: |
| 12 | channel: | 13 | channel: |
| ... | @@ -22,6 +23,17 @@ on: | ... | @@ -22,6 +23,17 @@ on: |
| 22 | required: false | 23 | required: false |
| 23 | type: string | 24 | type: string |
| 24 | | 25 | |
| | 26 | # Serialize nightlies (scheduled and manual) so overlapping runs cannot build |
| | 27 | # the same commit twice or publish out of order. Stable tag releases get their |
| | 28 | # own group so a nightly never blocks them. Running publishers are never |
| | 29 | # canceled, and queue: max keeps every pending run instead of the default |
| | 30 | # newest-wins single slot, so a queued stable tag can never be silently |
| | 31 | # dropped. Queued nightlies with no new commits skip via check_changes. |
| | 32 | concurrency: |
| | 33 | group: release-${{ (github.event_name == 'schedule' || inputs.channel == 'nightly') && 'nightly' || 'stable' }} |
| | 34 | cancel-in-progress: false |
| | 35 | queue: max |
| | 36 | |
| 25 | permissions: | 37 | permissions: |
| 26 | contents: read | 38 | contents: read |
| 27 | id-token: none | 39 | id-token: none |
| ... | @@ -199,8 +211,14 @@ jobs: | ... | @@ -199,8 +211,14 @@ jobs: |
| 199 | | 211 | |
| 200 | relay_public_config: | 212 | relay_public_config: |
| 201 | name: Resolve T3 Connect public config | 213 | name: Resolve T3 Connect public config |
| 202 | needs: preflight | 214 | # Consumes only the commit SHA, not preflight's resolved version, so it runs |
| 203 | if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }} | 215 | # alongside preflight instead of after it. The condition mirrors preflight's: |
| | 216 | # check_changes is skipped on non-schedule events (skipped is neither failure |
| | 217 | # nor success, so success() would be wrong here). |
| | 218 | needs: [check_changes] |
| | 219 | if: | |
| | 220 | !failure() && !cancelled() && |
| | 221 | (github.event_name != 'schedule' || needs.check_changes.outputs.has_changes == 'true') |
| 204 | runs-on: blacksmith-8vcpu-ubuntu-2404 | 222 | runs-on: blacksmith-8vcpu-ubuntu-2404 |
| 205 | timeout-minutes: 5 | 223 | timeout-minutes: 5 |
| 206 | environment: | 224 | environment: |
| ... | @@ -222,7 +240,7 @@ jobs: | ... | @@ -222,7 +240,7 @@ jobs: |
| 222 | - name: Checkout | 240 | - name: Checkout |
| 223 | uses: actions/checkout@v6 | 241 | uses: actions/checkout@v6 |
| 224 | with: | 242 | with: |
| 225 | ref: ${{ needs.preflight.outputs.ref }} | 243 | ref: ${{ github.sha }} |
| 226 | sparse-checkout: | | 244 | sparse-checkout: | |
| 227 | /* | 245 | /* |
| 228 | !/.repos/ | 246 | !/.repos/ |
| ... | @@ -295,15 +313,19 @@ jobs: | ... | @@ -295,15 +313,19 @@ jobs: |
| 295 | # machine. node-pty is N-API, so one binary works across all WSL Node versions. | 313 | # machine. node-pty is N-API, so one binary works across all WSL Node versions. |
| 296 | build_wsl_node_pty: | 314 | build_wsl_node_pty: |
| 297 | name: Build WSL node-pty (linux-x64) | 315 | name: Build WSL node-pty (linux-x64) |
| 298 | needs: [preflight] | 316 | # Same gating as relay_public_config: only the commit SHA is needed, so this |
| 299 | if: ${{ !failure() && !cancelled() && needs.preflight.result == 'success' }} | 317 | # runs alongside preflight. See the condition comment there. |
| | 318 | needs: [check_changes] |
| | 319 | if: | |
| | 320 | !failure() && !cancelled() && |
| | 321 | (github.event_name != 'schedule' || needs.check_changes.outputs.has_changes == 'true') |
| 300 | runs-on: blacksmith-8vcpu-ubuntu-2404 | 322 | runs-on: blacksmith-8vcpu-ubuntu-2404 |
| 301 | timeout-minutes: 15 | 323 | timeout-minutes: 15 |
| 302 | steps: | 324 | steps: |
| 303 | - name: Checkout | 325 | - name: Checkout |
| 304 | uses: actions/checkout@v6 | 326 | uses: actions/checkout@v6 |
| 305 | with: | 327 | with: |
| 306 | ref: ${{ needs.preflight.outputs.ref }} | 328 | ref: ${{ github.sha }} |
| 307 | sparse-checkout: | | 329 | sparse-checkout: | |
| 308 | /* | 330 | /* |
| 309 | !/.repos/ | 331 | !/.repos/ |
| ... | @@ -758,9 +780,8 @@ jobs: | ... | @@ -758,9 +780,8 @@ jobs: |
| 758 | - name: Align package versions to release version | 780 | - name: Align package versions to release version |
| 759 | run: node scripts/update-release-package-versions.ts "${{ needs.preflight.outputs.version }}" | 781 | run: node scripts/update-release-package-versions.ts "${{ needs.preflight.outputs.version }}" |
| 760 | | 782 | |
| 761 | - name: Build web package | 783 | # The t3 build task depends on @t3tools/web#build, so the web client is |
| 762 | run: vp run --filter @t3tools/web build | 784 | # built (once) as part of this step. |
| 763 | | | |
| 764 | - name: Build CLI package | 785 | - name: Build CLI package |
| 765 | run: vp run --filter t3 build | 786 | run: vp run --filter t3 build |
| 766 | | 787 | |