Skip to content

Commit 0dfda83

Browse files
author
SpecBridge
committed
chore: shard CLI integration and harden release reliability (v2.4.3)
1 parent 7bfca60 commit 0dfda83

14 files changed

Lines changed: 721 additions & 441 deletions

.github/workflows/ci.yml

Lines changed: 116 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -65,36 +65,77 @@ jobs:
6565
- name: Build
6666
run: npm run build
6767

68-
- name: Run core integration tests (retry once on failure)
68+
- name: Run core integration tests (retry once on failure + runtime budget)
6969
id: integration_core
70+
shell: bash
71+
timeout-minutes: 12
7072
run: |
7173
set +e
72-
npm run test:integration:core
74+
budget_seconds=120
75+
76+
run_core() {
77+
local attempt="$1"
78+
local log_file="integration-core-${attempt}.log"
79+
local started_at ended_at status
80+
81+
started_at=$(date +%s)
82+
npm run test:integration:core 2>&1 | tee "$log_file"
83+
status=${PIPESTATUS[0]}
84+
ended_at=$(date +%s)
85+
duration_seconds=$((ended_at - started_at))
86+
87+
echo "### Core integration (${attempt})" >> "$GITHUB_STEP_SUMMARY"
88+
echo "- status: ${status}" >> "$GITHUB_STEP_SUMMARY"
89+
echo "- duration: ${duration_seconds}s (budget ${budget_seconds}s)" >> "$GITHUB_STEP_SUMMARY"
90+
return "$status"
91+
}
92+
93+
run_core "run1"
7394
first_exit=$?
74-
if [ "$first_exit" -eq 0 ]; then
75-
echo "flaky=false" >> "$GITHUB_OUTPUT"
76-
exit 0
77-
fi
95+
first_duration=$duration_seconds
96+
97+
if [ "$first_exit" -ne 0 ]; then
98+
echo "First core integration run failed. Retrying once..."
99+
run_core "run2"
100+
second_exit=$?
101+
second_duration=$duration_seconds
102+
if [ "$second_exit" -ne 0 ]; then
103+
echo "flaky=false" >> "$GITHUB_OUTPUT"
104+
exit "$second_exit"
105+
fi
78106
79-
echo "First core integration run failed. Retrying once..."
80-
npm run test:integration:core
81-
second_exit=$?
82-
if [ "$second_exit" -eq 0 ]; then
83107
echo "flaky=true" >> "$GITHUB_OUTPUT"
84-
exit 0
108+
final_duration=$second_duration
109+
else
110+
echo "flaky=false" >> "$GITHUB_OUTPUT"
111+
final_duration=$first_duration
85112
fi
86113
87-
echo "flaky=false" >> "$GITHUB_OUTPUT"
88-
exit "$second_exit"
114+
echo "final_duration=${final_duration}" >> "$GITHUB_OUTPUT"
115+
if [ "$final_duration" -gt "$budget_seconds" ]; then
116+
echo "Core integration exceeded runtime budget (${final_duration}s > ${budget_seconds}s)."
117+
exit 1
118+
fi
89119
90120
- name: Annotate flaky core integration
91121
if: steps.integration_core.outputs.flaky == 'true'
92122
run: |
93123
echo "### Flaky integration detected (core)" >> "$GITHUB_STEP_SUMMARY"
94124
echo "- First run failed, retry passed." >> "$GITHUB_STEP_SUMMARY"
95125
126+
- name: Upload core integration logs on failure
127+
if: failure()
128+
uses: actions/upload-artifact@v4
129+
with:
130+
name: integration-core-logs
131+
path: integration-core-*.log
132+
retention-days: 7
133+
96134
test-integration-cli:
97135
runs-on: ubuntu-latest
136+
strategy:
137+
matrix:
138+
suite: [smoke, core, aux]
98139
env:
99140
HUSKY: 0
100141

@@ -113,34 +154,82 @@ jobs:
113154
- name: Build
114155
run: npm run build
115156

116-
- name: Run CLI integration tests (retry once on failure)
157+
- name: Run CLI integration suite (retry once on failure + runtime budget)
117158
id: integration_cli
159+
shell: bash
160+
timeout-minutes: 12
118161
run: |
119162
set +e
120-
npm run test:integration:cli
163+
case "${{ matrix.suite }}" in
164+
smoke)
165+
budget_seconds=90
166+
;;
167+
core|aux)
168+
budget_seconds=180
169+
;;
170+
*)
171+
budget_seconds=180
172+
;;
173+
esac
174+
175+
run_suite() {
176+
local attempt="$1"
177+
local log_file="integration-cli-${{ matrix.suite }}-${attempt}.log"
178+
local started_at ended_at status
179+
180+
started_at=$(date +%s)
181+
npm run "test:integration:cli:${{ matrix.suite }}" 2>&1 | tee "$log_file"
182+
status=${PIPESTATUS[0]}
183+
ended_at=$(date +%s)
184+
duration_seconds=$((ended_at - started_at))
185+
186+
echo "### CLI integration (${{ matrix.suite }} / ${attempt})" >> "$GITHUB_STEP_SUMMARY"
187+
echo "- status: ${status}" >> "$GITHUB_STEP_SUMMARY"
188+
echo "- duration: ${duration_seconds}s (budget ${budget_seconds}s)" >> "$GITHUB_STEP_SUMMARY"
189+
return "$status"
190+
}
191+
192+
run_suite "run1"
121193
first_exit=$?
122-
if [ "$first_exit" -eq 0 ]; then
123-
echo "flaky=false" >> "$GITHUB_OUTPUT"
124-
exit 0
125-
fi
194+
first_duration=$duration_seconds
195+
196+
if [ "$first_exit" -ne 0 ]; then
197+
echo "First CLI integration run failed for suite '${{ matrix.suite }}'. Retrying once..."
198+
run_suite "run2"
199+
second_exit=$?
200+
second_duration=$duration_seconds
201+
if [ "$second_exit" -ne 0 ]; then
202+
echo "flaky=false" >> "$GITHUB_OUTPUT"
203+
exit "$second_exit"
204+
fi
126205
127-
echo "First CLI integration run failed. Retrying once..."
128-
npm run test:integration:cli
129-
second_exit=$?
130-
if [ "$second_exit" -eq 0 ]; then
131206
echo "flaky=true" >> "$GITHUB_OUTPUT"
132-
exit 0
207+
final_duration=$second_duration
208+
else
209+
echo "flaky=false" >> "$GITHUB_OUTPUT"
210+
final_duration=$first_duration
133211
fi
134212
135-
echo "flaky=false" >> "$GITHUB_OUTPUT"
136-
exit "$second_exit"
213+
echo "final_duration=${final_duration}" >> "$GITHUB_OUTPUT"
214+
if [ "$final_duration" -gt "$budget_seconds" ]; then
215+
echo "CLI integration suite '${{ matrix.suite }}' exceeded runtime budget (${final_duration}s > ${budget_seconds}s)."
216+
exit 1
217+
fi
137218
138219
- name: Annotate flaky CLI integration
139220
if: steps.integration_cli.outputs.flaky == 'true'
140221
run: |
141-
echo "### Flaky integration detected (cli)" >> "$GITHUB_STEP_SUMMARY"
222+
echo "### Flaky integration detected (cli / ${{ matrix.suite }})" >> "$GITHUB_STEP_SUMMARY"
142223
echo "- First run failed, retry passed." >> "$GITHUB_STEP_SUMMARY"
143224
225+
- name: Upload CLI integration logs on failure
226+
if: failure()
227+
uses: actions/upload-artifact@v4
228+
with:
229+
name: integration-cli-logs-${{ matrix.suite }}
230+
path: integration-cli-${{ matrix.suite }}-*.log
231+
retention-days: 7
232+
144233
lint:
145234
runs-on: ubuntu-latest
146235
env:

.github/workflows/publish.yml

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,70 @@ jobs:
3333
- name: Build
3434
run: npm run build
3535

36-
- name: Run integration tests
37-
run: npm run test:integration
36+
- name: Run integration tests (retry once on failure + runtime budget)
37+
id: integration_release
38+
shell: bash
39+
timeout-minutes: 20
40+
run: |
41+
set +e
42+
budget_seconds=480
43+
44+
run_release_integration() {
45+
local attempt="$1"
46+
local log_file="publish-integration-${attempt}.log"
47+
local started_at ended_at status
48+
49+
started_at=$(date +%s)
50+
timeout 15m npm run test:integration 2>&1 | tee "$log_file"
51+
status=${PIPESTATUS[0]}
52+
ended_at=$(date +%s)
53+
duration_seconds=$((ended_at - started_at))
54+
55+
echo "### Publish integration (${attempt})" >> "$GITHUB_STEP_SUMMARY"
56+
echo "- status: ${status}" >> "$GITHUB_STEP_SUMMARY"
57+
echo "- duration: ${duration_seconds}s (budget ${budget_seconds}s)" >> "$GITHUB_STEP_SUMMARY"
58+
return "$status"
59+
}
60+
61+
run_release_integration "run1"
62+
first_exit=$?
63+
first_duration=$duration_seconds
64+
65+
if [ "$first_exit" -ne 0 ]; then
66+
echo "First publish integration run failed. Retrying once..."
67+
run_release_integration "run2"
68+
second_exit=$?
69+
second_duration=$duration_seconds
70+
if [ "$second_exit" -ne 0 ]; then
71+
echo "flaky=false" >> "$GITHUB_OUTPUT"
72+
exit "$second_exit"
73+
fi
74+
75+
echo "flaky=true" >> "$GITHUB_OUTPUT"
76+
final_duration=$second_duration
77+
else
78+
echo "flaky=false" >> "$GITHUB_OUTPUT"
79+
final_duration=$first_duration
80+
fi
81+
82+
if [ "$final_duration" -gt "$budget_seconds" ]; then
83+
echo "Publish integration exceeded runtime budget (${final_duration}s > ${budget_seconds}s)."
84+
exit 1
85+
fi
86+
87+
- name: Annotate flaky publish integration
88+
if: steps.integration_release.outputs.flaky == 'true'
89+
run: |
90+
echo "### Flaky integration detected in publish workflow" >> "$GITHUB_STEP_SUMMARY"
91+
echo "- First run failed, retry passed." >> "$GITHUB_STEP_SUMMARY"
92+
93+
- name: Upload publish integration logs on failure
94+
if: failure()
95+
uses: actions/upload-artifact@v4
96+
with:
97+
name: publish-integration-logs
98+
path: publish-integration-*.log
99+
retention-days: 7
38100

39101
- name: Verify package contents
40102
run: npm run pack:check

docs/maintenance/project-health.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Use this checklist for monthly maintenance or before a release.
77
```bash
88
npm ci
99
npm run health:check
10-
npm outdated
10+
npm run deps:outdated
1111
```
1212

1313
Expanded equivalent:
@@ -19,11 +19,13 @@ npm run lint:check
1919
npm run format:check
2020
npm test
2121
npm run test:integration:core
22-
npm run test:integration:cli
22+
npm run test:integration:cli:smoke
23+
npm run test:integration:cli:core
24+
npm run test:integration:cli:aux
2325
npm run test:coverage
2426
npm run pack:check
2527
npm audit --audit-level=high
26-
npm outdated
28+
npm run deps:outdated
2729
```
2830

2931
## Acceptance Criteria
@@ -36,6 +38,7 @@ npm outdated
3638
- Packaging checks pass with and without lifecycle scripts.
3739
- Runtime policy in docs matches `package.json` `engines.node`.
3840
- Integration retries (if needed) are annotated in CI step summaries as flaky.
41+
- Core and CLI integration runtime stay within configured CI budgets.
3942

4043
## Release Readiness Notes
4144

@@ -50,3 +53,13 @@ Track these regularly:
5053
- Major-version drift in core toolchain (`eslint`, `typescript`, `vitest`).
5154
- CI runtime drift vs dependency engine requirements.
5255
- Test runtime growth and flakiness in long integration suites.
56+
57+
## Troubleshooting
58+
59+
If dependency checks fail with `EACCES` under `~/.npm`, use local cache overrides:
60+
61+
```bash
62+
npm_config_cache=.cache/npm npm outdated --long
63+
```
64+
65+
This avoids root-owned global npm cache issues on local machines and CI mirrors.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ipation/specbridge",
3-
"version": "2.4.2",
3+
"version": "2.4.3",
44
"description": "Architecture Decision Runtime - Transform architectural decisions into executable, verifiable constraints",
55
"type": "module",
66
"main": "./dist/index.js",
@@ -23,6 +23,9 @@
2323
"test:integration": "npm run test:integration:core && npm run test:integration:cli",
2424
"test:integration:core": "vitest run --config vitest.integration.core.config.ts",
2525
"test:integration:cli": "vitest run --config vitest.integration.cli.config.ts",
26+
"test:integration:cli:smoke": "vitest run --config vitest.integration.cli.config.ts tests/integration/cli/smoke.test.ts",
27+
"test:integration:cli:core": "vitest run --config vitest.integration.cli.config.ts tests/integration/cli/init-verify.test.ts tests/integration/cli/infer-decision.test.ts",
28+
"test:integration:cli:aux": "vitest run --config vitest.integration.cli.config.ts tests/integration/cli/hook-report-context.test.ts tests/integration/cli/errors.test.ts",
2629
"test:coverage": "vitest run --coverage",
2730
"test:ui": "vitest --ui",
2831
"lint": "eslint .",
@@ -37,6 +40,7 @@
3740
"docs": "typedoc --out docs/api src/index.ts",
3841
"docs:serve": "npm run docs && npx http-server docs/api",
3942
"pack:check": "npm_config_cache=.cache/npm npm pack --ignore-scripts && npm_config_cache=.cache/npm HUSKY=0 npm pack --dry-run",
43+
"deps:outdated": "npm_config_cache=.cache/npm npm outdated --long",
4044
"health:check": "npm run type-check && npm run lint:check && npm run format:check && npm run test && npm run test:integration && npm run test:coverage && npm audit --audit-level=high",
4145
"prepare": "husky",
4246
"prepublishOnly": "npm run build"

0 commit comments

Comments
 (0)