chore: add automated staging smoke helper
This commit is contained in:
@@ -130,3 +130,9 @@ npm run e2e
|
||||
```bash
|
||||
just ui-e2e
|
||||
```
|
||||
|
||||
Для post-deploy smoke:
|
||||
|
||||
```bash
|
||||
just staging-smoke https://<domain>
|
||||
```
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
|
||||
## Current
|
||||
|
||||
### `feat/staging-regression-notes`
|
||||
### `feat/next-live-staging-pass`
|
||||
|
||||
Status: completed
|
||||
|
||||
DoD:
|
||||
- staging regression log template exists
|
||||
- deploy smoke runbook links to the regression log
|
||||
- README references the regression log as the canonical post-deploy notes location
|
||||
- automated staging smoke helper exists
|
||||
- helper validates core public routes, auth session JSON and legacy redirects
|
||||
- deploy smoke runbook and README reference the helper
|
||||
|
||||
## Next
|
||||
|
||||
- `feat/next-live-staging-pass`
|
||||
- `feat/live-staging-run`
|
||||
|
||||
## Backlog
|
||||
|
||||
|
||||
@@ -33,6 +33,29 @@
|
||||
- включенный `CRANK_DEMO_SEED=true`, если нужен предзаполненный smoke state;
|
||||
- bootstrap admin credentials для входа в UI.
|
||||
|
||||
## 3.1. Быстрый automated smoke
|
||||
|
||||
Есть helper script:
|
||||
|
||||
```bash
|
||||
just staging-smoke https://<domain>
|
||||
```
|
||||
|
||||
или напрямую:
|
||||
|
||||
```bash
|
||||
bash scripts/staging-smoke.sh https://<domain>
|
||||
```
|
||||
|
||||
Он проверяет:
|
||||
|
||||
- public routes;
|
||||
- `/api/auth/session` JSON contract;
|
||||
- `/mcp/health`;
|
||||
- legacy `/html/...` redirects.
|
||||
|
||||
Это не заменяет ручной smoke pass ниже, а только быстро отсеивает грубые deploy/routing поломки.
|
||||
|
||||
## 4. Server-side smoke
|
||||
|
||||
На сервере:
|
||||
|
||||
@@ -26,3 +26,6 @@ verify-ui:
|
||||
|
||||
ui-e2e:
|
||||
cd apps/ui && npm run e2e
|
||||
|
||||
staging-smoke base_url:
|
||||
bash scripts/staging-smoke.sh {{base_url}}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Scripts
|
||||
|
||||
## staging-smoke.sh
|
||||
|
||||
Post-deploy smoke helper for staging/production-like environments.
|
||||
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
./scripts/staging-smoke.sh https://rmcp.itexp.me
|
||||
```
|
||||
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: $0 <base-url>" >&2
|
||||
echo "example: $0 https://rmcp.itexp.me" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BASE_URL="${1%/}"
|
||||
TIMEOUT_SECONDS="${SMOKE_TIMEOUT_SECONDS:-20}"
|
||||
|
||||
check_head() {
|
||||
local path="$1"
|
||||
local expected_prefix="${2:-2}"
|
||||
local url="${BASE_URL}${path}"
|
||||
local code
|
||||
|
||||
code="$(curl -k -sS -o /dev/null -I -L --max-time "${TIMEOUT_SECONDS}" -w '%{http_code}' "${url}")"
|
||||
printf '%-36s %s\n' "${path}" "${code}"
|
||||
|
||||
if [[ "${code}" != ${expected_prefix}* ]]; then
|
||||
echo "unexpected status for ${url}: ${code}" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_json() {
|
||||
local path="$1"
|
||||
local expected_status_one="$2"
|
||||
local expected_status_two="${3:-}"
|
||||
local url="${BASE_URL}${path}"
|
||||
local headers
|
||||
local code
|
||||
local content_type
|
||||
|
||||
headers="$(mktemp)"
|
||||
code="$(curl -k -sS -o /dev/null -D "${headers}" --max-time "${TIMEOUT_SECONDS}" -w '%{http_code}' "${url}")"
|
||||
content_type="$(awk 'BEGIN{IGNORECASE=1} /^content-type:/ {print $2}' "${headers}" | tr -d '\r' | tail -n1)"
|
||||
rm -f "${headers}"
|
||||
|
||||
printf '%-36s %s (%s)\n' "${path}" "${code}" "${content_type:-unknown}"
|
||||
|
||||
if [[ "${code}" != "${expected_status_one}" && ( -z "${expected_status_two}" || "${code}" != "${expected_status_two}" ) ]]; then
|
||||
echo "unexpected status for ${url}: ${code}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "${content_type}" != application/json* ]]; then
|
||||
echo "unexpected content-type for ${url}: ${content_type:-missing}" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_redirect() {
|
||||
local path="$1"
|
||||
local expected_location_suffix="$2"
|
||||
local url="${BASE_URL}${path}"
|
||||
local headers
|
||||
local code
|
||||
local location
|
||||
|
||||
headers="$(mktemp)"
|
||||
code="$(curl -k -sS -o /dev/null -D "${headers}" --max-time "${TIMEOUT_SECONDS}" -w '%{http_code}' "${url}")"
|
||||
location="$(awk 'BEGIN{IGNORECASE=1} /^location:/ {print $2}' "${headers}" | tr -d '\r' | tail -n1)"
|
||||
rm -f "${headers}"
|
||||
|
||||
printf '%-36s %s -> %s\n' "${path}" "${code}" "${location:-missing}"
|
||||
|
||||
if [[ "${code}" != 30* ]]; then
|
||||
echo "expected redirect for ${url}, got ${code}" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ "${location}" != *"${expected_location_suffix}" ]]; then
|
||||
echo "unexpected redirect location for ${url}: ${location:-missing}" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "staging smoke: ${BASE_URL}"
|
||||
echo
|
||||
echo "public routes"
|
||||
check_head "/" 2
|
||||
check_head "/login" 2
|
||||
check_head "/agents" 2
|
||||
check_head "/secrets" 2
|
||||
check_head "/wizard/" 2
|
||||
check_head "/mcp/health" 2
|
||||
check_json "/api/auth/session" 200 401
|
||||
|
||||
echo
|
||||
echo "legacy redirects"
|
||||
check_redirect "/html/login.html" "/login"
|
||||
check_redirect "/html/agents.html" "/agents"
|
||||
check_redirect "/html/wizard/" "/wizard/"
|
||||
|
||||
echo
|
||||
echo "smoke completed"
|
||||
Reference in New Issue
Block a user