Skip to content

Commit eac201f

Browse files
ci: add server workflow, enforce Flutter tests, add protocol contract CI (#3)
* ci(server): add GitHub Actions workflow for pnpm typecheck, test, and audit Implements the CI requirements documented in server/SECURITY.md: frozen lockfile install, typecheck, build, blocking tests, and prod audit. Co-authored-by: Milan Le <leduckhc@users.noreply.github.com> * ci: enforce Flutter tests and add cross-stack protocol contract workflow - Make flutter test blocking; keep Codecov upload advisory - Use flutter analyze --fatal-infos to match local audit.sh - Add protocol-contract-ci.yml: fixture sync check + both contract tests Co-authored-by: Milan Le <leduckhc@users.noreply.github.com> * fix(ci): use Node 22 for pnpm 11.8.0 compatibility pnpm 11.8.0 requires Node.js >=22.13 (node:sqlite). CI was on Node 20, causing all server jobs to fail at install. Align engines field with reality. Co-authored-by: Milan Le <leduckhc@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Milan Le <leduckhc@users.noreply.github.com>
1 parent a77a765 commit eac201f

4 files changed

Lines changed: 220 additions & 4 deletions

File tree

.github/workflows/flutter-ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
- name: Run analysis (strict linting)
4646
run: |
4747
cd app
48-
flutter analyze --no-pub
48+
flutter analyze --no-pub --fatal-infos
4949
5050
- name: Check code formatting
5151
run: |
@@ -91,14 +91,13 @@ jobs:
9191
run: |
9292
cd app
9393
flutter test --coverage
94-
continue-on-error: true # Tests are informational; CI passes even if they fail
9594
9695
- name: Upload coverage to Codecov
9796
uses: codecov/codecov-action@v3
9897
with:
9998
files: ./app/coverage/lcov.info
10099
flags: flutter
101-
continue-on-error: true
100+
continue-on-error: true # Coverage upload is advisory; test failures block above
102101

103102
security-audit:
104103
runs-on: ubuntu-latest
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
name: Protocol Contract CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'app/test/fixtures/**'
8+
- 'server/test/fixtures/**'
9+
- 'app/test/codec_contract_test.dart'
10+
- 'server/test/protocol/contract.test.ts'
11+
- 'app/lib/transport/**'
12+
- 'server/src/protocol/**'
13+
- '.github/workflows/protocol-contract-ci.yml'
14+
pull_request:
15+
branches: [ main ]
16+
paths:
17+
- 'app/test/fixtures/**'
18+
- 'server/test/fixtures/**'
19+
- 'app/test/codec_contract_test.dart'
20+
- 'server/test/protocol/contract.test.ts'
21+
- 'app/lib/transport/**'
22+
- 'server/src/protocol/**'
23+
- '.github/workflows/protocol-contract-ci.yml'
24+
25+
jobs:
26+
fixture-sync:
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 5
29+
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@v4
33+
34+
- name: Verify shared fixtures are byte-identical
35+
run: |
36+
diff -rq app/test/fixtures server/test/fixtures
37+
echo "Shared fixtures are byte-identical between app and server."
38+
39+
server-contract:
40+
runs-on: ubuntu-latest
41+
timeout-minutes: 10
42+
needs: fixture-sync
43+
defaults:
44+
run:
45+
working-directory: server
46+
47+
steps:
48+
- name: Checkout code
49+
uses: actions/checkout@v4
50+
51+
- name: Setup Node.js
52+
uses: actions/setup-node@v4
53+
with:
54+
node-version: '22'
55+
56+
- name: Enable Corepack
57+
run: corepack enable
58+
59+
- name: Prepare pnpm
60+
run: corepack prepare pnpm@11.8.0 --activate
61+
62+
- name: Install dependencies
63+
run: pnpm secure:install
64+
65+
- name: Run server protocol contract tests
66+
run: node --import tsx --test test/protocol/contract.test.ts
67+
68+
flutter-contract:
69+
runs-on: ubuntu-latest
70+
timeout-minutes: 10
71+
needs: fixture-sync
72+
73+
steps:
74+
- name: Checkout code
75+
uses: actions/checkout@v4
76+
77+
- name: Setup Flutter
78+
uses: subosito/flutter-action@v2
79+
with:
80+
flutter-version: '3.44.4'
81+
channel: 'stable'
82+
83+
- name: Install Flutter dependencies
84+
run: |
85+
cd app
86+
flutter pub get --enforce-lockfile
87+
88+
- name: Run Flutter protocol contract tests
89+
run: |
90+
cd app
91+
flutter test test/codec_contract_test.dart

.github/workflows/server-ci.yml

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
name: Server Security + Lint CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- 'server/**'
8+
- '.github/workflows/server-ci.yml'
9+
pull_request:
10+
branches: [ main ]
11+
paths:
12+
- 'server/**'
13+
- '.github/workflows/server-ci.yml'
14+
15+
jobs:
16+
lint-and-typecheck:
17+
runs-on: ubuntu-latest
18+
timeout-minutes: 15
19+
defaults:
20+
run:
21+
working-directory: server
22+
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Setup Node.js
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: '22'
31+
32+
- name: Enable Corepack
33+
run: corepack enable
34+
35+
- name: Prepare pnpm
36+
run: corepack prepare pnpm@11.8.0 --activate
37+
38+
- name: Cache pnpm store
39+
uses: actions/cache@v4
40+
with:
41+
path: ~/.local/share/pnpm/store
42+
key: ${{ runner.os }}-pnpm-${{ hashFiles('server/pnpm-lock.yaml') }}
43+
restore-keys: |
44+
${{ runner.os }}-pnpm-
45+
46+
- name: Install dependencies (lockfile-locked)
47+
run: pnpm secure:install
48+
49+
- name: Run typecheck
50+
run: pnpm typecheck
51+
52+
- name: Build
53+
run: pnpm build
54+
55+
- name: Verify pnpm-lock.yaml integrity
56+
run: |
57+
if ! git diff --exit-code pnpm-lock.yaml > /dev/null; then
58+
echo "ERROR: pnpm-lock.yaml would be modified by pnpm install"
59+
echo "This indicates a lockfile inconsistency or manual edit."
60+
echo "Run: pnpm install && git add pnpm-lock.yaml"
61+
exit 1
62+
fi
63+
64+
test:
65+
runs-on: ubuntu-latest
66+
timeout-minutes: 15
67+
defaults:
68+
run:
69+
working-directory: server
70+
71+
steps:
72+
- name: Checkout code
73+
uses: actions/checkout@v4
74+
75+
- name: Setup Node.js
76+
uses: actions/setup-node@v4
77+
with:
78+
node-version: '22'
79+
80+
- name: Enable Corepack
81+
run: corepack enable
82+
83+
- name: Prepare pnpm
84+
run: corepack prepare pnpm@11.8.0 --activate
85+
86+
- name: Cache pnpm store
87+
uses: actions/cache@v4
88+
with:
89+
path: ~/.local/share/pnpm/store
90+
key: ${{ runner.os }}-pnpm-${{ hashFiles('server/pnpm-lock.yaml') }}
91+
restore-keys: |
92+
${{ runner.os }}-pnpm-
93+
94+
- name: Install dependencies
95+
run: pnpm secure:install
96+
97+
- name: Run tests
98+
run: pnpm test
99+
100+
security-audit:
101+
runs-on: ubuntu-latest
102+
timeout-minutes: 10
103+
defaults:
104+
run:
105+
working-directory: server
106+
107+
steps:
108+
- name: Checkout code
109+
uses: actions/checkout@v4
110+
111+
- name: Setup Node.js
112+
uses: actions/setup-node@v4
113+
with:
114+
node-version: '22'
115+
116+
- name: Enable Corepack
117+
run: corepack enable
118+
119+
- name: Prepare pnpm
120+
run: corepack prepare pnpm@11.8.0 --activate
121+
122+
- name: Install dependencies
123+
run: pnpm secure:install
124+
125+
- name: Audit production dependencies
126+
run: pnpm secure:audit

server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"pino": "./dist/index.js"
99
},
1010
"engines": {
11-
"node": ">=20.0.0",
11+
"node": ">=22.13.0",
1212
"pnpm": ">=11.0.0"
1313
},
1414
"scripts": {

0 commit comments

Comments
 (0)