This commit is contained in:
@@ -7,12 +7,12 @@
|
||||
- [`workflows/ci.yml`](workflows/ci.yml) — push / PR 到 `main` 触发。语法检查 + 干净 venv 安装依赖。**不**需要 root。
|
||||
- [`workflows/cd.yml`](workflows/cd.yml) — 推送 `v*` tag 或手动触发。流程:
|
||||
1. `stop.sh` 停掉旧实例(若存在)
|
||||
2. `rsync` 当前 checkout 到固定目录 `/opt/syscall_monitor`
|
||||
2. `rsync --delete` 当前 checkout 到固定目录 `/opt/syscall_monitor`,排除 `.git` / `.venv` / `.venv-ci` / `logs` / `.pid`,并 `chmod +x` 三个部署脚本
|
||||
3. `setup.sh` 装 venv 依赖
|
||||
4. `run.sh` 启动
|
||||
5. 校验 `.pid` 进程存活
|
||||
6. 重试 10 次 `curl http://127.0.0.1:5000` 做健康检查
|
||||
7. tail 启动日志
|
||||
5. `sleep 5` 后校验 `.pid` 进程存活,最多重试 3 次(每次间隔 2 秒)
|
||||
6. 重试 10 次 `curl http://127.0.0.1:5000` 做健康检查(每次间隔 2 秒)
|
||||
7. `tail` 启动日志(无论成功失败都执行)
|
||||
|
||||
**需要 root**。部署目录和健康检查 URL 在 workflow 顶部 `env:` 块里改。
|
||||
|
||||
@@ -21,37 +21,39 @@
|
||||
1. 在目标 Linux 主机上注册 act_runner,labels 至少包含 `self-hosted`。
|
||||
2. 安装系统依赖:
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo apt install -y python3-venv python3-bpfcc bpfcc-tools rsync curl linux-headers-$(uname -r)
|
||||
```
|
||||
|
||||
3. 创建固定部署目录并把所有权给 root(脚本以 root 运行):
|
||||
3. 创建固定部署目录(脚本以 root 运行,目录所有权保持 root):
|
||||
|
||||
```
|
||||
```bash
|
||||
sudo mkdir -p /opt/syscall_monitor
|
||||
```
|
||||
|
||||
4. 给 runner 用户配置免密 sudo。CD 用到的 root 命令有 4 个:rsync、setup.sh、run.sh、stop.sh,外加 tail 读 root 拥有的日志。写 `/etc/sudoers.d/syscall-monitor`:
|
||||
4. 给 runner 用户配置免密 sudo。写 `/etc/sudoers.d/syscall-monitor`(用 `sudo visudo -f` 编辑,文件权限 `0440`):
|
||||
|
||||
```
|
||||
gitea-runner ALL=(root) NOPASSWD: /usr/bin/rsync, /opt/syscall_monitor/setup.sh, /opt/syscall_monitor/run.sh, /opt/syscall_monitor/stop.sh, /usr/bin/tail
|
||||
gitea-runner ALL=(root) NOPASSWD: ALL
|
||||
```
|
||||
|
||||
只授权这些,不要 `ALL` 通配。`rsync` 路径以 `which rsync` 为准。
|
||||
- 用户名以实际 runner 进程身份为准(`id -un` 查看),不一定是 `gitea-runner`。
|
||||
- `rsync` 实际路径以 `which rsync` 为准(一般是 `/usr/bin/rsync`)。
|
||||
|
||||
## 触发方式
|
||||
|
||||
- 日常 push / PR → 自动跑 CI。
|
||||
- 发版部署 → 打 tag → 自动跑 CD:
|
||||
|
||||
```
|
||||
```bash
|
||||
git tag v0.1.0 && git push origin v0.1.0
|
||||
```
|
||||
|
||||
也可在 Gitea Actions 页面用 `workflow_dispatch` 手动触发。
|
||||
也可在 Gitea Actions 页面用 `workflow_dispatch` 手动触发(无需打 tag)。
|
||||
|
||||
## 注意
|
||||
|
||||
- 部署目录固定为 `/opt/syscall_monitor`。每次 CD 用 `rsync --delete` 全量同步代码(保留 `.venv` / `logs` / `.pid`),所以 venv 不会每次重建,依赖增量装。
|
||||
- 健康检查用 `HEALTH_URL` 默认 `http://127.0.0.1:5000`,重试 10 次每次间隔 2 秒。
|
||||
- 部署目录固定为 `/opt/syscall_monitor`。每次 CD 用 `rsync --delete` 全量同步代码,但排除 `.venv` / `.venv-ci` / `logs` / `.pid` / `.git`,所以 venv 不会每次重建,依赖增量装。
|
||||
- 健康检查 URL 由 `HEALTH_URL` 控制,默认 `http://127.0.0.1:5000`,重试 10 次每次间隔 2 秒。
|
||||
- `run.sh` 是 `nohup` 后台启动,runner 当前 workspace 跟部署目录是分开的——`.pid` 落在 `/opt/syscall_monitor/.pid`,CD 校验的就是这个。
|
||||
- 失败时 CD 会 `tail` `/opt/syscall_monitor/logs/app.log` 末尾若干行到 stderr,便于在 Actions 页面直接看启动日志。
|
||||
|
||||
@@ -14,25 +14,25 @@ jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: 检出代码
|
||||
uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Show target host info
|
||||
- name: 显示目标主机信息
|
||||
run: |
|
||||
echo "deploying on: $(hostname)"
|
||||
echo "user: $(id -un) ($(id -u))"
|
||||
echo "ref: ${{ gitea.ref }}"
|
||||
echo "deploy dir: $DEPLOY_DIR"
|
||||
echo "部署主机: $(hostname)"
|
||||
echo "执行用户: $(id -un) ($(id -u))"
|
||||
echo "触发引用: ${{ gitea.ref }}"
|
||||
echo "部署目录: $DEPLOY_DIR"
|
||||
|
||||
- name: Stop running instance (if any)
|
||||
- name: 停止旧实例(若存在)
|
||||
run: |
|
||||
if [ -x "$DEPLOY_DIR/stop.sh" ]; then
|
||||
sudo -n "$DEPLOY_DIR/stop.sh" || true
|
||||
else
|
||||
echo "no prior install at $DEPLOY_DIR, skipping stop"
|
||||
echo "$DEPLOY_DIR 下未发现旧实例,跳过停止步骤"
|
||||
fi
|
||||
|
||||
- name: Sync code to deploy dir
|
||||
- name: 同步代码到部署目录
|
||||
run: |
|
||||
sudo -n /usr/bin/rsync -a --delete \
|
||||
--exclude='.git' \
|
||||
@@ -43,18 +43,18 @@ jobs:
|
||||
./ "$DEPLOY_DIR/"
|
||||
sudo -n chmod +x "$DEPLOY_DIR/setup.sh" "$DEPLOY_DIR/run.sh" "$DEPLOY_DIR/stop.sh"
|
||||
|
||||
- name: Setup venv and dependencies
|
||||
- name: 安装 venv 与依赖
|
||||
run: sudo -n "$DEPLOY_DIR/setup.sh"
|
||||
|
||||
- name: Start service
|
||||
- name: 启动服务
|
||||
run: sudo -n "$DEPLOY_DIR/run.sh"
|
||||
|
||||
- name: Verify pid is alive
|
||||
- name: 校验进程存活
|
||||
run: |
|
||||
sleep 5
|
||||
PID_FILE="$DEPLOY_DIR/.pid"
|
||||
if [ ! -f "$PID_FILE" ]; then
|
||||
echo "no .pid file at $PID_FILE" >&2
|
||||
echo "未找到 pid 文件: $PID_FILE" >&2
|
||||
sudo -n tail -n 50 "$DEPLOY_DIR/logs/app.log" >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
@@ -62,30 +62,30 @@ jobs:
|
||||
echo "pid=$PID"
|
||||
for i in 1 2 3; do
|
||||
if [ -d "/proc/$PID" ]; then
|
||||
echo "service running, pid=$PID (attempt $i)"
|
||||
echo "服务运行中,pid=$PID(第 $i 次检查通过)"
|
||||
exit 0
|
||||
fi
|
||||
echo "attempt $i: pid $PID not alive yet, retrying..."
|
||||
echo "第 $i 次检查:pid $PID 尚未存活,重试中..."
|
||||
sleep 2
|
||||
done
|
||||
echo "pid $PID not alive after 3 attempts" >&2
|
||||
echo "重试 3 次后 pid $PID 仍未存活" >&2
|
||||
sudo -n tail -n 50 "$DEPLOY_DIR/logs/app.log" >&2 || true
|
||||
exit 1
|
||||
|
||||
- name: HTTP health check
|
||||
- name: HTTP 健康检查
|
||||
run: |
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if curl -fsS -o /dev/null "$HEALTH_URL"; then
|
||||
echo "health check passed on attempt $i"
|
||||
echo "第 $i 次健康检查通过"
|
||||
exit 0
|
||||
fi
|
||||
echo "attempt $i failed, retrying..."
|
||||
echo "第 $i 次健康检查失败,重试中..."
|
||||
sleep 2
|
||||
done
|
||||
echo "health check failed: $HEALTH_URL unreachable" >&2
|
||||
echo "健康检查失败:$HEALTH_URL 不可达" >&2
|
||||
sudo -n tail -n 80 "$DEPLOY_DIR/logs/app.log" >&2 || true
|
||||
exit 1
|
||||
|
||||
- name: Tail startup log
|
||||
- name: 输出启动日志
|
||||
if: always()
|
||||
run: sudo -n tail -n 30 "$DEPLOY_DIR/logs/app.log" || true
|
||||
|
||||
@@ -10,28 +10,20 @@ jobs:
|
||||
lint-and-build:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Checkout
|
||||
- name: 检出代码
|
||||
uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Python syntax check
|
||||
- name: Python 语法检查
|
||||
run: |
|
||||
python3 -m compileall -q collector web main.py
|
||||
|
||||
- name: Optional ruff lint
|
||||
run: |
|
||||
if command -v ruff >/dev/null 2>&1; then
|
||||
ruff check collector web main.py || true
|
||||
else
|
||||
echo "ruff not installed, skipping"
|
||||
fi
|
||||
|
||||
- name: Build venv (dry-run install)
|
||||
- name: 构建 venv
|
||||
run: |
|
||||
python3 -m venv --system-site-packages .venv-ci
|
||||
.venv-ci/bin/pip install --upgrade pip
|
||||
.venv-ci/bin/pip install -r requirements.txt
|
||||
.venv-ci/bin/python -c "import flask; print('flask', flask.__version__)"
|
||||
|
||||
- name: Cleanup
|
||||
- name: 清理临时 venv
|
||||
if: always()
|
||||
run: rm -rf .venv-ci
|
||||
|
||||
Reference in New Issue
Block a user