重写为 AI 情报 Agent 并接入 Jenkins 流水线
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
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
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=SignalScout AI Intelligence API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/signalscout
|
||||
EnvironmentFile=/opt/signalscout/.env
|
||||
ExecStart=/opt/signalscout/.venv/bin/python -B -m uvicorn app.main:app --host 127.0.0.1 --port 8020
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user