mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 07:24:55 +08:00
bat-rust / Build and test Rust (push) Successful in 3m47s
daemon 子进程现会透传下载并发配置,下载进度按已完成数量单调上报。MediaCatalog 改为使用官方相对路径生成全局媒体 URL,覆盖 GameData、Prologue 等目录并补齐 jpg 资源,避免叶子文件名误拼媒体根目录导致 403。同步更新测试、smoke 断言和运行文档。
185 lines
5.8 KiB
Bash
Executable File
185 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
cd "${REPO_ROOT}"
|
|
|
|
timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
|
|
SMOKE_ROOT="${BAT_SMOKE_ROOT:-/tmp/bat-official-smoke-${timestamp}}"
|
|
OUTPUT_DIR="${BAT_SMOKE_OUTPUT:-${SMOKE_ROOT}/resources}"
|
|
STATE_DIR="${BAT_SMOKE_STATE_DIR:-${SMOKE_ROOT}/state}"
|
|
REPORT_DIR="${BAT_SMOKE_REPORT_DIR:-${SMOKE_ROOT}/report}"
|
|
BAT_BIN="${BAT_BIN:-${REPO_ROOT}/target/release/bat}"
|
|
|
|
fail() {
|
|
printf 'error: %s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
real_output="$(realpath -m "${OUTPUT_DIR}")"
|
|
case "${real_output}" in
|
|
/tmp/*) ;;
|
|
*)
|
|
if [[ "${BAT_SMOKE_ALLOW_NON_TMP:-}" != "1" ]]; then
|
|
fail "BAT_SMOKE_OUTPUT must be under /tmp by default; set BAT_SMOKE_ALLOW_NON_TMP=1 only for an isolated test path"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
if [[ -e "${OUTPUT_DIR}" ]] && [[ -n "$(find "${OUTPUT_DIR}" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)" ]]; then
|
|
fail "output directory is not empty: ${OUTPUT_DIR}"
|
|
fi
|
|
|
|
mkdir -p "${OUTPUT_DIR}" "${STATE_DIR}" "${REPORT_DIR}"
|
|
|
|
if [[ "${BAT_SMOKE_SKIP_BUILD:-}" != "1" ]]; then
|
|
cargo build --release -p bat-infrastructure --bin bat
|
|
fi
|
|
|
|
[[ -x "${BAT_BIN}" ]] || fail "bat binary is not executable: ${BAT_BIN}"
|
|
|
|
write_command_file() {
|
|
local name="$1"
|
|
shift
|
|
local command_file="${REPORT_DIR}/${name}.command.txt"
|
|
: >"${command_file}"
|
|
printf '$' >>"${command_file}"
|
|
printf ' %q' "$@" >>"${command_file}"
|
|
printf '\n' >>"${command_file}"
|
|
}
|
|
|
|
run_step() {
|
|
local name="$1"
|
|
shift
|
|
printf '==> %s\n' "${name}"
|
|
write_command_file "${name}" "$@"
|
|
"$@" >"${REPORT_DIR}/${name}.stdout.json" 2>"${REPORT_DIR}/${name}.stderr.log"
|
|
}
|
|
|
|
require_contains() {
|
|
local path="$1"
|
|
local needle="$2"
|
|
local description="$3"
|
|
if ! grep -Fq "${needle}" "${path}"; then
|
|
fail "${description}; expected '${needle}' in ${path}"
|
|
fi
|
|
}
|
|
|
|
run_step "01-dry-run-plan" \
|
|
"${BAT_BIN}" \
|
|
--auto-discover \
|
|
--output "${OUTPUT_DIR}" \
|
|
--state-dir "${STATE_DIR}" \
|
|
--dry-run \
|
|
--plan \
|
|
--json \
|
|
--no-progress
|
|
|
|
run_step "02-first-full-pull" \
|
|
"${BAT_BIN}" \
|
|
--auto-discover \
|
|
--output "${OUTPUT_DIR}" \
|
|
--state-dir "${STATE_DIR}" \
|
|
--json \
|
|
--progress \
|
|
--no-banner
|
|
|
|
require_contains "${REPORT_DIR}/02-first-full-pull.stderr.log" "下载进度:已完成" "first pull did not emit completed download progress"
|
|
require_contains "${REPORT_DIR}/02-first-full-pull.stderr.log" "单文件" "first pull did not emit single-file download progress"
|
|
require_contains "${REPORT_DIR}/02-first-full-pull.stderr.log" "校验结果:" "first pull did not emit verification summary"
|
|
|
|
run_step "03-second-up-to-date" \
|
|
"${BAT_BIN}" \
|
|
--auto-discover \
|
|
--output "${OUTPUT_DIR}" \
|
|
--state-dir "${STATE_DIR}" \
|
|
--json \
|
|
--no-progress
|
|
|
|
require_contains "${REPORT_DIR}/03-second-up-to-date.stdout.json" '"update_status": "up_to_date"' "second run did not report up_to_date"
|
|
|
|
current_link="${OUTPUT_DIR}/current"
|
|
[[ -e "${current_link}" ]] || fail "current release symlink/path was not created: ${current_link}"
|
|
current_dir="$(realpath "${current_link}")"
|
|
|
|
damage_file="$(find "${current_dir}" -type f \
|
|
! -name 'official-sync-snapshot.json' \
|
|
! -name 'official-download-manifest.json' \
|
|
-print -quit)"
|
|
[[ -n "${damage_file}" ]] || fail "no resource file found to damage under ${current_dir}"
|
|
|
|
printf '%s\n' "${damage_file}" >"${REPORT_DIR}/damaged-file.txt"
|
|
{
|
|
printf 'path: %s\n' "${damage_file}"
|
|
printf 'bytes: %s\n' "$(wc -c <"${damage_file}" | tr -d ' ')"
|
|
printf 'sha256: %s\n' "$(sha256sum "${damage_file}" | awk '{print $1}')"
|
|
} >"${REPORT_DIR}/damaged-file.before.txt"
|
|
printf 'BAT official smoke intentional corruption\n' >"${damage_file}"
|
|
|
|
run_step "04-repair-after-damage" \
|
|
"${BAT_BIN}" \
|
|
repair \
|
|
--auto-discover \
|
|
--output "${OUTPUT_DIR}" \
|
|
--state-dir "${STATE_DIR}" \
|
|
--json \
|
|
--progress \
|
|
--no-banner
|
|
|
|
require_contains "${REPORT_DIR}/04-repair-after-damage.stdout.json" '"command": "repair"' "repair command report missing"
|
|
require_contains "${REPORT_DIR}/04-repair-after-damage.stdout.json" '"status": "completed"' "repair command did not complete"
|
|
require_contains "${REPORT_DIR}/04-repair-after-damage.stderr.log" "下载进度:已完成" "repair did not emit completed download progress"
|
|
require_contains "${REPORT_DIR}/04-repair-after-damage.stderr.log" "单文件" "repair did not emit single-file download progress"
|
|
require_contains "${REPORT_DIR}/04-repair-after-damage.stderr.log" "校验结果:" "repair did not emit verification summary"
|
|
|
|
run_step "05-verify-after-repair" \
|
|
"${BAT_BIN}" \
|
|
verify \
|
|
--auto-discover \
|
|
--output "${OUTPUT_DIR}" \
|
|
--state-dir "${STATE_DIR}" \
|
|
--json \
|
|
--no-progress
|
|
|
|
require_contains "${REPORT_DIR}/05-verify-after-repair.stdout.json" '"healthy": true' "verify after repair did not report healthy=true"
|
|
|
|
file_count="$(find "${current_dir}" -type f | wc -l | tr -d ' ')"
|
|
current_size="$(du -sh "${current_dir}" | awk '{print $1}')"
|
|
report_file="${REPORT_DIR}/SMOKE_REPORT.md"
|
|
|
|
cat >"${report_file}" <<EOF
|
|
# Official Full Pull Smoke Report
|
|
|
|
- generated_at_utc: ${timestamp}
|
|
- repo: ${REPO_ROOT}
|
|
- bat: ${BAT_BIN}
|
|
- output: ${OUTPUT_DIR}
|
|
- state_dir: ${STATE_DIR}
|
|
- current_release: ${current_dir}
|
|
- current_release_size: ${current_size}
|
|
- current_release_file_count: ${file_count}
|
|
- damaged_file: ${damage_file}
|
|
|
|
## Steps
|
|
|
|
1. dry-run with full URL plan: 01-dry-run-plan
|
|
2. first full pull: 02-first-full-pull
|
|
3. second up-to-date check: 03-second-up-to-date
|
|
4. intentional local file damage and repair: 04-repair-after-damage
|
|
5. verify after repair: 05-verify-after-repair
|
|
|
|
Each step has:
|
|
|
|
- <step>.command.txt
|
|
- <step>.stdout.json
|
|
- <step>.stderr.log
|
|
|
|
The large resource output is intentionally outside Git and remains under:
|
|
|
|
\`${OUTPUT_DIR}\`
|
|
EOF
|
|
|
|
printf '\nSmoke report: %s\n' "${report_file}"
|
|
printf 'Resource output: %s\n' "${OUTPUT_DIR}"
|