Repository navigation
223 lines (188 loc) · 8.9 KB
/
Copy pathci.yml
File metadata and controls
223 lines (188 loc) · 8.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
name: CI
on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]
# GIT-83: run the venue gate by hand (Actions → CI → Run workflow) before
# tagging. Publishing still happens only on a v* tag.
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- name: Install dependencies
run: npm ci --legacy-peer-deps
- name: Type check
run: npm run typecheck
- name: Build
run: npm run build
- name: Unit tests
run: npm run test:unit
- name: Smoke test (free tier)
run: npm run test:smoke:free
# GIT-89: session identity across a real MCP server restart. Runs the
# single e2e file rather than `npm run test:e2e`, because the Pro suites in
# that config gate on Docker/Supabase and hang rather than skip when
# neither is present (GIT-90). This file spawns the built server directly
# on the free tier — no Docker, no credentials — so it is safe in CI, and
# the publish job gates on this one passing.
- name: E2E — session identity survives MCP restart
run: npx vitest run --config vitest.e2e.config.ts tests/e2e/git-89-session-identity.test.ts
# GIT-120: install-hooks / uninstall-hooks keep foreign hooks. Runs the
# real CLI in a scratch repo; no server, Docker or credentials.
- name: E2E — hooks install/uninstall keep foreign hooks
run: npx vitest run --config vitest.e2e.config.ts tests/e2e/git-120-hooks-merge.test.ts
# GIT-115: a fresh install in a clean HOME — init, the SessionStart hook,
# the built server — plus the CLI/wizard suite. Both run the real CLI in
# scratch directories with a scratch HOME; no Docker or credentials.
- name: E2E — fresh install reads what init wrote; CLI and wizard
run: npx vitest run --config vitest.e2e.config.ts tests/e2e/git-115-fresh-install.test.ts tests/e2e/cli-fresh-install.test.ts
- name: Dependency audit (no unused deps)
run: npx depcheck --ignores="@types/*" --json | node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); const unused=d.dependencies||[]; if(unused.length){console.error('Unused dependencies:',unused);process.exit(1)}"
# GIT-83 / GIT-112: the hook suite on a runner WITHOUT jq (or ps). The hooks
# fall back to node and bash builtins there; on 1.10.0 that fallback left
# Stop enforcement inactive and nothing noticed, because every runner and
# dev machine the suite had run on had jq.
hooks-without-jq:
runs-on: ubuntu-latest
container: node:20-bookworm-slim
steps:
- uses: actions/checkout@v4
- name: Runner has no jq and no ps
run: |
if command -v jq >/dev/null; then echo "::error::jq is installed; this job must run without it"; exit 1; fi
if command -v ps >/dev/null; then echo "::error::ps is installed; this job must run without it"; exit 1; fi
bash --version | head -1; node --version
- name: Hook tests
run: bash hooks/tests/test-hooks.sh
# GIT-116: the same suite on stock macOS. The runner has Homebrew (and may
# have coreutils' timeout), so the suite runs with the system directories
# plus a directory holding only node — what a Mac without Homebrew has.
hooks-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Hook tests on a stock macOS PATH (no Homebrew, no timeout)
run: |
mkdir -p "$RUNNER_TEMP/nodeonly"
ln -s "$(command -v node)" "$RUNNER_TEMP/nodeonly/node"
STOCK="/usr/bin:/bin:/usr/sbin:/sbin:$RUNNER_TEMP/nodeonly"
for t in timeout gtimeout; do
if PATH="$STOCK" command -v "$t" >/dev/null; then echo "::error::$t is on the stock PATH"; exit 1; fi
done
# macOS 15+ ships /usr/bin/jq; older macOS does not. The jq-less path
# is covered by hooks-without-jq (Linux); report which this runner is.
PATH="$STOCK" command -v jq >/dev/null && echo "stock jq present: $(PATH="$STOCK" jq --version)" || echo "stock jq absent"
env -i HOME="$HOME" PATH="$STOCK" /bin/bash hooks/tests/test-hooks.sh
# GIT-83: the release gate. Customers never run SQL after setup (standing
# rule, 2026-09-21), so a release must work on a store still on the v1.8.0
# setup.sql — the venue is put on exactly that schema first, then the
# current one. Runs on v* tags (publish depends on it) and on demand.
#
# Needs repository secrets, all for the DISPOSABLE venue (never production;
# scripts/venue-schema.sh and the driver both refuse it):
# VENUE_REF project ref
# VENUE_SUPABASE_URL https://<VENUE_REF>.supabase.co
# VENUE_SERVICE_ROLE_KEY service role key
# VENUE_DB_URL postgres:// URL (session pooler) for schema resets
venue-gate:
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 30
# One venue: two runs would wipe each other's data.
concurrency:
group: gitmem-venue
cancel-in-progress: false
env:
VENUE_REF: ${{ secrets.VENUE_REF }}
VENUE_DB_URL: ${{ secrets.VENUE_DB_URL }}
VENUE_SUPABASE_URL: ${{ secrets.VENUE_SUPABASE_URL }}
VENUE_SERVICE_ROLE_KEY: ${{ secrets.VENUE_SERVICE_ROLE_KEY }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # the v1.8.0 tag supplies the floor schema
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci --legacy-peer-deps
- run: npm run build
# Missing secrets fail the gate — a skipped gate would let publish through.
- name: Venue configured
run: |
missing=""
for v in VENUE_REF VENUE_DB_URL VENUE_SUPABASE_URL VENUE_SERVICE_ROLE_KEY; do
[ -n "${!v}" ] || missing="$missing $v"
done
if [ -n "$missing" ]; then echo "::error::venue gate cannot run, missing secrets:$missing"; exit 1; fi
umask 077
printf 'SUPABASE_URL=%s\nSUPABASE_SERVICE_ROLE_KEY=%s\nVENUE_REF=%s\n' \
"$VENUE_SUPABASE_URL" "$VENUE_SERVICE_ROLE_KEY" "$VENUE_REF" > "$RUNNER_TEMP/venue.env"
echo "VENUE_ENV=$RUNNER_TEMP/venue.env" >> "$GITHUB_ENV"
echo "RUNS=$RUNNER_TEMP/venue-runs" >> "$GITHUB_ENV"
mkdir -p "$RUNNER_TEMP/venue-runs"
git show v1.8.0:schema/setup.sql > "$RUNNER_TEMP/setup-v1.8.0.sql"
- name: Venue on the v1.8.0 setup.sql
run: scripts/venue-schema.sh reset-to "$RUNNER_TEMP/setup-v1.8.0.sql"
- name: Driver on v1.8.0 — flow
run: node tests/e2e/blank-supabase.mjs flow --label v180-flow --out "$RUNS"
- name: Driver on v1.8.0 — egress
run: node tests/e2e/blank-supabase.mjs egress --label v180-egress --out "$RUNS" --rows 250 --usage 5
- name: Driver on v1.8.0 — projects (when the driver has it)
run: |
# The usage line lists the modes; a bare "projects" string also appears in a path.
if grep -q 'flow|egress|projects' tests/e2e/blank-supabase.mjs; then
node tests/e2e/blank-supabase.mjs projects --label v180-projects --out "$RUNS"
else
echo "driver has no projects mode in this revision"
fi
# The current setup.sql must apply on top of v1.8.0, and apply again.
- name: Venue on the current setup.sql (applied twice)
run: |
scripts/venue-schema.sh apply schema/setup.sql
scripts/venue-schema.sh apply schema/setup.sql
- name: Driver on the current schema — flow
run: node tests/e2e/blank-supabase.mjs flow --label current-flow --out "$RUNS"
- name: Driver reports
if: always()
uses: actions/upload-artifact@v4
with:
name: venue-gate-${{ github.run_id }}
# netlogs record method, path, status and body size only — no bodies or headers.
path: ${{ runner.temp }}/venue-runs
if-no-files-found: ignore
retention-days: 14
publish:
needs: [build, hooks-without-jq, hooks-macos, venue-gate]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: https://registry.npmjs.org
cache: npm
- run: npm ci --legacy-peer-deps
- run: npm run build
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}