Skip to content

Commit 1741fbd

Browse files
committed
ci: CI 워크플로 현대화 + 품질 게이트 확장
- 액션 순서 수정(pnpm/action-setup→setup-node) + cache:pnpm로 수동 store 캐시 3스텝 제거. Node 20(EOL)→24. - 빌드 1회 후 lint/typecheck/test/size가 turbo 캐시 재사용(기존 이중 빌드 해소). - 게이트 추가: lint:fast(oxlint)·lint(eslint)·knip·lint:package(publint+attw) ·size(size-limit). - e2e를 분리 잡으로 + Playwright 브라우저 캐시(미스 시에만 설치) → 매 실행 무조건 설치 제거. publish는 ci+e2e 통과 후로. - publish 스텝은 불변(발행 흐름 유지), 러너만 Node 24+cache:pnpm로 현대화.
1 parent a832a6e commit 1741fbd

1 file changed

Lines changed: 79 additions & 58 deletions

File tree

.github/workflows/ci.yml

Lines changed: 79 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ name: CI
22

33
on:
44
pull_request:
5-
branches: [ master, develop ]
5+
branches: [master, develop]
66
push:
7-
branches: [ master, develop ]
7+
branches: [master, develop]
88

99
permissions:
1010
contents: read
@@ -23,43 +23,42 @@ jobs:
2323
with:
2424
fetch-depth: 0
2525

26-
- name: Setup Node
27-
uses: actions/setup-node@v6
28-
with:
29-
node-version: 20
30-
26+
# pnpm must be set up BEFORE setup-node so `cache: pnpm` can find it
3127
- name: Setup pnpm
3228
uses: pnpm/action-setup@v6
3329

34-
- name: Get pnpm store directory
35-
shell: bash
36-
run: |
37-
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
38-
39-
- name: Setup pnpm cache
40-
uses: actions/cache@v5
30+
- name: Setup Node
31+
uses: actions/setup-node@v6
4132
with:
42-
path: ${{ env.STORE_PATH }}
43-
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
44-
restore-keys: |
45-
${{ runner.os }}-pnpm-store-
33+
node-version: 24
34+
cache: pnpm
4635

4736
- run: pnpm install --frozen-lockfile
4837

49-
- name: Lint
50-
run: |
51-
if pnpm run | grep -q "^ *lint *"; then pnpm run lint; else echo "no lint script"; fi
38+
# Build once; lint/typecheck/test/size reuse the Turbo cache (no rebuild)
39+
- name: Build
40+
run: pnpm run build
41+
42+
- name: Lint (oxlint fast pass)
43+
run: pnpm run lint:fast
44+
45+
- name: Lint (ESLint)
46+
run: pnpm run lint
5247

5348
- name: Typecheck
5449
run: pnpm run typecheck
5550

56-
- name: Install Playwright Browsers
57-
run: npx playwright install --with-deps
51+
- name: Dead code / unused deps (knip)
52+
run: pnpm run knip
53+
54+
- name: Package correctness (publint + attw)
55+
run: pnpm run lint:package
5856

5957
- name: Test
60-
run: |
61-
if pnpm run | grep -q "^ *test *"; then pnpm test -- --coverage; else echo "no test script"; fi
62-
pnpm --filter @scrolloop/react test:e2e
58+
run: pnpm test -- --coverage
59+
60+
- name: Bundle size budgets (size-limit)
61+
run: pnpm run size
6362

6463
- name: Report Coverage
6564
if: success() && github.event_name == 'pull_request'
@@ -68,52 +67,86 @@ jobs:
6867
script: |
6968
const fs = require('fs');
7069
const path = require('path');
71-
70+
7271
const packagesDir = 'packages';
7372
if (!fs.existsSync(packagesDir)) return;
74-
73+
7574
const dirs = fs.readdirSync(packagesDir);
76-
75+
7776
const validPackages = dirs.filter(dir => {
7877
const summaryPath = path.join(packagesDir, dir, 'coverage', 'coverage-summary.json');
7978
return fs.existsSync(summaryPath);
8079
});
81-
80+
8281
if (validPackages.length === 0) return;
83-
82+
8483
let message = '## 📊 Test Coverage Report (vitest) \n\n';
85-
84+
8685
message += '| Package | Statements | Branches | Functions | Lines |\n';
8786
message += '| :--- | :--- | :--- | :--- | :--- |\n';
88-
87+
8988
const metrics = ['statements', 'branches', 'functions', 'lines'];
90-
89+
9190
for (const pkg of validPackages) {
9291
const summaryPath = path.join(packagesDir, pkg, 'coverage', 'coverage-summary.json');
9392
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8'));
9493
const total = summary.total;
95-
94+
9695
message += `| **@scrolloop/${pkg}** |`;
97-
96+
9897
for (const metric of metrics) {
9998
const data = total[metric];
10099
message += ` ${data.covered}/${data.total} (${data.pct}%) |`;
101100
}
102101
message += '\n';
103102
}
104-
103+
105104
await github.rest.issues.createComment({
106105
issue_number: context.issue.number,
107106
owner: context.repo.owner,
108107
repo: context.repo.repo,
109108
body: message
110109
});
111110
112-
- name: Build
113-
run: pnpm run build
111+
e2e:
112+
runs-on: ubuntu-latest
113+
steps:
114+
- uses: actions/checkout@v5
115+
with:
116+
fetch-depth: 0
117+
118+
- name: Setup pnpm
119+
uses: pnpm/action-setup@v6
120+
121+
- name: Setup Node
122+
uses: actions/setup-node@v6
123+
with:
124+
node-version: 24
125+
cache: pnpm
126+
127+
- run: pnpm install --frozen-lockfile
128+
- run: pnpm run build
129+
130+
- name: Cache Playwright browsers
131+
id: pw-cache
132+
uses: actions/cache@v4
133+
with:
134+
path: ~/.cache/ms-playwright
135+
key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }}
136+
137+
- name: Install Playwright (browsers + system deps)
138+
if: steps.pw-cache.outputs.cache-hit != 'true'
139+
run: pnpm --filter @scrolloop/react exec playwright install --with-deps
140+
141+
- name: Install Playwright system deps (cached browsers)
142+
if: steps.pw-cache.outputs.cache-hit == 'true'
143+
run: pnpm --filter @scrolloop/react exec playwright install-deps
144+
145+
- name: E2E
146+
run: pnpm --filter @scrolloop/react test:e2e
114147

115148
publish:
116-
needs: ci
149+
needs: [ci, e2e]
117150
if: github.event_name == 'push' && startsWith(github.ref, 'refs/heads/master')
118151
runs-on: ubuntu-latest
119152
permissions:
@@ -124,27 +157,15 @@ jobs:
124157
with:
125158
fetch-depth: 0
126159

127-
- name: Setup Node (npm registry)
128-
uses: actions/setup-node@v6
129-
with:
130-
node-version: 20
131-
registry-url: https://registry.npmjs.org/
132-
133160
- name: Setup pnpm
134161
uses: pnpm/action-setup@v6
135162

136-
- name: Get pnpm store directory
137-
shell: bash
138-
run: |
139-
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
140-
141-
- name: Setup pnpm cache
142-
uses: actions/cache@v5
163+
- name: Setup Node (npm registry)
164+
uses: actions/setup-node@v6
143165
with:
144-
path: ${{ env.STORE_PATH }}
145-
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
146-
restore-keys: |
147-
${{ runner.os }}-pnpm-store-
166+
node-version: 24
167+
cache: pnpm
168+
registry-url: https://registry.npmjs.org/
148169

149170
- run: pnpm install --frozen-lockfile
150171
- run: pnpm run build
@@ -177,4 +198,4 @@ jobs:
177198
env:
178199
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
179200
run: |
180-
pnpm publish --access public --no-git-checks
201+
pnpm publish --access public --no-git-checks

0 commit comments

Comments
 (0)