新增自动化部署:Gitea Actions + systemd + gunicorn
Some checks failed
Deploy / deploy (push) Failing after 1s
Some checks failed
Deploy / deploy (push) Failing after 1s
- .gitea/workflows/deploy.yml:push main 自动触发部署
- requirements.txt:Python 依赖清单
- deploy/opc-manager.service:systemd 服务(gunicorn --preload -w 4)
- deploy/README.md:完整部署指南
- deploy/服务器配置任务提示词.md:给服务器管理 Agent 的操作提示词
- health 接口简化返回 {ok, service}
This commit is contained in:
90
.gitea/workflows/deploy.yml
Normal file
90
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,90 @@
|
||||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: prod-deploy
|
||||
env:
|
||||
DEPLOY_BASE: /opt/opc-manager
|
||||
REPO_URL: https://qiukai:${{ secrets.DEPLOY_TOKEN }}@git.qiukai.me/qiukai/opc-manager.git
|
||||
SERVICE_NAME: opc-manager
|
||||
steps:
|
||||
- name: Clone and deploy
|
||||
run: |
|
||||
set -e
|
||||
RELEASE_ID="${{ github.sha }}"
|
||||
RELEASE_DIR="${DEPLOY_BASE}/releases/${RELEASE_ID}"
|
||||
CLONE_DIR="/tmp/opc-deploy-${RELEASE_ID}"
|
||||
|
||||
echo "=== 1. Clone repository ==="
|
||||
rm -rf "${CLONE_DIR}"
|
||||
git clone --depth 1 --branch main "${REPO_URL}" "${CLONE_DIR}"
|
||||
|
||||
echo "=== 2. Prepare release directory ==="
|
||||
rm -rf "${RELEASE_DIR}"
|
||||
mkdir -p "${RELEASE_DIR}"
|
||||
|
||||
# Copy repo content to release dir (exclude .git, .env, venv, data)
|
||||
rsync -a --exclude='.git' \
|
||||
--exclude='.env' \
|
||||
--exclude='.env.local' \
|
||||
--exclude='.venv' \
|
||||
--exclude='data/uploads' \
|
||||
--exclude='data/opc.sqlite' \
|
||||
--exclude='__pycache__' \
|
||||
--exclude='.gitea' \
|
||||
"${CLONE_DIR}/" "${RELEASE_DIR}/"
|
||||
|
||||
echo "=== 3. Link shared resources ==="
|
||||
# .env from shared dir (not in git)
|
||||
ln -sfn "${DEPLOY_BASE}/shared/.env" "${RELEASE_DIR}/.env"
|
||||
# uploads directory from shared (persist across releases)
|
||||
mkdir -p "${DEPLOY_BASE}/shared/uploads"
|
||||
ln -sfn "${DEPLOY_BASE}/shared/uploads" "${RELEASE_DIR}/data/uploads"
|
||||
|
||||
echo "=== 4. Setup Python venv ==="
|
||||
cd "${RELEASE_DIR}"
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
echo "=== 5. Restart service ==="
|
||||
# Update WorkingDirectory in service via symlink approach
|
||||
# The systemd service points to /opt/opc-manager/current
|
||||
ln -sfn "${RELEASE_DIR}" "${DEPLOY_BASE}/current"
|
||||
systemctl restart "${SERVICE_NAME}"
|
||||
sleep 3
|
||||
|
||||
echo "=== 6. Health check ==="
|
||||
for i in 1 2 3 4 5; do
|
||||
if curl -fsS http://127.0.0.1:5177/api/health >/dev/null 2>&1; then
|
||||
echo "Health check passed"
|
||||
break
|
||||
fi
|
||||
echo "Attempt $i: waiting for service..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# Final verify
|
||||
if ! curl -fsS http://127.0.0.1:5177/api/health >/dev/null 2>&1; then
|
||||
echo "ERROR: Health check failed after 5 attempts"
|
||||
echo "Rolling back to previous release..."
|
||||
PREV=$(ls -t "${DEPLOY_BASE}/releases" | sed -n '2p')
|
||||
if [ -n "${PREV}" ]; then
|
||||
ln -sfn "${DEPLOY_BASE}/releases/${PREV}" "${DEPLOY_BASE}/current"
|
||||
systemctl restart "${SERVICE_NAME}"
|
||||
echo "Rolled back to ${PREV}"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== 7. Cleanup old releases ==="
|
||||
find "${DEPLOY_BASE}/releases" -mindepth 1 -maxdepth 1 -type d | sort | head -n -5 | xargs -r rm -rf
|
||||
|
||||
echo "=== 8. Cleanup temp ==="
|
||||
rm -rf "${CLONE_DIR}"
|
||||
|
||||
echo "=== Deploy complete: ${RELEASE_ID} ==="
|
||||
@@ -1046,7 +1046,7 @@ def delete_file(file_id):
|
||||
|
||||
@app.route("/api/health")
|
||||
def health():
|
||||
return jsonify({"ok": True, "db": str(DB_PATH)})
|
||||
return jsonify({"ok": True, "service": "opc-manager"})
|
||||
|
||||
|
||||
init_db()
|
||||
|
||||
193
deploy/README.md
Normal file
193
deploy/README.md
Normal file
@@ -0,0 +1,193 @@
|
||||
# OPC-Manager 自动化部署指南
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
开发者 push main → Gitea 仓库 (git.qiukai.me)
|
||||
↓
|
||||
Gitea Actions 触发
|
||||
↓
|
||||
Runner(跑在业务服务器 82.157.208.197 上)
|
||||
↓
|
||||
git clone → rsync 到 release 目录
|
||||
↓
|
||||
创建 venv → pip install → systemctl restart
|
||||
↓
|
||||
健康检查 → 切换 current 软链 → 清理旧版本
|
||||
```
|
||||
|
||||
## 服务器目录结构
|
||||
|
||||
```
|
||||
/opt/opc-manager/
|
||||
├── releases/
|
||||
│ ├── abc1234/ ← 本次发布(commit sha)
|
||||
│ ├── def5678/ ← 上次发布
|
||||
│ └── ... ← 保留最近 5 个
|
||||
├── shared/
|
||||
│ ├── .env ← 环境变量(不进 git,持久化)
|
||||
│ └── uploads/ ← 上传的文件(持久化,跨版本共享)
|
||||
└── current → releases/abc1234 ← 软链,指向当前生效版本
|
||||
```
|
||||
|
||||
## 一次性准备(在业务服务器上执行)
|
||||
|
||||
### 1. 安装 Gitea Actions Runner
|
||||
|
||||
```bash
|
||||
# 下载 act_runner
|
||||
cd /opt
|
||||
wget https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64 -O act_runner
|
||||
chmod +x act_runner
|
||||
mv act_runner /usr/local/bin/
|
||||
|
||||
# 注册 runner(到 git.qiukai.me)
|
||||
# 先在 Gitea 网页:仓库设置 → Actions → Runners → New runner,获取 token
|
||||
act_runner register \
|
||||
--instance https://git.qiukai.me \
|
||||
--token <YOUR_RUNNER_TOKEN> \
|
||||
--name prod-deploy \
|
||||
--labels prod-deploy \
|
||||
--no-interactive
|
||||
|
||||
# 安装为系统服务
|
||||
act_runner daemon --config /etc/act_runner/config.yaml &
|
||||
# 或用 systemd:
|
||||
cat > /etc/systemd/system/act-runner.service <<'EOF'
|
||||
[Unit]
|
||||
Description=Gitea Actions Runner
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/act_runner daemon
|
||||
Restart=on-failure
|
||||
Environment=HOME=/root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now act-runner
|
||||
```
|
||||
|
||||
### 2. 创建部署目录结构
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/opc-manager/{releases,shared/uploads}
|
||||
```
|
||||
|
||||
### 3. 创建 .env 文件
|
||||
|
||||
```bash
|
||||
cat > /opt/opc-manager/shared/.env <<'EOF'
|
||||
SECRET_KEY=改成一串随机字符串_至少32位
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_USER=opc
|
||||
DB_PASSWORD=opc123456
|
||||
DB_NAME=opc
|
||||
FLASK_DEBUG=false
|
||||
EOF
|
||||
|
||||
chmod 600 /opt/opc-manager/shared/.env
|
||||
```
|
||||
|
||||
### 4. 安装 systemd service
|
||||
|
||||
```bash
|
||||
# 从仓库的 deploy/opc-manager.service 复制
|
||||
cat > /etc/systemd/system/opc-manager.service <<'EOF'
|
||||
[Unit]
|
||||
Description=OPC Manager (Flask)
|
||||
After=network.target mysql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/opc-manager/current
|
||||
ExecStart=/opt/opc-manager/current/.venv/bin/gunicorn --preload -w 4 -b 0.0.0.0:5177 backend.flask_app:app
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
EnvironmentFile=/opt/opc-manager/current/.env
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable opc-manager
|
||||
```
|
||||
|
||||
### 5. 配置 Gitea Secret
|
||||
|
||||
在 Gitea 网页操作:
|
||||
1. 进入仓库 `qiukai/opc-manager`
|
||||
2. 设置 → Actions → Secrets → New Secret
|
||||
3. Name: `DEPLOY_TOKEN`
|
||||
4. Value: 你的 Gitea Personal Access Token(需要有 repo 读权限)
|
||||
- 生成路径:头像 → 设置 → 应用 → 生成令牌
|
||||
|
||||
### 6. 首次手动部署
|
||||
|
||||
push 代码前,先手动跑一次确保目录结构正确:
|
||||
|
||||
```bash
|
||||
cd /opt/opc-manager
|
||||
git clone --depth 1 --branch main https://git.qiukai.me/qiukai/opc-manager.git /tmp/opc-init
|
||||
RELEASE_DIR=/opt/opc-manager/releases/initial
|
||||
mkdir -p "${RELEASE_DIR}"
|
||||
rsync -a --exclude='.git' --exclude='.env' --exclude='.venv' /tmp/opc-init/ "${RELEASE_DIR}/"
|
||||
ln -sfn /opt/opc-manager/shared/.env "${RELEASE_DIR}/.env"
|
||||
ln -sfn /opt/opc-manager/shared/uploads "${RELEASE_DIR}/data/uploads"
|
||||
cd "${RELEASE_DIR}"
|
||||
python3 -m venv .venv
|
||||
. .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
ln -sfn "${RELEASE_DIR}" /opt/opc-manager/current
|
||||
systemctl start opc-manager
|
||||
curl http://127.0.0.1:5177/api/health
|
||||
rm -rf /tmp/opc-init
|
||||
```
|
||||
|
||||
## 日常使用
|
||||
|
||||
### 发布新版本
|
||||
```bash
|
||||
# 本地
|
||||
git push origin main
|
||||
# 自动触发 Gitea Actions → 服务器自动部署
|
||||
```
|
||||
|
||||
### 查看部署状态
|
||||
```bash
|
||||
# 在 Gitea 网页:仓库 → Actions 查看部署日志
|
||||
# 或在服务器:
|
||||
systemctl status opc-manager
|
||||
ls -la /opt/opc-manager/current
|
||||
```
|
||||
|
||||
### 回滚
|
||||
```bash
|
||||
# 列出历史版本
|
||||
ls -t /opt/opc-manager/releases
|
||||
# 切换到上一个版本
|
||||
PREV=$(ls -t /opt/opc-manager/releases | sed -n '2p')
|
||||
ln -sfn "/opt/opc-manager/releases/${PREV}" /opt/opc-manager/current
|
||||
systemctl restart opc-manager
|
||||
```
|
||||
|
||||
## Nginx 反代(可选)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name opc.yxcowork.vip;
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:5177;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
}
|
||||
```
|
||||
14
deploy/opc-manager.service
Normal file
14
deploy/opc-manager.service
Normal file
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=OPC Manager (Flask)
|
||||
After=network.target mysql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/opc-manager/current
|
||||
ExecStart=/opt/opc-manager/current/.venv/bin/gunicorn --preload -w 4 -b 0.0.0.0:5177 backend.flask_app:app
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
EnvironmentFile=/opt/opc-manager/current/.env
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
82
deploy/服务器配置任务提示词.md
Normal file
82
deploy/服务器配置任务提示词.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# OPC-Manager 自动化部署配置任务
|
||||
|
||||
## 背景
|
||||
OPC-Manager 项目(Flask + MySQL,端口 5177)需要配置 Gitea Actions 自动化部署。参考 SalesManager 的模式:push 到 main 分支后自动部署到业务服务器。部署工作流文件已写好(`.gitea/workflows/deploy.yml`),需要在服务器上完成一次性准备。
|
||||
|
||||
## 服务器信息
|
||||
- 业务服务器:82.157.208.197(SSH 别名 `ssh business`)
|
||||
- Gitea 地址:https://git.qiukai.me
|
||||
- 仓库:qiukai/opc-manager
|
||||
- 服务端口:5177
|
||||
- MySQL:已安装(8.0.45,系统服务),数据库 `opc`,用户 `opc/opc123456`
|
||||
|
||||
## 需要完成的 5 个步骤
|
||||
|
||||
### 1. 安装 Gitea Actions Runner
|
||||
在业务服务器上安装 `act_runner` 并注册到 Gitea:
|
||||
- 下载地址:https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
|
||||
- 放到 `/usr/local/bin/act_runner`
|
||||
- 注册时 name=`prod-deploy`,labels=`prod-deploy`
|
||||
- 注册 token 需要到 Gitea 网页获取:仓库 qiukai/opc-manager → 设置 → Actions → Runners → New runner
|
||||
- 安装为 systemd 服务(`/etc/systemd/system/act-runner.service`),开机自启
|
||||
|
||||
### 2. 创建部署目录结构
|
||||
```bash
|
||||
mkdir -p /opt/opc-manager/{releases,shared/uploads}
|
||||
```
|
||||
|
||||
### 3. 创建 .env 文件
|
||||
在 `/opt/opc-manager/shared/.env` 创建环境变量文件:
|
||||
```
|
||||
SECRET_KEY=随机生成32位以上字符串
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_USER=opc
|
||||
DB_PASSWORD=opc123456
|
||||
DB_NAME=opc
|
||||
FLASK_DEBUG=false
|
||||
```
|
||||
权限设为 600。
|
||||
|
||||
### 4. 安装 systemd service
|
||||
创建 `/etc/systemd/system/opc-manager.service`:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=OPC Manager (Flask)
|
||||
After=network.target mysql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/opc-manager/current
|
||||
ExecStart=/opt/opc-manager/current/.venv/bin/gunicorn --preload -w 4 -b 0.0.0.0:5177 backend.flask_app:app
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
EnvironmentFile=/opt/opc-manager/current/.env
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
执行 `systemctl daemon-reload && systemctl enable opc-manager`(先不 start,等首次部署后自动启动)。
|
||||
|
||||
### 5. 配置 Gitea Secret
|
||||
在 Gitea 网页操作(需要用户在浏览器完成):
|
||||
- 进入仓库 qiukai/opc-manager → 设置 → Actions → Secrets → New Secret
|
||||
- Name: `DEPLOY_TOKEN`
|
||||
- Value: 用户的 Gitea Personal Access Token(需 repo 读权限)
|
||||
- 生成路径:头像 → 设置 → 应用 → 生成令牌
|
||||
|
||||
## 首次部署验证
|
||||
准备完成后,在本地执行一次 `git push origin main`,观察:
|
||||
1. Gitea 网页 Actions 页面是否有部署任务在运行
|
||||
2. 部署日志是否正常
|
||||
3. 部署完成后 `curl http://127.0.0.1:5177/api/health` 是否返回 `{"ok":true,"service":"opc-manager"}`
|
||||
4. `systemctl status opc-manager` 是否 active
|
||||
|
||||
## 参考文件
|
||||
项目的部署工作流在仓库的 `.gitea/workflows/deploy.yml`,systemd 模板在 `deploy/opc-manager.service`,完整说明在 `deploy/README.md`。
|
||||
|
||||
## 注意事项
|
||||
- Gitea Runner 的 token 需要用户在浏览器获取后告诉你,你无法自动获取
|
||||
- Gitea Secret (DEPLOY_TOKEN) 也需要用户在浏览器配置
|
||||
- 如果服务器没有 python3.11+,需要先安装(OPC-Manager 要求 Python 3.9+)
|
||||
- 确保服务器已安装 git、rsync、curl(一般都有)
|
||||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
flask==3.1.3
|
||||
mysql-connector-python==9.4.0
|
||||
python-dotenv==1.2.1
|
||||
werkzeug==3.1.8
|
||||
gunicorn==23.0.0
|
||||
Reference in New Issue
Block a user