Repository navigation
148 lines (136 loc) · 5.66 KB
/
Copy pathcompat.yml
File metadata and controls
148 lines (136 loc) · 5.66 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
name: Compat
# dshbase-style compatibility verification (weekly + per PR + on demand):
# 1. bare-import: install the packed tarball into an empty project (native
# builds allowlisted) and import its entry - catches devDependencies
# mistaken for dependencies and native-build gate regressions.
# 2. profile: install the tarball into a scratch DSH_HOME profile next to
# dsh-base + dsh-headless, assert the bundle row mounts (dump-config), and
# run one keyless headless task. MISSING_CREDENTIAL proves the plugin tree
# loaded; a hang (pending service) hits the 120s timeout and fails, which
# is exactly how a missing injected service surfaces.
# 3. uninstall: the profile install must be fully reversible.
# Platform guard: every assertion here is platform-neutral. Platform-specific
# behavior (Windows/macOS-only rows) is never asserted on this Linux runner.
on:
pull_request:
schedule:
- cron: '0 4 * * 1'
workflow_dispatch:
jobs:
bare-import:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
with:
version: 11.7.0
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install
run: pnpm install --frozen-lockfile
- name: Build and pack
run: |
pnpm run build
pnpm pack --pack-destination "$RUNNER_TEMP"
- name: Bare install + import smoke
run: |
set -euo pipefail
TARBALL="$(ls "$RUNNER_TEMP"/perrylink-dsh-github-*.tgz | head -n1)"
mkdir -p "$RUNNER_TEMP/bare" && cd "$RUNNER_TEMP/bare"
pnpm init >/dev/null
cat > pnpm-workspace.yaml <<'YAML'
packages:
- .
nodeLinker: hoisted
autoInstallPeers: true
allowBuilds:
'@deepseek-ai/dsh-subprocess-local': true
koffi: true
node-pty: true
protobufjs: true
'@google/genai': true
YAML
pnpm add "$TARBALL" >/dev/null
node --input-type=module -e "import('@perrylink/dsh-github').then(()=>process.exit(0)).catch(e=>{console.error(e);process.exit(1)})"
profile:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
with:
version: 11.7.0
- uses: actions/setup-node@v7
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install
run: pnpm install --frozen-lockfile
- name: Build and pack
run: |
pnpm run build
pnpm pack --pack-destination "$RUNNER_TEMP"
- name: Install dsh CLI
run: npm install -g @deepseek-ai/dsh@0.2.1-alpha.1
- name: Install into a scratch profile (builds allowlisted)
run: |
set -euo pipefail
TARBALL="$(ls "$RUNNER_TEMP"/perrylink-dsh-github-*.tgz | head -n1)"
export DSH_HOME="$RUNNER_TEMP/dsh-home"
mkdir -p "$DSH_HOME/profiles/compat"
cat > "$DSH_HOME/profiles/compat/pnpm-workspace.yaml" <<'YAML'
packages:
- .
nodeLinker: hoisted
minimumReleaseAge: 0
autoInstallPeers: false
allowBuilds:
'@deepseek-ai/dsh-subprocess-local': true
koffi: true
node-pty: true
protobufjs: true
'@google/genai': true
YAML
dsh plugin --profile compat add '@deepseek-ai/dsh-base@0.2.1-alpha.1' '@deepseek-ai/dsh-headless@0.2.1-alpha.1' "$TARBALL"
- name: Row-mount assertion
run: |
set -euo pipefail
export DSH_HOME="$RUNNER_TEMP/dsh-home"
dsh --profile compat --dump-config > dump.txt
grep -q "@perrylink/dsh-github" dump.txt
- name: Keyless headless smoke (best-effort; the mount proof above is the gate)
run: |
set -euo pipefail
export DSH_HOME="$RUNNER_TEMP/dsh-home"
set +e
timeout 120 dsh --profile compat "Reply with exactly: ok" > smoke.log 2>&1
code="$?"
set -e
# What this step can legitimately observe without an API key, measured on the
# pinned host line: the host either fails fast with a keyless abort, or blocks
# before writing anything. Both prove the tree reached the model call, which is
# all this step was ever meant to show - the deterministic mount proof is the
# --dump-config row assertion above. Note the abort code is not stable across
# environments: the runner reports TRANSPORT where a workstation reports
# MISSING_CREDENTIAL for the same missing key.
if grep -qE 'MISSING_CREDENTIAL|INVALID_CREDENTIAL|NO_ADAPTER|TRANSPORT|AUTH' smoke.log; then
echo 'PASS: plugin tree loaded (keyless abort):'
grep -oE 'MISSING_CREDENTIAL|INVALID_CREDENTIAL|NO_ADAPTER|TRANSPORT|AUTH' smoke.log | sort -u | sed 's/^/ /'
elif [ "$code" -eq 0 ] && grep -qiE '(^|[^a-z])ok([^a-z]|$)' smoke.log; then
echo 'PASS: plugin tree loaded (with key)'
elif [ "$code" -eq 124 ] && [ ! -s smoke.log ]; then
echo 'PASS: mount proven above; the keyless host blocked instead of aborting (no output, 120s)'
else
echo 'FAIL: headless smoke produced a real error (not a keyless abort)'
cat smoke.log
exit 1
fi
- name: Uninstall
run: |
set -euo pipefail
export DSH_HOME="$RUNNER_TEMP/dsh-home"
dsh plugin --profile compat remove @perrylink/dsh-github