Skip to content

Commit a6251f8

Browse files
ci: parallelize E2E tests with sharding and separate jobs
- Split CI into separate jobs: build, test-unit, test-e2e, coverage - E2E tests now run in 3 parallel shards - Build artifacts cached and reused across jobs - Reduces total CI time by running tests in parallel Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6ef31e3 commit a6251f8

1 file changed

Lines changed: 102 additions & 40 deletions

File tree

.github/workflows/ci.yml

Lines changed: 102 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,76 +22,138 @@ on:
2222
- 'docs/**'
2323

2424
jobs:
25-
build-test:
26-
runs-on: ${{ matrix.os }}
27-
28-
permissions:
29-
# Required to checkout the code and push coverage badge updates
30-
contents: write
31-
# Required to put a comment into the pull-request
32-
pull-requests: write
33-
34-
strategy:
35-
matrix:
36-
os: [ubuntu-latest]
37-
25+
build:
26+
runs-on: ubuntu-latest
3827
steps:
3928
- uses: actions/checkout@v5
40-
4129
- run: corepack enable
4230
- uses: actions/setup-node@v6
4331
with:
4432
node-version: lts/*
4533
cache: pnpm
46-
4734
- name: 📦 Install dependencies
4835
run: pnpm install --frozen-lockfile
49-
5036
- name: 👀 Lint
5137
run: pnpm lint
52-
5338
- name: 🚀 Build
5439
run: pnpm build
55-
40+
- name: 📦 Cache build
41+
uses: actions/cache/save@v4
42+
with:
43+
path: |
44+
dist
45+
node_modules
46+
key: build-${{ github.sha }}
47+
48+
test-unit:
49+
needs: build
50+
runs-on: ubuntu-latest
51+
permissions:
52+
contents: write
53+
pull-requests: write
54+
steps:
55+
- uses: actions/checkout@v5
56+
- run: corepack enable
57+
- uses: actions/setup-node@v6
58+
with:
59+
node-version: lts/*
60+
cache: pnpm
61+
- name: 📦 Restore build
62+
uses: actions/cache/restore@v4
63+
with:
64+
path: |
65+
dist
66+
node_modules
67+
key: build-${{ github.sha }}
5668
- name: 🧪 Test (Unit + Integration)
5769
run: pnpm test:unit --coverage
5870

59-
- name: 🧪 Test (E2E)
60-
run: pnpm test:e2e
61-
71+
test-e2e:
72+
needs: build
73+
runs-on: ubuntu-latest
74+
strategy:
75+
fail-fast: false
76+
matrix:
77+
shard: [1, 2, 3]
78+
steps:
79+
- uses: actions/checkout@v5
80+
- run: corepack enable
81+
- uses: actions/setup-node@v6
82+
with:
83+
node-version: lts/*
84+
cache: pnpm
85+
- name: 📦 Restore build
86+
uses: actions/cache/restore@v4
87+
with:
88+
path: |
89+
dist
90+
node_modules
91+
key: build-${{ github.sha }}
92+
- name: 🧪 Test (E2E) - Shard ${{ matrix.shard }}/3
93+
run: pnpm test:e2e --shard=${{ matrix.shard }}/3
94+
95+
coverage-report:
96+
needs: test-unit
97+
runs-on: ubuntu-latest
98+
if: github.event_name == 'pull_request'
99+
permissions:
100+
pull-requests: write
101+
steps:
102+
- uses: actions/checkout@v5
103+
- run: corepack enable
104+
- uses: actions/setup-node@v6
105+
with:
106+
node-version: lts/*
107+
cache: pnpm
108+
- name: 📦 Restore build
109+
uses: actions/cache/restore@v4
110+
with:
111+
path: |
112+
dist
113+
node_modules
114+
key: build-${{ github.sha }}
115+
- name: 🧪 Generate coverage
116+
run: pnpm test:unit --coverage
62117
- name: 📊 Vitest Coverage Report
63118
uses: davelosert/vitest-coverage-report-action@v2
64-
if: github.event_name == 'pull_request'
65119
with:
66120
json-summary-path: ./coverage/coverage-summary.json
67121
json-final-path: ./coverage/coverage-final.json
68122

123+
coverage-badge:
124+
needs: test-unit
125+
runs-on: ubuntu-latest
126+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
127+
permissions:
128+
contents: write
129+
steps:
130+
- uses: actions/checkout@v5
131+
- run: corepack enable
132+
- uses: actions/setup-node@v6
133+
with:
134+
node-version: lts/*
135+
cache: pnpm
136+
- name: 📦 Restore build
137+
uses: actions/cache/restore@v4
138+
with:
139+
path: |
140+
dist
141+
node_modules
142+
key: build-${{ github.sha }}
143+
- name: 🧪 Generate coverage
144+
run: pnpm test:unit --coverage
69145
- name: 📊 Update coverage badge
70-
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
71146
run: |
72-
# Extract coverage percentage
73147
COVERAGE=$(node -e "
74148
const data = require('./coverage/coverage-summary.json');
75149
console.log(Math.round(data.total.lines.pct));
76150
")
77-
78-
# Determine badge color
79-
if [ "$COVERAGE" -ge 80 ]; then
80-
COLOR="brightgreen"
81-
elif [ "$COVERAGE" -ge 60 ]; then
82-
COLOR="green"
83-
elif [ "$COVERAGE" -ge 40 ]; then
84-
COLOR="yellow"
85-
else
86-
COLOR="red"
87-
fi
88-
151+
if [ "$COVERAGE" -ge 80 ]; then COLOR="brightgreen"
152+
elif [ "$COVERAGE" -ge 60 ]; then COLOR="green"
153+
elif [ "$COVERAGE" -ge 40 ]; then COLOR="yellow"
154+
else COLOR="red"; fi
89155
echo "Coverage: $COVERAGE%, Color: $COLOR"
90-
91-
# Update README
92156
sed -i "s|coverage-[0-9]*%25-[a-z]*|coverage-${COVERAGE}%25-${COLOR}|g" README.md
93-
94-
# Check if changed
95157
if git diff --quiet README.md; then
96158
echo "No coverage change"
97159
else

0 commit comments

Comments
 (0)