bigpowers 2.12.0 → 2.12.1
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/.pi/package.json +1 -1
- package/CHANGELOG.md +7 -0
- package/SKILL-INDEX.md +1 -1
- package/package.json +1 -1
- package/scripts/run-smoke.sh +233 -0
package/.pi/package.json
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [2.12.1](https://github.com/danielvm-git/bigpowers/compare/v2.12.0...v2.12.1) (2026-06-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **skills:** add run-smoke.sh referenced by deploy, smoke-test ([5108891](https://github.com/danielvm-git/bigpowers/commit/51088912084979df38d6bb529297b03a34a6bb66))
|
|
7
|
+
|
|
1
8
|
# [2.12.0](https://github.com/danielvm-git/bigpowers/compare/v2.11.0...v2.12.0) (2026-06-20)
|
|
2
9
|
|
|
3
10
|
|
package/SKILL-INDEX.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **DO NOT EDIT** — This file is auto-generated by `scripts/generate-skill-index.sh`.
|
|
4
4
|
> Edit `SKILL.md` source files or `skills-lock.json` instead. Run `bash scripts/sync-skills.sh` to regenerate.
|
|
5
5
|
|
|
6
|
-
**Generated:** 2026-06-20T21:
|
|
6
|
+
**Generated:** 2026-06-20T21:59:15Z
|
|
7
7
|
**Skills:** 66
|
|
8
8
|
|
|
9
9
|
---
|
package/package.json
CHANGED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# run-smoke.sh — Post-deploy health-check runner for smoke-test skill
|
|
3
|
+
# Usage: bash scripts/run-smoke.sh [url] [smoke-checks-file]
|
|
4
|
+
#
|
|
5
|
+
# Reads from smoke-checks.yaml by default. Falls back to single-URL check.
|
|
6
|
+
# Env vars: DEPLOY_URL, SMOKE_CHECKS_FILE, SMOKE_TIMEOUT, SMOKE_RETRIES
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SMOKE_CHECKS_FILE="${2:-${SMOKE_CHECKS_FILE:-smoke-checks.yaml}}"
|
|
10
|
+
BASE_URL="${1:-${DEPLOY_URL:-}}"
|
|
11
|
+
SMOKE_TIMEOUT="${SMOKE_TIMEOUT:-30}"
|
|
12
|
+
SMOKE_RETRIES="${SMOKE_RETRIES:-0}"
|
|
13
|
+
|
|
14
|
+
TMPDIR=$(mktemp -d)
|
|
15
|
+
trap 'rm -rf "$TMPDIR"' EXIT
|
|
16
|
+
|
|
17
|
+
checks_passed=0
|
|
18
|
+
checks_failed=0
|
|
19
|
+
failures=""
|
|
20
|
+
|
|
21
|
+
# ── 1. Load checks ──────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
run_single_url_check() {
|
|
24
|
+
local url="$1"
|
|
25
|
+
local name="${2:-URL check}"
|
|
26
|
+
local expected_status="${3:-200}"
|
|
27
|
+
local content_signal="${4:-}"
|
|
28
|
+
|
|
29
|
+
echo "[$name]"
|
|
30
|
+
start_time=$(python3 -c 'import time; print(int(time.time() * 1000))')
|
|
31
|
+
response=$(curl -s -o "$TMPDIR/body.txt" -w "%{http_code}" --max-time "$SMOKE_TIMEOUT" "$url")
|
|
32
|
+
response_time=$(( $(python3 -c 'import time; print(int(time.time() * 1000))') - start_time ))
|
|
33
|
+
status="$response"
|
|
34
|
+
body=$(cat "$TMPDIR/body.txt" 2>/dev/null || echo "")
|
|
35
|
+
|
|
36
|
+
# Assert status
|
|
37
|
+
if [ "$status" -ne "$expected_status" ]; then
|
|
38
|
+
echo " FAIL: HTTP $status (expected $expected_status)"
|
|
39
|
+
checks_failed=$((checks_failed + 1))
|
|
40
|
+
failures="${failures} - $name: HTTP $status (expected $expected_status)\n"
|
|
41
|
+
else
|
|
42
|
+
echo " PASS: HTTP $status"
|
|
43
|
+
checks_passed=$((checks_passed + 1))
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Assert content signal
|
|
47
|
+
if [ -n "$content_signal" ]; then
|
|
48
|
+
if echo "$body" | grep -qiE "$content_signal"; then
|
|
49
|
+
echo " PASS: body matches \"$content_signal\""
|
|
50
|
+
else
|
|
51
|
+
echo " FAIL: body does not match \"$content_signal\""
|
|
52
|
+
checks_failed=$((checks_failed + 1))
|
|
53
|
+
failures="${failures} - $name: missing content signal \"$content_signal\"\n"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Assert response time
|
|
58
|
+
if [ "$response_time" -gt 0 ]; then
|
|
59
|
+
echo " Time: ${response_time}ms"
|
|
60
|
+
fi
|
|
61
|
+
echo ""
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
parse_and_run_checks() {
|
|
65
|
+
local file="$1"
|
|
66
|
+
local base_url=""
|
|
67
|
+
local in_checks=false
|
|
68
|
+
local check_name="" check_path="" check_method="" check_status="" check_signal="" check_time=""
|
|
69
|
+
|
|
70
|
+
while IFS= read -r line; do
|
|
71
|
+
# Strip inline comments
|
|
72
|
+
line="${line%%#*}"
|
|
73
|
+
# Trim whitespace
|
|
74
|
+
line="${line#"${line%%[![:space:]]*}"}"
|
|
75
|
+
line="${line%"${line##*[![:space:]]}"}"
|
|
76
|
+
[ -z "$line" ] && continue
|
|
77
|
+
|
|
78
|
+
if [[ "$line" =~ ^base_url: ]]; then
|
|
79
|
+
base_url="${line#base_url:}"
|
|
80
|
+
base_url="${base_url#"${base_url%%[![:space:]]*}"}"
|
|
81
|
+
base_url="${base_url%"${base_url##*[![:space:]]}"}"
|
|
82
|
+
base_url="${base_url%\"}"
|
|
83
|
+
base_url="${base_url#\"}"
|
|
84
|
+
base_url="${base_url%\'}"
|
|
85
|
+
base_url="${base_url#\'}"
|
|
86
|
+
continue
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [[ "$line" == "checks:" ]]; then
|
|
90
|
+
in_checks=true
|
|
91
|
+
check_name=""; check_path=""; check_method="GET"; check_status="200"
|
|
92
|
+
check_signal=""; check_time=""
|
|
93
|
+
continue
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if $in_checks; then
|
|
97
|
+
# Detect new check entry (dash at start of list item)
|
|
98
|
+
if [[ "$line" == "- name:"* ]]; then
|
|
99
|
+
# Run previous check if accumulated
|
|
100
|
+
if [ -n "$check_name" ] && [ -n "$base_url" ]; then
|
|
101
|
+
run_parsed_check "$base_url" "$check_name" "$check_path" "$check_status" "$check_signal"
|
|
102
|
+
fi
|
|
103
|
+
check_name="${line#- name:}"
|
|
104
|
+
check_name="${check_name#"${check_name%%[![:space:]]*}"}"
|
|
105
|
+
check_name="${check_name%\"}"; check_name="${check_name#\"}"
|
|
106
|
+
check_name="${check_name%\'}"; check_name="${check_name#\'}"
|
|
107
|
+
check_path=""; check_method="GET"; check_status="200"; check_signal=""; check_time=""
|
|
108
|
+
elif [[ "$line" == "name:"* ]]; then
|
|
109
|
+
check_name="${line#name:}"
|
|
110
|
+
check_name="${check_name#"${check_name%%[![:space:]]*}"}"
|
|
111
|
+
check_name="${check_name%\"}"; check_name="${check_name#\"}"
|
|
112
|
+
check_name="${check_name%\'}"; check_name="${check_name#\'}"
|
|
113
|
+
elif [[ "$line" == "path:"* ]]; then
|
|
114
|
+
check_path="${line#path:}"
|
|
115
|
+
check_path="${check_path#"${check_path%%[![:space:]]*}"}"
|
|
116
|
+
check_path="${check_path%\"}"; check_path="${check_path#\"}"
|
|
117
|
+
check_path="${check_path%\'}"; check_path="${check_path#\'}"
|
|
118
|
+
elif [[ "$line" == "method:"* ]]; then
|
|
119
|
+
check_method="${line#method:}"
|
|
120
|
+
check_method="${check_method#"${check_method%%[![:space:]]*}"}"
|
|
121
|
+
check_method="${check_method%\"}"; check_method="${check_method#\"}"
|
|
122
|
+
check_method="${check_method%\'}"; check_method="${check_method#\'}"
|
|
123
|
+
elif [[ "$line" == "expected_status:"* ]]; then
|
|
124
|
+
check_status="${line#expected_status:}"
|
|
125
|
+
check_status="${check_status#"${check_status%%[![:space:]]*}"}"
|
|
126
|
+
elif [[ "$line" == "content_signal:"* ]]; then
|
|
127
|
+
check_signal="${line#content_signal:}"
|
|
128
|
+
check_signal="${check_signal#"${check_signal%%[![:space:]]*}"}"
|
|
129
|
+
check_signal="${check_signal%\"}"; check_signal="${check_signal#\"}"
|
|
130
|
+
check_signal="${check_signal%\'}"; check_signal="${check_signal#\'}"
|
|
131
|
+
elif [[ "$line" == "max_response_time_ms:"* ]]; then
|
|
132
|
+
check_time="${line#max_response_time_ms:}"
|
|
133
|
+
check_time="${check_time#"${check_time%%[![:space:]]*}"}"
|
|
134
|
+
fi
|
|
135
|
+
fi
|
|
136
|
+
done < "$file"
|
|
137
|
+
|
|
138
|
+
# Run last check
|
|
139
|
+
if [ -n "$check_name" ] && [ -n "$base_url" ]; then
|
|
140
|
+
run_parsed_check "$base_url" "$check_name" "$check_path" "$check_status" "$check_signal"
|
|
141
|
+
fi
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
run_parsed_check() {
|
|
145
|
+
local base_url="$1" name="$2" path="$3" expected_status="$4" content_signal="$5"
|
|
146
|
+
local url="${base_url}${path}"
|
|
147
|
+
|
|
148
|
+
echo "[$name]"
|
|
149
|
+
echo " URL: $url"
|
|
150
|
+
start_time=$(python3 -c 'import time; print(int(time.time() * 1000))')
|
|
151
|
+
response=$(curl -s -o "$TMPDIR/body.txt" -w "%{http_code}" --max-time "$SMOKE_TIMEOUT" "$url" 2>/dev/null || echo "000")
|
|
152
|
+
response_time=$(( $(python3 -c 'import time; print(int(time.time() * 1000))') - start_time ))
|
|
153
|
+
status="$response"
|
|
154
|
+
body=$(cat "$TMPDIR/body.txt" 2>/dev/null || echo "")
|
|
155
|
+
|
|
156
|
+
# Assert status code
|
|
157
|
+
if [ "$status" -ne "$expected_status" ]; then
|
|
158
|
+
echo " FAIL: HTTP $status (expected $expected_status)"
|
|
159
|
+
checks_failed=$((checks_failed + 1))
|
|
160
|
+
failures="${failures} - $name: HTTP $status (expected $expected_status)\n"
|
|
161
|
+
else
|
|
162
|
+
echo " PASS: HTTP $status"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Assert content signal
|
|
166
|
+
if [ -n "$content_signal" ]; then
|
|
167
|
+
if echo "$body" | grep -qiE "$content_signal"; then
|
|
168
|
+
echo " PASS: body matches \"$content_signal\""
|
|
169
|
+
checks_passed=$((checks_passed + 1))
|
|
170
|
+
else
|
|
171
|
+
echo " FAIL: body does not match \"$content_signal\""
|
|
172
|
+
checks_failed=$((checks_failed + 1))
|
|
173
|
+
failures="${failures} - $name: missing content signal \"$content_signal\"\n"
|
|
174
|
+
fi
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Assert response time
|
|
178
|
+
if [ -n "${check_time:-}" ] && [ "$check_time" -gt 0 ] 2>/dev/null; then
|
|
179
|
+
if [ "$response_time" -gt "$check_time" ]; then
|
|
180
|
+
echo " FAIL: ${response_time}ms exceeds ${check_time}ms max"
|
|
181
|
+
checks_failed=$((checks_failed + 1))
|
|
182
|
+
failures="${failures} - $name: response time ${response_time}ms (max ${check_time}ms)\n"
|
|
183
|
+
else
|
|
184
|
+
echo " PASS: ${response_time}ms within ${check_time}ms limit"
|
|
185
|
+
fi
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
if [ "$response_time" -gt 0 ]; then
|
|
189
|
+
echo " Time: ${response_time}ms"
|
|
190
|
+
fi
|
|
191
|
+
echo ""
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
# ── Main dispatch ───────────────────────────────────────────────────────────
|
|
195
|
+
|
|
196
|
+
echo "=== Smoke Test Runner ==="
|
|
197
|
+
echo "Started at: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
|
198
|
+
echo ""
|
|
199
|
+
|
|
200
|
+
if [ -f "$SMOKE_CHECKS_FILE" ]; then
|
|
201
|
+
echo "Checks file: $SMOKE_CHECKS_FILE"
|
|
202
|
+
parse_and_run_checks "$SMOKE_CHECKS_FILE"
|
|
203
|
+
elif [ -n "$BASE_URL" ]; then
|
|
204
|
+
echo "Single URL mode: $BASE_URL"
|
|
205
|
+
run_single_url_check "$BASE_URL" "Baseline"
|
|
206
|
+
else
|
|
207
|
+
echo "ERROR: No smoke-checks.yaml found and no URL provided."
|
|
208
|
+
echo "Usage: bash scripts/run-smoke.sh [url] [smoke-checks-file]"
|
|
209
|
+
echo " DEPLOY_URL=http://example.com bash scripts/run-smoke.sh"
|
|
210
|
+
exit 2
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# ── Summary ──────────────────────────────────────────────────────────────────
|
|
214
|
+
|
|
215
|
+
total=$((checks_passed + checks_failed))
|
|
216
|
+
echo "=== Smoke Test Summary ==="
|
|
217
|
+
echo "Total: $total | Passed: $checks_passed | Failed: $checks_failed"
|
|
218
|
+
echo ""
|
|
219
|
+
|
|
220
|
+
if [ "$checks_failed" -gt 0 ]; then
|
|
221
|
+
echo "Failures:"
|
|
222
|
+
echo -e "$failures"
|
|
223
|
+
echo "Smoke test FAILED."
|
|
224
|
+
exit 1
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
if [ "$total" -eq 0 ]; then
|
|
228
|
+
echo "No checks were executed."
|
|
229
|
+
exit 1
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
echo "All checks passed."
|
|
233
|
+
exit 0
|