From ad54e179b6a3921fd26ad3ac585f5ef965b01c1b Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Sun, 19 Apr 2026 15:40:21 -0400 Subject: [PATCH] ci: add concurrency group and split build/test with artifact sharing - Add concurrency group keyed on github.ref with cancel-in-progress to stop superseded runs on rapid pushes - Split validate matrix into: validate (typecheck/lint/format), build, test - Build uploads dist/ artifact; test downloads instead of rebuilding (removes inline build:all duplication) - Net: faster feedback, less runner time, DRY build step --- .github/workflows/ci.yml | 97 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 065a26de..5b45e544 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,9 +6,13 @@ on: # Design notes: # - Matrix parallelism cuts wall time from ~3-4min to ~60-90s (cache warm). -# - Each matrix leg restores the same cache; `Ensure deps` fills gaps on cache miss. +# - Concurrency group cancels superseded runs on the same ref (saves runner time on rapid pushes). +# - Build leg produces dist/ artifact; test leg downloads it instead of rebuilding (DRY). # - fail-fast: false so every failure is visible in one run (no re-pushing to see the next failure). -# - Test leg runs build:all inline because it needs dist/ artifacts; still parallel with other legs. + +concurrency: + group: ci-${{ github.ref }} + cancel-in-progress: true jobs: validate: @@ -20,8 +24,6 @@ jobs: - { name: typecheck, cmd: 'bun run typecheck' } - { name: lint, cmd: 'bun run lint' } - { name: format, cmd: 'bun run format:check' } - - { name: build, cmd: 'bun run build:all' } - - { name: test, cmd: 'bun run build:all && bun run test:all' } name: ${{ matrix.check.name }} steps: @@ -56,3 +58,90 @@ jobs: - name: Run ${{ matrix.check.name }} run: ${{ matrix.check.cmd }} + + build: + runs-on: [self-hosted, linux, x64] + name: build + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: '1.3.9' + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Restore bun + node_modules cache + uses: actions/cache@v4 + with: + path: | + ~/.bun/install/cache + node_modules + ui/node_modules + key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock', 'ui/bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun- + + - name: Ensure dependencies + run: | + [ -d node_modules ] || bun install --frozen-lockfile + [ -d ui/node_modules ] || (cd ui && bun install --frozen-lockfile) + + - name: Build + run: bun run build:all + + - name: Upload dist artifact + uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + retention-days: 1 + if-no-files-found: error + + test: + runs-on: [self-hosted, linux, x64] + name: test + needs: [build] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: '1.3.9' + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Restore bun + node_modules cache + uses: actions/cache@v4 + with: + path: | + ~/.bun/install/cache + node_modules + ui/node_modules + key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock', 'ui/bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun- + + - name: Ensure dependencies + run: | + [ -d node_modules ] || bun install --frozen-lockfile + [ -d ui/node_modules ] || (cd ui && bun install --frozen-lockfile) + + - name: Download dist artifact + uses: actions/download-artifact@v4 + with: + name: dist + path: dist/ + + - name: Test + run: bun run test:all