@metasession.co/devaudit-cli 0.3.7 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/scripts/upload-evidence.sh +33 -3
- package/sdlc/files/_common/scripts/close-out-contract.sh +34 -0
- package/sdlc/files/_common/scripts/derive-release-version.sh +18 -0
- package/sdlc/files/_common/scripts/derive-release-version.test.sh +57 -0
- package/sdlc/files/_common/scripts/extract-release-metadata.sh +119 -0
- package/sdlc/files/_common/scripts/extract-release-metadata.test.sh +363 -0
- package/sdlc/files/_common/scripts/upload-evidence.sh +593 -0
- package/sdlc/files/_common/scripts/validate-test-summary.sh +37 -0
- package/sdlc/files/_common/scripts/validate-test-summary.test.sh +87 -0
- package/sdlc/files/_common/skills/e2e-test-engineer/SKILL.md +16 -0
- package/sdlc/files/_common/skills/sdlc-implementer/SKILL.md +7 -4
- package/sdlc/files/ci/check-release-approval.yml.template +80 -21
- package/sdlc/files/ci/ci-status-fallback.yml.template +3 -0
- package/sdlc/files/ci/ci.yml.template +24 -33
- package/sdlc/files/ci/close-out-release.yml.template +67 -11
- package/sdlc/files/ci/compliance-evidence.yml.template +32 -16
- package/sdlc/files/ci/quality-gates-provenance.yml.template +62 -0
- package/sdlc/files/stacks/node/hooks/pre-push +58 -8
- package/sdlc/package.json +1 -1
- package/sdlc/src/bin/devaudit-sdlc.js +22 -2
- package/sdlc/src/blueprints/3-compile-evidence.raw.md +20 -6
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# extract-release-metadata.test.sh — Tests for extract-release-metadata.sh.
|
|
3
|
+
#
|
|
4
|
+
# Creates throwaway release-ticket fixtures, sources the helper, and asserts
|
|
5
|
+
# on the extracted title and summary. Hermetic: runs inside mktemp'd
|
|
6
|
+
# directories that are torn down at the end.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./scripts/extract-release-metadata.test.sh
|
|
10
|
+
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
14
|
+
HELPER="$SCRIPT_DIR/extract-release-metadata.sh"
|
|
15
|
+
[ -x "$HELPER" ] || chmod +x "$HELPER"
|
|
16
|
+
|
|
17
|
+
PASS=0
|
|
18
|
+
FAIL=0
|
|
19
|
+
|
|
20
|
+
WORK=$(mktemp -d)
|
|
21
|
+
trap 'rm -rf "$WORK"' EXIT
|
|
22
|
+
|
|
23
|
+
# $1 = test name, $2 = expected, $3 = actual
|
|
24
|
+
assert_eq() {
|
|
25
|
+
local name="$1" expected="$2" actual="$3"
|
|
26
|
+
if [ "$expected" = "$actual" ]; then
|
|
27
|
+
echo " ✓ $name"
|
|
28
|
+
PASS=$((PASS + 1))
|
|
29
|
+
else
|
|
30
|
+
echo " ✗ $name"
|
|
31
|
+
echo " Expected: $expected"
|
|
32
|
+
echo " Actual: $actual"
|
|
33
|
+
FAIL=$((FAIL + 1))
|
|
34
|
+
fi
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
assert_empty() {
|
|
38
|
+
local name="$1" actual="$2"
|
|
39
|
+
if [ -z "$actual" ]; then
|
|
40
|
+
echo " ✓ $name"
|
|
41
|
+
PASS=$((PASS + 1))
|
|
42
|
+
else
|
|
43
|
+
echo " ✗ $name (expected empty, got: $actual)"
|
|
44
|
+
FAIL=$((FAIL + 1))
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# $1 = test dir
|
|
49
|
+
make_fixture() {
|
|
50
|
+
local dir="$1"
|
|
51
|
+
rm -rf "$dir"
|
|
52
|
+
mkdir -p "$dir/compliance/pending-releases"
|
|
53
|
+
mkdir -p "$dir/compliance/approved-releases"
|
|
54
|
+
cd "$dir"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
echo "=== extract-release-metadata.sh tests ==="
|
|
58
|
+
echo ""
|
|
59
|
+
|
|
60
|
+
# --- Test 1: Extract title from **Requirement:** line ---
|
|
61
|
+
echo "--- Test 1: Title from **Requirement:** line ---"
|
|
62
|
+
make_fixture "$WORK/test1"
|
|
63
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-089.md" <<'TICKET'
|
|
64
|
+
# Release Ticket — REQ-089
|
|
65
|
+
|
|
66
|
+
**Requirement:** REQ-089 — Admin order management: portion size selection, manual price override, per-item special instructions, stock validation
|
|
67
|
+
|
|
68
|
+
## Summary
|
|
69
|
+
This release implements admin order management features including portion size
|
|
70
|
+
selection, manual price override, and per-item special instructions.
|
|
71
|
+
|
|
72
|
+
## Changes
|
|
73
|
+
- Added portion size dropdown
|
|
74
|
+
- Added manual price override
|
|
75
|
+
TICKET
|
|
76
|
+
|
|
77
|
+
source "$HELPER"
|
|
78
|
+
extract_release_metadata "REQ-089"
|
|
79
|
+
assert_eq "Title from Requirement line" \
|
|
80
|
+
"Admin order management: portion size selection, manual price override, per-item special instructions, stock validation" \
|
|
81
|
+
"$RELEASE_TITLE"
|
|
82
|
+
assert_eq "Summary extracted" \
|
|
83
|
+
"This release implements admin order management features including portion size
|
|
84
|
+
selection, manual price override, and per-item special instructions." \
|
|
85
|
+
"$RELEASE_SUMMARY"
|
|
86
|
+
echo ""
|
|
87
|
+
|
|
88
|
+
# --- Test 2: Fallback to H1 when no **Requirement:** line ---
|
|
89
|
+
echo "--- Test 2: Fallback to normalised H1 ---"
|
|
90
|
+
make_fixture "$WORK/test2"
|
|
91
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-001.md" <<'TICKET'
|
|
92
|
+
# Release Ticket — REQ-001
|
|
93
|
+
|
|
94
|
+
## Summary
|
|
95
|
+
Some summary here.
|
|
96
|
+
TICKET
|
|
97
|
+
|
|
98
|
+
source "$HELPER"
|
|
99
|
+
extract_release_metadata "REQ-001"
|
|
100
|
+
assert_eq "H1 fallback strips 'Release Ticket —' prefix" \
|
|
101
|
+
"REQ-001" \
|
|
102
|
+
"$RELEASE_TITLE"
|
|
103
|
+
echo ""
|
|
104
|
+
|
|
105
|
+
# --- Test 3: Empty title when no ticket exists ---
|
|
106
|
+
echo "--- Test 3: Empty title when no ticket ---"
|
|
107
|
+
make_fixture "$WORK/test3"
|
|
108
|
+
source "$HELPER"
|
|
109
|
+
extract_release_metadata "REQ-999"
|
|
110
|
+
assert_empty "Title empty when no ticket" "$RELEASE_TITLE"
|
|
111
|
+
assert_empty "Summary empty when no ticket" "$RELEASE_SUMMARY"
|
|
112
|
+
echo ""
|
|
113
|
+
|
|
114
|
+
# --- Test 4: Summary with placeholder text is cleared ---
|
|
115
|
+
echo "--- Test 4: Placeholder summary is cleared ---"
|
|
116
|
+
make_fixture "$WORK/test4"
|
|
117
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-002.md" <<'TICKET'
|
|
118
|
+
# Release Ticket — REQ-002
|
|
119
|
+
|
|
120
|
+
**Requirement:** REQ-002 — Some feature
|
|
121
|
+
|
|
122
|
+
## Summary
|
|
123
|
+
TODO: Add summary
|
|
124
|
+
|
|
125
|
+
## Changes
|
|
126
|
+
- Stuff
|
|
127
|
+
TICKET
|
|
128
|
+
|
|
129
|
+
source "$HELPER"
|
|
130
|
+
extract_release_metadata "REQ-002"
|
|
131
|
+
assert_eq "Title still extracted" "Some feature" "$RELEASE_TITLE"
|
|
132
|
+
assert_empty "Placeholder summary cleared" "$RELEASE_SUMMARY"
|
|
133
|
+
echo ""
|
|
134
|
+
|
|
135
|
+
# --- Test 5: No Summary section → empty summary ---
|
|
136
|
+
echo "--- Test 5: No Summary section ---"
|
|
137
|
+
make_fixture "$WORK/test5"
|
|
138
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-003.md" <<'TICKET'
|
|
139
|
+
# Release Ticket — REQ-003
|
|
140
|
+
|
|
141
|
+
**Requirement:** REQ-003 — Another feature
|
|
142
|
+
|
|
143
|
+
## Changes
|
|
144
|
+
- Change A
|
|
145
|
+
TICKET
|
|
146
|
+
|
|
147
|
+
source "$HELPER"
|
|
148
|
+
extract_release_metadata "REQ-003"
|
|
149
|
+
assert_eq "Title extracted" "Another feature" "$RELEASE_TITLE"
|
|
150
|
+
assert_empty "Summary empty when no section" "$RELEASE_SUMMARY"
|
|
151
|
+
echo ""
|
|
152
|
+
|
|
153
|
+
# --- Test 6: Summary stops at next ## heading ---
|
|
154
|
+
echo "--- Test 6: Summary stops at next ## ---"
|
|
155
|
+
make_fixture "$WORK/test6"
|
|
156
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-004.md" <<'TICKET'
|
|
157
|
+
# Release Ticket — REQ-004
|
|
158
|
+
|
|
159
|
+
**Requirement:** REQ-004 — Feature four
|
|
160
|
+
|
|
161
|
+
## Summary
|
|
162
|
+
Line one of summary.
|
|
163
|
+
Line two of summary.
|
|
164
|
+
|
|
165
|
+
## Changes
|
|
166
|
+
This should NOT be in summary.
|
|
167
|
+
TICKET
|
|
168
|
+
|
|
169
|
+
source "$HELPER"
|
|
170
|
+
extract_release_metadata "REQ-004"
|
|
171
|
+
assert_eq "Title" "Feature four" "$RELEASE_TITLE"
|
|
172
|
+
assert_eq "Summary stops at next ##" \
|
|
173
|
+
"Line one of summary.
|
|
174
|
+
Line two of summary." \
|
|
175
|
+
"$RELEASE_SUMMARY"
|
|
176
|
+
echo ""
|
|
177
|
+
|
|
178
|
+
# --- Test 7: Approved-releases fallback when no pending ticket ---
|
|
179
|
+
echo "--- Test 7: Approved-releases fallback ---"
|
|
180
|
+
make_fixture "$WORK/test7"
|
|
181
|
+
cat > "compliance/approved-releases/RELEASE-TICKET-REQ-005.md" <<'TICKET'
|
|
182
|
+
# Release Ticket — REQ-005
|
|
183
|
+
|
|
184
|
+
**Requirement:** REQ-005 — Approved feature
|
|
185
|
+
|
|
186
|
+
## Summary
|
|
187
|
+
Summary from approved ticket.
|
|
188
|
+
TICKET
|
|
189
|
+
|
|
190
|
+
source "$HELPER"
|
|
191
|
+
extract_release_metadata "REQ-005"
|
|
192
|
+
assert_eq "Title from approved-releases" "Approved feature" "$RELEASE_TITLE"
|
|
193
|
+
assert_eq "Summary from approved-releases" "Summary from approved ticket." "$RELEASE_SUMMARY"
|
|
194
|
+
echo ""
|
|
195
|
+
|
|
196
|
+
# --- Test 8: Em-dash variant in Requirement line ---
|
|
197
|
+
echo "--- Test 8: Em-dash variant ---"
|
|
198
|
+
make_fixture "$WORK/test8"
|
|
199
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-006.md" <<'TICKET'
|
|
200
|
+
# Release Ticket — REQ-006
|
|
201
|
+
|
|
202
|
+
**Requirement:** REQ-006 — Feature with em-dash
|
|
203
|
+
|
|
204
|
+
## Summary
|
|
205
|
+
Summary.
|
|
206
|
+
TICKET
|
|
207
|
+
|
|
208
|
+
source "$HELPER"
|
|
209
|
+
extract_release_metadata "REQ-006"
|
|
210
|
+
assert_eq "Em-dash title" "Feature with em-dash" "$RELEASE_TITLE"
|
|
211
|
+
echo ""
|
|
212
|
+
|
|
213
|
+
# --- Test 9: H1 with human title (not just REQ-XXX) ---
|
|
214
|
+
echo "--- Test 9: H1 with human title fallback ---"
|
|
215
|
+
make_fixture "$WORK/test9"
|
|
216
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-007.md" <<'TICKET'
|
|
217
|
+
# Fix login redirect bug
|
|
218
|
+
|
|
219
|
+
## Summary
|
|
220
|
+
Fixes the redirect issue.
|
|
221
|
+
TICKET
|
|
222
|
+
|
|
223
|
+
source "$HELPER"
|
|
224
|
+
extract_release_metadata "REQ-007"
|
|
225
|
+
assert_eq "H1 human title fallback" "Fix login redirect bug" "$RELEASE_TITLE"
|
|
226
|
+
echo ""
|
|
227
|
+
|
|
228
|
+
# --- Test 10: Summary with leading/trailing blank lines trimmed ---
|
|
229
|
+
echo "--- Test 10: Summary blank line trimming ---"
|
|
230
|
+
make_fixture "$WORK/test10"
|
|
231
|
+
printf '%s\n' \
|
|
232
|
+
'# Release Ticket — REQ-008' \
|
|
233
|
+
'' \
|
|
234
|
+
'**Requirement:** REQ-008 — Feature eight' \
|
|
235
|
+
'' \
|
|
236
|
+
'## Summary' \
|
|
237
|
+
'' \
|
|
238
|
+
'' \
|
|
239
|
+
'Actual summary content.' \
|
|
240
|
+
'' \
|
|
241
|
+
'' \
|
|
242
|
+
'## Changes' \
|
|
243
|
+
'- Change' > "compliance/pending-releases/RELEASE-TICKET-REQ-008.md"
|
|
244
|
+
|
|
245
|
+
source "$HELPER"
|
|
246
|
+
extract_release_metadata "REQ-008"
|
|
247
|
+
assert_eq "Title" "Feature eight" "$RELEASE_TITLE"
|
|
248
|
+
assert_eq "Summary trimmed" "Actual summary content." "$RELEASE_SUMMARY"
|
|
249
|
+
echo ""
|
|
250
|
+
|
|
251
|
+
# --- Test 11: RTM issue title fallback without release ticket ---
|
|
252
|
+
echo "--- Test 11: RTM issue title fallback without release ticket ---"
|
|
253
|
+
make_fixture "$WORK/test11"
|
|
254
|
+
cat > compliance/RTM.md <<'RTM'
|
|
255
|
+
| REQ-ID | Issue | Risk | Evidence | Status |
|
|
256
|
+
| ------- | ----- | ---- | -------- | ------ |
|
|
257
|
+
| REQ-011 | #456 | LOW | n/a | DRAFT |
|
|
258
|
+
RTM
|
|
259
|
+
mkdir -p bin
|
|
260
|
+
cat > bin/gh <<'GH'
|
|
261
|
+
#!/usr/bin/env bash
|
|
262
|
+
if [ "$1" = "issue" ] && [ "$2" = "view" ] && [ "$3" = "456" ]; then
|
|
263
|
+
printf '%s\n' "Issue title from RTM"
|
|
264
|
+
exit 0
|
|
265
|
+
fi
|
|
266
|
+
exit 1
|
|
267
|
+
GH
|
|
268
|
+
chmod +x bin/gh
|
|
269
|
+
PATH="$PWD/bin:$PATH"
|
|
270
|
+
source "$HELPER"
|
|
271
|
+
extract_release_metadata "REQ-011"
|
|
272
|
+
assert_eq "RTM issue title fallback without ticket" "Issue title from RTM" "$RELEASE_TITLE"
|
|
273
|
+
assert_empty "Summary empty without ticket" "$RELEASE_SUMMARY"
|
|
274
|
+
echo ""
|
|
275
|
+
|
|
276
|
+
# --- Test 12 (#571 Gap 3): No ticket, no RTM, no gh CLI — all fallbacks empty ---
|
|
277
|
+
echo "--- Test 12: All fallbacks unreachable ---"
|
|
278
|
+
make_fixture "$WORK/test12"
|
|
279
|
+
source "$HELPER"
|
|
280
|
+
extract_release_metadata "REQ-999"
|
|
281
|
+
assert_empty "Title empty when no ticket, no RTM, no gh" "$RELEASE_TITLE"
|
|
282
|
+
assert_empty "Summary empty when no ticket" "$RELEASE_SUMMARY"
|
|
283
|
+
echo ""
|
|
284
|
+
|
|
285
|
+
# --- Test 13 (#571 Gap 3): Ticket exists but has no **Requirement:** line,
|
|
286
|
+
# no H1, and no ## Summary — all extraction targets are unreachable ---
|
|
287
|
+
echo "--- Test 13: Ticket with no extractable content ---"
|
|
288
|
+
make_fixture "$WORK/test13"
|
|
289
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-012.md" <<'TICKET'
|
|
290
|
+
Some prose without any standard headings.
|
|
291
|
+
|
|
292
|
+
Just a paragraph.
|
|
293
|
+
TICKET
|
|
294
|
+
|
|
295
|
+
source "$HELPER"
|
|
296
|
+
extract_release_metadata "REQ-012"
|
|
297
|
+
assert_empty "Title empty when no Requirement line or H1" "$RELEASE_TITLE"
|
|
298
|
+
assert_empty "Summary empty when no ## Summary section" "$RELEASE_SUMMARY"
|
|
299
|
+
echo ""
|
|
300
|
+
|
|
301
|
+
# --- Test 14 (#571 Gap 3): RTM row exists but has no issue number,
|
|
302
|
+
# so the gh CLI fallback is unreachable. Title should be empty. ---
|
|
303
|
+
echo "--- Test 14: RTM row without issue number ---"
|
|
304
|
+
make_fixture "$WORK/test14"
|
|
305
|
+
cat > compliance/RTM.md <<'RTM'
|
|
306
|
+
| REQ-ID | Issue | Risk | Evidence | Status |
|
|
307
|
+
| ------- | ----- | ---- | -------- | ------ |
|
|
308
|
+
| REQ-013 | | LOW | n/a | DRAFT |
|
|
309
|
+
RTM
|
|
310
|
+
source "$HELPER"
|
|
311
|
+
extract_release_metadata "REQ-013"
|
|
312
|
+
assert_empty "Title empty when RTM row has no issue number" "$RELEASE_TITLE"
|
|
313
|
+
echo ""
|
|
314
|
+
|
|
315
|
+
# --- Test 15 (#571 Gap 3): gh CLI exists but issue lookup fails —
|
|
316
|
+
# must fall through to H1 fallback, not error out ---
|
|
317
|
+
echo "--- Test 15: gh CLI fails, falls through to H1 ---"
|
|
318
|
+
make_fixture "$WORK/test15"
|
|
319
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-014.md" <<'TICKET'
|
|
320
|
+
# Fix critical payment bug
|
|
321
|
+
|
|
322
|
+
## Summary
|
|
323
|
+
Fixes the payment redirect issue.
|
|
324
|
+
TICKET
|
|
325
|
+
cat > compliance/RTM.md <<'RTM'
|
|
326
|
+
| REQ-ID | Issue | Risk | Evidence | Status |
|
|
327
|
+
| ------- | ----- | ---- | -------- | ------ |
|
|
328
|
+
| REQ-014 | #999 | LOW | n/a | DRAFT |
|
|
329
|
+
RTM
|
|
330
|
+
mkdir -p bin
|
|
331
|
+
cat > bin/gh <<'GH'
|
|
332
|
+
#!/usr/bin/env bash
|
|
333
|
+
# Simulate gh CLI failing (e.g. rate limited, issue not found)
|
|
334
|
+
exit 1
|
|
335
|
+
GH
|
|
336
|
+
chmod +x bin/gh
|
|
337
|
+
PATH="$PWD/bin:$PATH"
|
|
338
|
+
source "$HELPER"
|
|
339
|
+
extract_release_metadata "REQ-014"
|
|
340
|
+
assert_eq "H1 fallback when gh CLI fails" "Fix critical payment bug" "$RELEASE_TITLE"
|
|
341
|
+
echo ""
|
|
342
|
+
|
|
343
|
+
# --- Test 16 (#571 Gap 3): Summary section exists but is only whitespace ---
|
|
344
|
+
echo "--- Test 16: Whitespace-only summary is cleared ---"
|
|
345
|
+
make_fixture "$WORK/test16"
|
|
346
|
+
cat > "compliance/pending-releases/RELEASE-TICKET-REQ-015.md" <<'TICKET'
|
|
347
|
+
**Requirement:** REQ-015 — Feature fifteen
|
|
348
|
+
|
|
349
|
+
## Summary
|
|
350
|
+
|
|
351
|
+
## Changes
|
|
352
|
+
- Change A
|
|
353
|
+
TICKET
|
|
354
|
+
|
|
355
|
+
source "$HELPER"
|
|
356
|
+
extract_release_metadata "REQ-015"
|
|
357
|
+
assert_eq "Title extracted" "Feature fifteen" "$RELEASE_TITLE"
|
|
358
|
+
assert_empty "Whitespace-only summary cleared" "$RELEASE_SUMMARY"
|
|
359
|
+
echo ""
|
|
360
|
+
|
|
361
|
+
echo ""
|
|
362
|
+
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
363
|
+
exit $FAIL
|