-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
175 lines (169 loc) Β· 7.44 KB
/
Copy pathci.yml
File metadata and controls
175 lines (169 loc) Β· 7.44 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
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
node:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}
# package.json's "test" passes --test-force-exit, which needs Node >=20.14.
# Node 18 is still a supported RUNTIME (engines ">=18"; bin/install.js
# refuses to run below 18), so it stays in the matrix and runs the suite
# without the flag rather than being dropped β testing a version we claim
# to support matters more than uniform invocation. Verified flagless on
# 18.20.8: 172/172, no hang. The job timeout is the backstop the flag
# would otherwise provide.
- name: Installer test suite
run: |
if node -e 'process.exit(process.versions.node.split(".")[0] >= 20 ? 0 : 1)'; then
npm test
else
node --test tests/installer/*.test.mjs
fi
- name: Standalone hook/tool tests
run: |
for f in tests/test_*.js; do
echo "== $f"
node "$f"
done
python:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.11'
# Several python tests shell out to node for hook checks β don't rely
# on the runner image happening to ship it.
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
- name: Python test suite
run: python -m unittest discover -s tests -v
# The Windows surface nothing else covers.
#
# engine-ci.yml already runs npm test, tests/*.js, the Python suites and
# verify_repo.py on windows-latest β that is not duplicated here. What it
# never exercised is the PowerShell installer and the shell contract for the
# hook commands we write, which is how #835 shipped: settings.json got
# PowerShell call-operator syntax that Git Bash β Claude Code's actual
# Windows hook shell β rejects with a syntax error, so every standalone
# Windows install had two dead hooks and no test noticed.
#
# tests/test_hooks.py skips its install flow on Windows ("POSIX shell install
# path; Windows uses install.ps1"). That skip is correct, and this job is what
# makes it safe: it covers the install.ps1 path the skip hands off to.
#
# Kept deliberately small so it runs in a few minutes and a red here means
# something real.
windows-powershell:
runs-on: windows-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
# The hook runner Claude Code uses on Windows IS Git Bash. Windows runners
# ship Git for Windows, so this is the real shell, not a stand-in.
- name: Git Bash is present (Claude Code's Windows hook shell)
shell: pwsh
run: |
$bash = Get-Command bash -ErrorAction Stop
Write-Host "bash: $($bash.Source)"
bash --version
# Hook-command shape is asserted cross-platform in
# tests/installer/platform-paths.test.mjs, but only here does it face the
# real Git Bash build that ships on Windows.
- name: Hook command shape parses under the real Git Bash
shell: pwsh
run: node --test --test-force-exit tests/installer/platform-paths.test.mjs
- name: Hook stdin lifecycle (no waiting on a lagging pipe close)
shell: pwsh
run: node tests/test_hook_stdin_lifecycle.js
- name: PowerShell scripts parse
shell: pwsh
run: |
$bad = 0
Get-ChildItem -Recurse -Filter *.ps1 -File |
Where-Object { $_.FullName -notmatch 'node_modules' } |
ForEach-Object {
$errors = $null; $tokens = $null
[void][System.Management.Automation.Language.Parser]::ParseFile(
$_.FullName, [ref]$tokens, [ref]$errors)
if ($errors.Count -gt 0) {
$bad++
Write-Host "PARSE FAIL: $($_.FullName)"
$errors | ForEach-Object { Write-Host " $($_.Message)" }
}
}
if ($bad -gt 0) { exit 1 }
- name: Standalone hook install/uninstall round trip
shell: pwsh
env:
CLAUDE_CONFIG_DIR: ${{ runner.temp }}\caveman-hooks-test
run: |
New-Item -ItemType Directory -Force -Path $env:CLAUDE_CONFIG_DIR | Out-Null
'{ "theme": "dark" }' | Set-Content "$env:CLAUDE_CONFIG_DIR\settings.json"
./src/hooks/install.ps1
$s = Get-Content "$env:CLAUDE_CONFIG_DIR\settings.json" -Raw | ConvertFrom-Json
if (-not $s.hooks.SessionStart) { throw "SessionStart hook was not wired" }
# Every hook command we write is evaluated by Git Bash. If bash cannot
# parse it, the hook is dead on arrival for every session (#835).
foreach ($event in $s.hooks.PSObject.Properties.Name) {
foreach ($entry in $s.hooks.$event) {
foreach ($h in $entry.hooks) {
bash -n -c $h.command
if ($LASTEXITCODE -ne 0) { throw "bash cannot parse hook command: $($h.command)" }
}
}
}
./src/hooks/uninstall.ps1
$after = Get-Content "$env:CLAUDE_CONFIG_DIR\settings.json" -Raw | ConvertFrom-Json
if ($after.hooks) { throw "uninstall left caveman hooks behind" }
if ($after.theme -ne 'dark') { throw "uninstall destroyed the user's own settings" }
# macOS is the primary development platform and had no runner at all: every
# `runs-on:` in this repo was ubuntu-latest plus one windows-latest, so "CI
# passes" proved nothing about the platform most of this code is written on.
# bash 3.2, BSD sed/find/readlink, and the POSIX install path all live here.
macos:
runs-on: macos-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 22
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.13'
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: go.mod
- name: Bash version (macOS ships 3.2 β no bash 4+ syntax may creep in)
run: bash --version
- name: Installer test suite
run: npm test
- name: Standalone hook/tool tests
run: node --test --test-force-exit tests/*.js
- name: Python test suite
run: python -m unittest discover -s tests
- name: Repo verification
run: python tests/verify_repo.py
# Without this the macOS runner touches no Go at all, so a BSD-only path,
# spawn or timer regression in the engine/proxy ships fully green on the
# platform this job exists to cover.
- name: Go test suite
run: go test ./engine/... ./proxy/... ./shared/...