99 lines
3.4 KiB
Bash
99 lines
3.4 KiB
Bash
set -euo pipefail
|
|
|
|
repo_url="${REPO_URL:-http://gitadmin:12345678911@gitea:3000/gitadmin/signalscout-backend.git}"
|
|
source_dir="/opt/signalscout-source"
|
|
remote_dir="/opt/signalscout"
|
|
release_dir="/opt/signalscout.release"
|
|
public_ready_url="${PUBLIC_READY_URL:-}"
|
|
python_bin="${PYTHON_BIN:-python3.9}"
|
|
deploy_lock="/tmp/signalscout-backend-deploy.lock"
|
|
|
|
# 同一时间只允许一个部署任务替换源码、虚拟环境和运行目录,避免并发构建互相删除文件。
|
|
exec 9>"${deploy_lock}"
|
|
flock 9
|
|
|
|
# 服务器直接从 Gitea main 分支取代码,Jenkins和手动部署共享同一条发布路径。
|
|
if [ ! -d "${source_dir}/.git" ]; then
|
|
rm -rf "${source_dir}"
|
|
git clone --branch main "${repo_url}" "${source_dir}"
|
|
else
|
|
git -C "${source_dir}" remote set-url origin "${repo_url}"
|
|
git -C "${source_dir}" fetch origin main
|
|
git -C "${source_dir}" reset --hard origin/main
|
|
fi
|
|
|
|
if ! command -v "${python_bin}" >/dev/null 2>&1; then
|
|
echo "Python runtime is required but ${python_bin} was not found" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# 源码目录先安装开发依赖并跑测试,测试通过后才生成发布目录。
|
|
rm -rf "${source_dir}/.venv"
|
|
"${python_bin}" -m venv "${source_dir}/.venv"
|
|
"${source_dir}/.venv/bin/python" -m ensurepip --upgrade
|
|
"${source_dir}/.venv/bin/python" -m pip install -e "${source_dir}[dev]"
|
|
"${source_dir}/.venv/bin/python" -B -m ruff check "${source_dir}"
|
|
"${source_dir}/.venv/bin/python" -B -m pytest "${source_dir}"
|
|
|
|
# 发布目录重新生成,避免把源码仓库、测试缓存或旧虚拟环境带入 systemd 运行目录。
|
|
rm -rf "${release_dir}"
|
|
mkdir -p "${release_dir}"
|
|
tar \
|
|
--exclude=.git \
|
|
--exclude=.venv \
|
|
--exclude=.pytest_cache \
|
|
--exclude=.ruff_cache \
|
|
--exclude=__pycache__ \
|
|
--exclude=*.pyc \
|
|
--exclude=.env \
|
|
--exclude=reports \
|
|
--exclude=logs \
|
|
-C "${source_dir}" \
|
|
-cf - . | tar -C "${release_dir}" -xf -
|
|
|
|
# 服务配置以服务器当前 .env 为准;缺失时直接失败,避免 systemd 启动后才暴露为502。
|
|
if [ ! -f "${remote_dir}/.env" ]; then
|
|
echo "signalscout backend .env is missing at ${remote_dir}/.env" >&2
|
|
exit 1
|
|
fi
|
|
cp "${remote_dir}/.env" "${release_dir}/.env"
|
|
|
|
"${python_bin}" -m venv "${release_dir}/.venv"
|
|
"${release_dir}/.venv/bin/python" -m ensurepip --upgrade
|
|
"${release_dir}/.venv/bin/python" -m pip install -e "${release_dir}"
|
|
(
|
|
cd "${release_dir}"
|
|
"${release_dir}/.venv/bin/python" -B -m alembic upgrade head
|
|
"${release_dir}/.venv/bin/python" -B scripts/seed_topics.py
|
|
)
|
|
|
|
rm -rf "${remote_dir}"
|
|
mv "${release_dir}" "${remote_dir}"
|
|
mkdir -p "${remote_dir}/logs" "${remote_dir}/reports"
|
|
|
|
cp "${remote_dir}/deployment/systemd/signalscout.service" /etc/systemd/system/signalscout.service
|
|
systemctl daemon-reload
|
|
systemctl restart signalscout
|
|
if ! systemctl is-active --quiet signalscout; then
|
|
systemctl status signalscout --no-pager -l >&2 || true
|
|
journalctl -u signalscout -n 120 --no-pager >&2 || true
|
|
exit 1
|
|
fi
|
|
|
|
# systemd启动成功后继续等待HTTP健康检查,确保API真实开始监听。
|
|
for attempt in $(seq 1 20); do
|
|
if curl -fsS "http://127.0.0.1:8020/health" >/dev/null; then
|
|
if [ -n "${public_ready_url}" ]; then
|
|
curl -fsS "${public_ready_url}" >/dev/null
|
|
fi
|
|
echo "signalscout backend deploy ok"
|
|
exit 0
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
echo "signalscout backend health check failed" >&2
|
|
systemctl status signalscout --no-pager -l >&2 || true
|
|
journalctl -u signalscout -n 120 --no-pager >&2 || true
|
|
exit 1
|