Update release notes and deploy workspace
This commit is contained in:
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
MAX_LINES="${MAX_LINES:-500}"
|
||||
|
||||
find Backend frontend/src \
|
||||
-type f \( -name '*.cs' -o -name '*.ts' -o -name '*.vue' \) \
|
||||
-not -path '*/bin/*' \
|
||||
-not -path '*/obj/*' \
|
||||
-not -path 'Backend/Migrations/*' \
|
||||
-print0 \
|
||||
| xargs -0 wc -l \
|
||||
| awk -v max="$MAX_LINES" '
|
||||
$2 != "total" && $1 > max { printf "%6d %s\n", $1, $2; found = 1 }
|
||||
END { exit found ? 1 : 0 }
|
||||
'
|
||||
Executable
+117
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
API_BASE="${API_BASE:-http://127.0.0.1:5084}"
|
||||
ADMIN_SESSION_TOKEN="${ADMIN_SESSION_TOKEN:-}"
|
||||
|
||||
fail() {
|
||||
printf 'smoke failed: %s\n' "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "missing required command: $1"
|
||||
}
|
||||
|
||||
http_json() {
|
||||
local url="$1"
|
||||
shift || true
|
||||
curl -fsS "$@" "$url"
|
||||
}
|
||||
|
||||
json_value() {
|
||||
local expression="$1"
|
||||
node -e "
|
||||
let data = '';
|
||||
process.stdin.on('data', chunk => data += chunk);
|
||||
process.stdin.on('end', () => {
|
||||
const root = JSON.parse(data);
|
||||
const value = (${expression})(root);
|
||||
if (typeof value === 'object') {
|
||||
console.log(JSON.stringify(value));
|
||||
} else {
|
||||
console.log(value ?? '');
|
||||
}
|
||||
});
|
||||
"
|
||||
}
|
||||
|
||||
require_command curl
|
||||
require_command node
|
||||
|
||||
printf '== VTuber Awards local smoke ==\n'
|
||||
printf 'API: %s\n' "$API_BASE"
|
||||
|
||||
printf '\n[1/6] health\n'
|
||||
http_json "$API_BASE/api/health" >/tmp/vtsa-smoke-health.json
|
||||
cat /tmp/vtsa-smoke-health.json
|
||||
printf '\n'
|
||||
|
||||
printf '\n[2/6] database health\n'
|
||||
http_json "$API_BASE/api/health/database" >/tmp/vtsa-smoke-db.json
|
||||
cat /tmp/vtsa-smoke-db.json
|
||||
printf '\n'
|
||||
can_connect="$(json_value 'root => root.canConnect' </tmp/vtsa-smoke-db.json)"
|
||||
if [[ "$can_connect" != "true" ]]; then
|
||||
fail "database cannot connect"
|
||||
fi
|
||||
|
||||
printf '\n[3/6] public overview\n'
|
||||
http_json "$API_BASE/api/public/overview" >/tmp/vtsa-smoke-overview.json
|
||||
year="$(json_value 'root => root.year' </tmp/vtsa-smoke-overview.json)"
|
||||
season_id="$(json_value 'root => root.seasonId' </tmp/vtsa-smoke-overview.json)"
|
||||
printf 'current season: year=%s seasonId=%s\n' "$year" "$season_id"
|
||||
if [[ -z "$year" || -z "$season_id" ]]; then
|
||||
fail "public overview did not expose current season"
|
||||
fi
|
||||
|
||||
printf '\n[4/6] public category structure\n'
|
||||
http_json "$API_BASE/api/public/seasons/$year/categories" >/tmp/vtsa-smoke-categories.json
|
||||
category_count="$(json_value 'root => root.categories?.length ?? 0' </tmp/vtsa-smoke-categories.json)"
|
||||
legacy_count="$(json_value 'root => (root.categories ?? []).filter(c => ["Main Awards", "Discovery", "Gaming", "Creative", "Performance", "Entertainment", "Community", "Collab"].includes(c.groupName)).length' </tmp/vtsa-smoke-categories.json)"
|
||||
main_group_count="$(json_value 'root => new Set((root.categories ?? []).map(c => c.groupName)).size' </tmp/vtsa-smoke-categories.json)"
|
||||
printf 'categories=%s mainGroups=%s legacyParents=%s\n' "$category_count" "$main_group_count" "$legacy_count"
|
||||
if [[ "$category_count" == "0" ]]; then
|
||||
fail "public categories are empty"
|
||||
fi
|
||||
if [[ "$legacy_count" != "0" ]]; then
|
||||
fail "legacy parent labels are still exposed publicly"
|
||||
fi
|
||||
|
||||
printf '\n[5/6] admin endpoints (optional)\n'
|
||||
if [[ -z "$ADMIN_SESSION_TOKEN" ]]; then
|
||||
printf 'skipped: set ADMIN_SESSION_TOKEN to check admin season/team endpoints\n'
|
||||
else
|
||||
auth_header=( -H "Authorization: Bearer $ADMIN_SESSION_TOKEN" )
|
||||
http_json "$API_BASE/api/admin/seasons" "${auth_header[@]}" >/tmp/vtsa-smoke-admin-seasons.json
|
||||
admin_season_count="$(json_value 'root => Array.isArray(root) ? root.length : (root.seasons?.length ?? 0)' </tmp/vtsa-smoke-admin-seasons.json)"
|
||||
printf 'admin seasons=%s\n' "$admin_season_count"
|
||||
if [[ "$admin_season_count" == "0" ]]; then
|
||||
fail "admin seasons endpoint returned no seasons"
|
||||
fi
|
||||
|
||||
http_json "$API_BASE/api/admin/seasons/$season_id" "${auth_header[@]}" >/tmp/vtsa-smoke-admin-detail.json
|
||||
voting_groups="$(json_value 'root => root.votingWorkspace?.categories?.length ?? 0' </tmp/vtsa-smoke-admin-detail.json)"
|
||||
subcategory_templates="$(json_value 'root => root.subcategoryTemplates?.length ?? 0' </tmp/vtsa-smoke-admin-detail.json)"
|
||||
printf 'admin detail: votingCategories=%s subcategoryTemplates=%s\n' "$voting_groups" "$subcategory_templates"
|
||||
if [[ "$voting_groups" == "0" || "$subcategory_templates" == "0" ]]; then
|
||||
fail "admin detail is missing voting workspace or subcategory templates"
|
||||
fi
|
||||
|
||||
http_json "$API_BASE/api/admin/team" "${auth_header[@]}" >/tmp/vtsa-smoke-admin-team.json
|
||||
permissions="$(json_value 'root => (root.permissions ?? []).map(p => p.key).sort().join(",")' </tmp/vtsa-smoke-admin-team.json)"
|
||||
printf 'permission keys=%s\n' "$permissions"
|
||||
node -e '
|
||||
const fs = require("fs");
|
||||
const root = JSON.parse(fs.readFileSync("/tmp/vtsa-smoke-admin-team.json", "utf8"));
|
||||
const keys = new Set((root.permissions ?? []).map(item => item.key));
|
||||
const required = ["dashboard","years","nominations","categories","candidates","clips","content","risk","audit","analytics","voting","winners","settings","team"];
|
||||
const missing = required.filter(key => !keys.has(key));
|
||||
if (missing.length) {
|
||||
console.error(`missing permission keys: ${missing.join(", ")}`);
|
||||
process.exit(1);
|
||||
}
|
||||
'
|
||||
fi
|
||||
|
||||
printf '\n[6/6] smoke complete\n'
|
||||
Reference in New Issue
Block a user