diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..2ef59df --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,95 @@ +name: CI Deploy + +on: + push: + branches: + - main + +env: + NODE_VERSION: 20 + +jobs: + build-test-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + + - name: Test + run: npm run test + + - name: Build + run: npm run build + + - name: Prune dev dependencies + run: npm prune --omit=dev + + - name: Package artifact + run: | + tar -czf qun-monitor-release.tar.gz \ + dist \ + keywords.yaml \ + package.json \ + package-lock.json \ + node_modules \ + .env.example \ + README.md + + - name: Upload artifact to server + uses: appleboy/scp-action@v0.1.7 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + password: ${{ secrets.DEPLOY_PASSWORD }} + port: ${{ secrets.DEPLOY_PORT || '22' }} + source: qun-monitor-release.tar.gz + target: ${{ secrets.DEPLOY_PACKAGE_DIR || '/home/atai/deployments/qun-monitor' }} + + - name: Remote deploy + uses: appleboy/ssh-action@v0.1.10 + with: + host: ${{ secrets.DEPLOY_HOST }} + username: ${{ secrets.DEPLOY_USER }} + password: ${{ secrets.DEPLOY_PASSWORD }} + port: ${{ secrets.DEPLOY_PORT || '22' }} + script_stop: true + command_timeout: 30m + script: | + set -euo pipefail + APP_DIR=${{ secrets.DEPLOY_APP_DIR || '/home/atai/services/qun-monitor' }} + PACKAGE_DIR=${{ secrets.DEPLOY_PACKAGE_DIR || '/home/atai/deployments/qun-monitor' }} + PACKAGE_FILE="${PACKAGE_DIR}/qun-monitor-release.tar.gz" + + mkdir -p "${APP_DIR}" "${PACKAGE_DIR}" + tar -xzf "${PACKAGE_FILE}" -C "${APP_DIR}" + + cd "${APP_DIR}" + + if [ ! -f .env ]; then + echo "[deploy] ⚠️ 未检测到 .env,已跳过启动,请参考 .env.example 配置后自行重启。" + exit 0 + fi + + if ! command -v pm2 >/dev/null 2>&1; then + sudo npm install -g pm2 + fi + + if pm2 describe qun-monitor >/dev/null 2>&1; then + pm2 restart qun-monitor --update-env + else + pm2 start npm --name qun-monitor -- start + fi + + pm2 save >/dev/null 2>&1 || true diff --git a/README.md b/README.md index a821c95..53b70ca 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,55 @@ keywords: - `npm run build`:编译到 `dist/`,配合 `npm run start` 运行。 - `npm run lint`:`tsc --noEmit` 类型检查。 - `npm run test`:Vitest 单测,当前覆盖 `KeywordStore` 热加载逻辑。 +- `npm run dev:inspect`:以 `node --inspect` 启动开发流程,便于 Chrome DevTools 调试。 +- `npm run start:inspect`:对编译后的 `dist/main.js` 开启 Inspector,适合线上问题排查。 ## 注意事项 - user-bot 与汇报 Bot 都必须在 `REPORT_CHAT_LINK` 对应的群/频道里,且 Bot 拥有发言权限。 - Telegram 对频繁入群会触发 `FLOOD_WAIT_xx`,日志会提示需要等待的秒数。 - `sessions/*.session` 含账号授权信息,请妥善保管。 - 长期部署建议使用 `pm2 / systemd` 等守护方式并接入日志轮转。 + +## CDP 调试检查(Chrome DevTools) +1. 本地或服务器执行 `npm run dev:inspect`(开发态)或 `npm run start:inspect`(生产态)。Node 会输出 `Debugger listening on ws://127.0.0.1:/...`,该端口是临时分配的,不会占用既有业务端口。 +2. 在 Chrome 地址栏输入 `chrome://inspect`,点击 “Configure”,将服务器 `IP:port`(若为远程需先通过 SSH 端口转发)加入可调试目标,然后点击 `inspect`。 +3. 在 Sources 面板设置断点,依次验证以下关键流程: + - `loadConfig`:检查 `.env` 解析、会话目录创建与多群链接拆分。 + - `createTelegramClient`:确认 `session` 落盘、验证码 / 2FA 输入路径。 + - `KeywordStore`:在 `registerWatcher` 处模拟 `keywords.yaml` 修改,验证热加载是否触发。 + - `GroupMonitor`:跟踪 `ensureJoined`、`watchGroup` 调用链,确保入群与群主识别逻辑正确。 + - `Reporter`:在 `sendAlert` 断点检查 Markdown 转义与 Bot Token 使用。 +4. 调试完成后可执行 `disconnect()`,或在终端 `Ctrl+C` 退出。若需复现问题,可结合 `console.profile`、`Performance` 面板导出火焰图。 + +## 服务器部署与 CI/CD + +### 一次性初始化 +1. 登录服务器(示例:`ssh atai@172.16.74.159`),确保 Node.js ≥ 18 与 npm 可用。 +2. 安装 pm2(如未安装):`sudo npm install -g pm2`。 +3. 创建运行目录:`mkdir -p /home/atai/services/qun-monitor`。 +4. 拷贝 `.env.example` 为 `.env` 并填入真实参数;首次登录需要人工输入短信验证码。 + +### Gitea Workflow 自动部署 +仓库内新增 `.gitea/workflows/deploy.yaml`,当 `main` 分支有推送时会执行: + +1. `npm ci && npm run lint && npm run test && npm run build`,保证代码通过类型检查与单测。 +2. `npm prune --omit=dev` 并将 `dist/ + node_modules + 环境模板 + README` 打包为 `qun-monitor-release.tar.gz`。 +3. 通过 `appleboy/scp-action` 将制品上传到服务器(默认 `/home/atai/deployments/qun-monitor`)。 +4. 使用 `appleboy/ssh-action` 在服务器解压至 `APP_DIR`(默认 `/home/atai/services/qun-monitor`),若检测到 `.env`,则: + - 自动安装 pm2(若缺失)。 + - `pm2 restart qun-monitor --update-env` 或 `pm2 start npm --name qun-monitor -- start`。 + - `pm2 save` 持久化进程列表。 + +### CI/CD 所需机密 +请在 Gitea 仓库 Settings → Secrets 中配置以下变量: + +| Secret 名称 | 说明 | +|-------------|------| +| `DEPLOY_HOST` | 服务器 IP,例如 `172.16.74.159` | +| `DEPLOY_PORT` | SSH 端口,默认 `22` 可省略 | +| `DEPLOY_USER` | SSH 用户名,例如 `atai` | +| `DEPLOY_PASSWORD` | 对应的登录密码 | +| `DEPLOY_APP_DIR` | (可选)部署目录,默认 `/home/atai/services/qun-monitor` | +| `DEPLOY_PACKAGE_DIR` | (可选)制品临时目录,默认 `/home/atai/deployments/qun-monitor` | + +如果服务器到 Gitea 存在网络限制(如本次环境无法直接访问 10.23.73.251:443),Workflow 将负责打包后 “推送” 到服务器,无需在服务器侧执行 `git pull`,避免占用已有进程端口或破坏现有代理设置。 diff --git a/package.json b/package.json index d3d8a67..fea2f37 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "build": "tsc -p tsconfig.json", "start": "node dist/main.js", "dev": "tsx src/main.ts", + "dev:inspect": "node --inspect=0 --loader tsx ./src/main.ts", + "start:inspect": "node --inspect=0 dist/main.js", "lint": "tsc --noEmit", "test": "vitest run" },