test(smoke): decouple admin checks from bootstrap credentials (#686)

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-08-04 19:20:34 +08:00 committed by GitHub
parent 51ff9b99d2
commit fc457a0651
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 220 additions and 9 deletions

View file

@ -38,5 +38,6 @@ jobs:
- run: bash scripts/tests/runtime-secret-test.sh
- run: bash scripts/tests/validate-release-config-test.sh
- run: bash scripts/tests/nginx-forwarded-proto-test.sh
- run: bash scripts/tests/smoke-test-admin-mode-test.sh
- run: bash scripts/tests/dev-web-host-test.sh
- run: bash scripts/tests/workflow-security-test.sh

View file

@ -313,7 +313,7 @@ staging: ## 构建并启动 staging 环境,运行 smoke test混合模式
@echo "=== [4/5] Starting staging services ==="
$(STAGING_COMPOSE) up -d --wait server web
@echo "=== [5/5] Running smoke tests ==="
@if BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD='Admin@staging2026' \
@if SMOKE_ADMIN_USERNAME=admin SMOKE_ADMIN_PASSWORD='Admin@staging2026' \
bash scripts/smoke-test.sh $(STAGING_API_URL); then \
echo ""; \
echo "Staging passed. Environment is running:"; \

View file

@ -400,6 +400,18 @@ Run it against a local backend:
./scripts/smoke-test.sh http://localhost:8080
```
Admin label-management smoke checks run only when current admin credentials are
supplied explicitly:
```bash
SMOKE_ADMIN_USERNAME=admin SMOKE_ADMIN_PASSWORD='current-password' \
./scripts/smoke-test.sh http://localhost:8080
```
Use `SMOKE_ADMIN_CHECKS=false` for persistent environments where only non-admin
smoke checks should run. The script no longer falls back to bootstrap admin
password defaults.
## Architecture
```

View file

@ -193,6 +193,16 @@ make generate-api # 重新生成 OpenAPI 类型
./scripts/smoke-test.sh http://localhost:8080 # 运行冒烟测试
```
管理员标签管理冒烟测试只会在显式提供当前管理员凭证时运行:
```bash
SMOKE_ADMIN_USERNAME=admin SMOKE_ADMIN_PASSWORD='current-password' \
./scripts/smoke-test.sh http://localhost:8080
```
持久化环境只跑非管理员冒烟检查时,可设置 `SMOKE_ADMIN_CHECKS=false`
脚本不再回退使用 bootstrap 管理员默认密码。
说明:不要在 `server/` 下直接执行 `./mvnw -pl skillhub-app clean test``skillhub-app` 依赖同仓库的 sibling modules单独 clean 构建时会回退到本地 Maven 仓库里的旧产物并出现大量 `cannot find symbol` / 签名不匹配错误。需要使用 `-am`,或者直接使用上面的 `make test-backend-app` / `make build-backend-app`
### 项目结构

View file

@ -129,6 +129,12 @@ This will:
4. Run smoke tests against the API
5. Print pass/fail summary
`scripts/smoke-test.sh` separates bootstrap creation from smoke credentials.
Admin smoke checks run only when `SMOKE_ADMIN_USERNAME` and
`SMOKE_ADMIN_PASSWORD` are provided. Use `SMOKE_ADMIN_CHECKS=false` when testing
a persistent environment where the current admin password is not part of the
smoke run.
If all tests pass, the environment stays running at:
- Web UI: http://localhost
- Backend API: http://localhost:8080

View file

@ -31,6 +31,12 @@ check() {
fi
}
finish() {
echo
echo "Results: $PASS passed, $FAIL failed"
[[ "$FAIL" -eq 0 ]]
}
echo "=== SkillHub Smoke Test ==="
echo "Target: $BASE_URL"
echo
@ -113,8 +119,30 @@ else
fi
# ---- Label Management (requires admin) ----
ADMIN_USERNAME="${BOOTSTRAP_ADMIN_USERNAME:-admin}"
ADMIN_PASSWORD="${BOOTSTRAP_ADMIN_PASSWORD:-ChangeMe!2026}"
SMOKE_ADMIN_CHECKS="${SMOKE_ADMIN_CHECKS:-auto}"
SMOKE_ADMIN_USERNAME="${SMOKE_ADMIN_USERNAME:-}"
SMOKE_ADMIN_PASSWORD="${SMOKE_ADMIN_PASSWORD:-}"
ADMIN_CONFIG_FAILED=0
if [[ "$SMOKE_ADMIN_CHECKS" != "auto" && "$SMOKE_ADMIN_CHECKS" != "true" && "$SMOKE_ADMIN_CHECKS" != "false" ]]; then
echo "FAIL: SMOKE_ADMIN_CHECKS must be auto, true, or false"
FAIL=$((FAIL + 1))
ADMIN_CONFIG_FAILED=1
fi
if [[ "$SMOKE_ADMIN_CHECKS" == "true" && ( -z "$SMOKE_ADMIN_USERNAME" || -z "$SMOKE_ADMIN_PASSWORD" ) ]]; then
echo "FAIL: SMOKE_ADMIN_CHECKS=true requires SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD"
FAIL=$((FAIL + 1))
ADMIN_CONFIG_FAILED=1
fi
if [[ "$ADMIN_CONFIG_FAILED" -ne 0 ]]; then
finish
exit $?
fi
if [[ "$SMOKE_ADMIN_CHECKS" == "false" || ( "$SMOKE_ADMIN_CHECKS" == "auto" && ( -z "$SMOKE_ADMIN_USERNAME" || -z "$SMOKE_ADMIN_PASSWORD" ) ) ]]; then
echo "SKIP: Admin label management (set SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD to enable)"
finish
exit $?
fi
ADMIN_COOKIE_JAR="$(mktemp)"
LABEL_SLUG="smoke-label-$(date +%s)"
@ -134,7 +162,7 @@ ADMIN_LOGIN_STATUS="$(curl --max-time 10 -s -o /dev/null -w "%{http_code}" \
-c "$ADMIN_COOKIE_JAR" \
-H "X-XSRF-TOKEN: $ADMIN_CSRF" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$ADMIN_USERNAME\",\"password\":\"$ADMIN_PASSWORD\"}" || true)"
-d "{\"username\":\"$SMOKE_ADMIN_USERNAME\",\"password\":\"$SMOKE_ADMIN_PASSWORD\"}" || true)"
if [[ "$ADMIN_LOGIN_STATUS" == "200" ]]; then
echo "PASS: Admin login (HTTP $ADMIN_LOGIN_STATUS)"
PASS=$((PASS + 1))
@ -196,8 +224,4 @@ else
FAIL=$((FAIL + 1))
fi
echo
echo "Results: $PASS passed, $FAIL failed"
if [[ "$FAIL" -ne 0 ]]; then
exit 1
fi
finish

View file

@ -0,0 +1,156 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SMOKE_SCRIPT="$REPO_ROOT/scripts/smoke-test.sh"
TMP_DIR="$(mktemp -d)"
cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
fail() {
echo "FAIL: $*" >&2
exit 1
}
mkdir -p "$TMP_DIR/bin"
cat >"$TMP_DIR/bin/curl" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
url=""
method="GET"
data=""
cookie_in=""
cookie_out=""
write_code=false
output_file=""
while (($#)); do
case "$1" in
-X)
method="$2"
shift 2
;;
-d)
data="$2"
shift 2
;;
-b)
cookie_in="$2"
shift 2
;;
-c)
cookie_out="$2"
shift 2
;;
-w)
write_code=true
shift 2
;;
-o)
output_file="$2"
shift 2
;;
-H|--max-time|--retry|--retry-delay)
shift 2
;;
-s|-sS)
shift
;;
http://*|https://*)
url="$1"
shift
;;
*)
shift
;;
esac
done
if [[ -n "$cookie_out" ]]; then
printf '%s\n' "localhost FALSE / FALSE 0 XSRF-TOKEN csrf-token" >>"$cookie_out"
fi
printf '%s\n' "$method $url $data" >>"${SMOKE_CURL_LOG:?SMOKE_CURL_LOG is required}"
status=200
case "$url" in
*/actuator/health) status=200 ;;
*/actuator/prometheus) status=401 ;;
*/api/v1/namespaces)
if [[ -n "$cookie_in" && -f "$cookie_in.session" ]]; then status=200; else status=401; fi
;;
*/api/v1/auth/me)
if [[ -n "$cookie_in" && -f "$cookie_in.session" && ! -f "$cookie_in.logged-out" ]]; then status=200; else status=401; fi
;;
*/api/v1/auth/local/register)
[[ -n "$cookie_out" ]] && touch "$cookie_out.session"
status=200
;;
*/api/v1/auth/local/change-password) status=200 ;;
*/api/v1/auth/logout)
[[ -n "$cookie_out" ]] && touch "$cookie_out.logged-out"
status=200
;;
*/api/v1/auth/local/login)
if [[ "$data" == *'"username":"current-admin"'* && "$data" == *'"password":"current-secret"'* ]]; then
[[ -n "$cookie_out" ]] && touch "$cookie_out.session"
status=200
else
status=401
fi
;;
*/api/v1/admin/labels|*/api/v1/labels|*/api/v1/admin/labels/*)
status=200
;;
esac
if [[ "$output_file" != "/dev/null" && -n "$output_file" ]]; then
printf '{}\n' >"$output_file"
fi
if [[ "$write_code" == true ]]; then
printf '%s' "$status"
fi
EOF
chmod +x "$TMP_DIR/bin/curl"
run_smoke() {
local name="$1"
shift
local log="$TMP_DIR/$name.curl.log"
local out="$TMP_DIR/$name.out"
local status=0
env PATH="$TMP_DIR/bin:$PATH" SMOKE_CURL_LOG="$log" "$@" "$SMOKE_SCRIPT" http://skillhub.test >"$out" 2>&1 || status=$?
printf '%s\n' "$status"
}
status="$(run_smoke skip-admin env)"
[[ "$status" == "0" ]] || fail "default smoke without admin credentials should pass"
grep -Fq "SKIP: Admin label management" "$TMP_DIR/skip-admin.out" \
|| fail "default smoke should skip admin section without explicit credentials"
if grep -Fq "/api/v1/auth/local/login" "$TMP_DIR/skip-admin.curl.log"; then
fail "default smoke must not attempt admin login without explicit credentials"
fi
status="$(run_smoke missing-admin env SMOKE_ADMIN_CHECKS=true)"
[[ "$status" != "0" ]] || fail "SMOKE_ADMIN_CHECKS=true without credentials should fail"
grep -Fq "SMOKE_ADMIN_CHECKS=true requires SMOKE_ADMIN_USERNAME and SMOKE_ADMIN_PASSWORD" "$TMP_DIR/missing-admin.out" \
|| fail "missing admin credentials should produce an actionable error"
if grep -Fq "/api/v1/auth/local/login" "$TMP_DIR/missing-admin.curl.log"; then
fail "missing explicit admin credentials must stop before admin login"
fi
status="$(run_smoke explicit-admin env SMOKE_ADMIN_USERNAME=current-admin SMOKE_ADMIN_PASSWORD=current-secret BOOTSTRAP_ADMIN_PASSWORD=wrong-bootstrap)"
[[ "$status" == "0" ]] || fail "explicit admin credentials should run full smoke successfully"
grep -Fq '"username":"current-admin","password":"current-secret"' "$TMP_DIR/explicit-admin.curl.log" \
|| fail "admin login should use SMOKE_ADMIN credentials"
if grep -Fq 'wrong-bootstrap' "$TMP_DIR/explicit-admin.curl.log"; then
fail "admin login must not use BOOTSTRAP_ADMIN_PASSWORD"
fi
if grep -Fq 'ChangeMe!2026' "$TMP_DIR/explicit-admin.curl.log"; then
fail "admin login must not fall back to the bootstrap default password"
fi
echo "smoke-test-admin-mode-test passed"

View file

@ -77,6 +77,8 @@ grep -Fq 'bash scripts/tests/validate-release-config-test.sh' "$PR_SCRIPTS_WORKF
|| fail "pr-scripts must run validate-release-config-test"
grep -Fq 'bash scripts/tests/nginx-forwarded-proto-test.sh' "$PR_SCRIPTS_WORKFLOW" \
|| fail "pr-scripts must run nginx-forwarded-proto-test"
grep -Fq 'bash scripts/tests/smoke-test-admin-mode-test.sh' "$PR_SCRIPTS_WORKFLOW" \
|| fail "pr-scripts must run smoke-test-admin-mode-test"
grep -Fq 'bash scripts/tests/runtime-secret-test.sh' "$PR_SCRIPTS_WORKFLOW" \
|| fail "pr-scripts must run runtime-secret-test"
grep -Fq 'bash scripts/tests/dev-web-host-test.sh' "$PR_SCRIPTS_WORKFLOW" \