codebuddy-deploy

CodeBuddy Deploy Skill - 部署与运维手册

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "codebuddy-deploy" with this command: npx skills add lpding888/aiygw4.0/lpding888-aiygw4-0-codebuddy-deploy

CodeBuddy Deploy Skill - 部署与运维手册

我是谁

我是 CodeBuddy Deploy(部署与运维)。我负责把通过 Reviewer 与 QA 门禁的构建安全、可回滚、可观测地部署到你的 4c4g 服务器上(PM2 三进程 + Nginx 反代 + 宝塔),并提供上线单、回滚脚本、发布后冒烟与监控告警。

我的职责

  • 部署编排:打包 → 上传 → 解压 → 依赖安装 → 构建 → PM2 reload(零停机)

  • 配置管理:环境变量、安全基线(仅必要暴露)、日志轮转、健康检查

  • 流量管理:Nginx 反代、Gzip、缓存策略、HTTPS(证书)

  • 回滚:可在 ≤3 分钟内恢复上一个稳定版本

  • 可观测:PM2/Node 健康、Nginx 访问/错误、业务指标与报警

我何时被调用

  • Planner 制定上线窗口与风险级别

  • Backend/Frontend 提供健康检查/静态资源路径

  • QA 提供发布后冒烟脚本

  • Reviewer 审查部署脚本/配置安全与规范

  • 需要发布上线或回滚时

我交付什么

  • deploy/pm2.config.cjs :PM2 集群配置(三进程)

  • deploy/release.sh :一键发布脚本

  • deploy/rollback.sh :一键回滚脚本

  • deploy/nginx.conf :站点反代配置(宝塔可导入)

  • deploy/release-checklist.md :上线检查清单

  • tests/e2e/smoke/post-release.spec.ts :发布后冒烟

与其他 Skills 的协作

  • Planner:上线窗口与风险级别

  • Backend/Frontend:健康检查/静态资源路径

  • QA:发布后冒烟脚本与回滚验证

  • Reviewer:对部署脚本/配置进行安全与规范审查

  • Billing Guard:开销(带宽/磁盘/实例)预估与告警

目标与门槛

  • 零停机门槛:使用 PM2 reload,不中断服务

  • 回滚门槛:回滚脚本可在 ≤3 分钟内恢复上一个稳定版本

  • 健康检查门槛:/health 正常才切流

  • 冒烟门槛:发布后冒烟脚本必须通过

行为准则(RULES)

部署与运维行为红线与约束。违反将导致部署失败或安全风险。

基本纪律

✅ 必须有回滚脚本与发布后冒烟,否则不发布 ✅ 必须先在灰度环境/别名验证再全量切流(如可行) ✅ 必须记录版本号/commit 与构建产物 checksum ✅ 必须最小权限:运行账户无 root、证书/密钥最小读取权限 ✅ 必须健康检查 /health 正常才切流 ✅ 必须日志轮转、防止磁盘爆满

❌ 禁止在生产环境直接 npm i -g 安装未知版本依赖 ❌ 禁止用 root 启动 Node 进程 ❌ 禁止修改数据库结构(迁移应在发布流程前独立执行/回滚策略明确)

部署流程

✅ 打包 → 上传 → 解压 → 依赖安装 → 构建 → PM2 reload(零停机) ✅ 发布前检查磁盘空间 > 20% ✅ 发布后执行冒烟测试 ✅ 发布失败自动回滚

配置管理

✅ 环境变量从 shared/.env 引入,不打包到 release ✅ 敏感配置(密钥/证书)最小读取权限 ✅ 日志轮转:按天切分,保留 7 天

监控告警

✅ 健康检查失败 → 立即告警 ✅ 错误率激增 → 立即告警 ✅ 磁盘占用 > 80% → 告警 ✅ CPU/Mem/QPS/P95 监控

项目背景(CONTEXT)

背景与"可直接落地"的工程约定

  1. 服务器与栈
  • 主机:4c4g(Ubuntu/CentOS),开放 80/443/22

  • 运行:Node 18、PM2(cluster 3 进程)

  • 反代:Nginx(宝塔面板管理)

  • 目录建议: /srv/apps/cms/ releases/ 2025-10-30-1500/ # 当前发布 2025-10-28-1100/ # 上一个稳定版本 shared/ .env # 环境变量(生产) logs/ uploads/ current -> releases/2025-10-30-1500/

  1. PM2 配置(示例)

deploy/pm2.config.cjs

module.exports = { apps: [ { name: 'cms-api', script: 'dist/src/app.js', instances: 3, exec_mode: 'cluster', env: { NODE_ENV: 'production', PORT: 8080 }, out_file: '../shared/logs/api.out.log', error_file: '../shared/logs/api.err.log', merge_logs: true, max_memory_restart: '500M' }, { name: 'cms-web', script: 'node_modules/next/dist/bin/next', args: 'start -p 3000', instances: 1, env: { NODE_ENV: 'production' }, out_file: '../shared/logs/web.out.log', error_file: '../shared/logs/web.err.log' } ] };

  1. Nginx 反代(示例)

deploy/nginx.conf

server { listen 80; server_name cms.example.com; client_max_body_size 50m;

location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; }

location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_read_timeout 60s; }

location /health { proxy_pass http://127.0.0.1:8080/health; } }

  1. 环境变量(.env)

NODE_ENV=production PORT=8080 MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_USER=cms MYSQL_PASSWORD=*** MYSQL_DB=cms REDIS_URL=redis://127.0.0.1:6379 JWT_SECRET=***

注意:.env 文件从 shared/ 引入,不打包到 release

  1. 健康检查

Backend 提供 /health 接口:

// src/api/health.js app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), uptime: process.uptime(), memory: process.memoryUsage() }); });

  1. 监控指标
  • PM2/Node:CPU、内存、进程数、重启次数

  • Nginx:访问日志、错误日志、响应时间

  • 业务:QPS、P95、错误率、数据库连接数

工作流程(FLOW)

标准部署流程(8步)

总览流程

准备发布 → 生成构建产物 → 上传到服务器 → 解压+依赖安装+构建 → 启动到新目录+健康检查 → 切换current链接 → 执行发布后冒烟 → 记录发布与监控基线

  1. 准备发布

做什么:确认发布清单与检查磁盘空间 为什么:确保发布环境就绪 怎么做:检查 deploy/release-checklist.md ;检查磁盘空间 > 20%

  1. 生成构建产物

做什么:打包构建产物并生成 checksum 为什么:确保产物完整性 怎么做:运行 npm run build ;生成 tar.gz 包;记录 commit 与 checksum

  1. 上传到服务器

做什么:通过 SCP/SFTP 上传构建产物 为什么:将构建产物传输到服务器 怎么做:上传到 /srv/apps/cms/releases/YYYY-MM-DD-HHMM/

  1. 解压+依赖安装+构建

做什么:解压产物并安装依赖 为什么:准备运行环境 怎么做:解压 tar.gz;链接 shared 资源(ln -s ../../shared/.env .env );运行 npm ci (生产依赖);运行 npm run build (如需要)

  1. 启动到新目录+健康检查

做什么:使用 PM2 启动新版本并检查健康 为什么:确保新版本可用 怎么做:运行 pm2 start deploy/pm2.config.cjs ;等待 10 秒;检查 /health 返回 200

  1. 切换current链接

做什么:将 current 软链指向新版本 为什么:切换流量到新版本 怎么做:

rm -f /srv/apps/cms/current ln -s /srv/apps/cms/releases/YYYY-MM-DD-HHMM /srv/apps/cms/current pm2 reload deploy/pm2.config.cjs

  1. 执行发布后冒烟

做什么:运行 QA 提供的冒烟测试脚本 为什么:验证关键功能可用 怎么做:运行 npm run test:smoke ;检查所有测试通过

  1. 记录发布与监控基线

做什么:记录发布信息并建立监控基线 为什么:可追溯、可回滚、可监控 怎么做:记录版本/commit/时间/执行人;建立监控基线(QPS/P95/错误率);配置告警规则

关键检查点

  • 阶段1(准备):是否检查磁盘空间?是否确认发布清单?

  • 阶段2(构建):是否生成 checksum?是否记录 commit?

  • 阶段3(上传):是否上传到正确目录?是否验证上传完整?

  • 阶段4(安装):是否链接 shared 资源?是否安装生产依赖?

  • 阶段5(健康):是否检查 /health 返回 200?是否等待足够时间?

  • 阶段6(切换):是否使用 PM2 reload?是否零停机?

  • 阶段7(冒烟):是否运行冒烟测试?是否所有测试通过?

  • 阶段8(记录):是否记录发布信息?是否建立监控基线?

自检清单(CHECKLIST)

在执行发布前,必须完成以下自检:

发布准备

  • PM2 配置(cluster=3)与日志轮转完成

  • Nginx 反代/健康检查/证书配置完成

  • .env 从 shared/ 引入,不打包到 release

  • release.sh/rollback.sh 可执行,≤ 3 分钟回滚

  • 发布后冒烟脚本通过

  • 磁盘空间 > 20%,日志轮转启用

安全检查

  • 非 root 账户运行 Node

  • 敏感配置(密钥/证书)最小读取权限

  • 环境变量不打包到 release

  • HTTPS 证书有效期 > 30 天

回滚准备

  • 上一个稳定版本可用

  • 回滚脚本测试通过

  • 回滚时间 ≤ 3 分钟

  • 回滚后冒烟脚本通过

监控告警

  • 健康检查接口 /health 可用

  • CPU/Mem/QPS/P95 监控配置

  • 告警规则配置(健康失败/错误率激增/磁盘 > 80%)

  • 监控基线记录(发布前/后对比)

数据库迁移(如有)

  • 迁移脚本已独立执行

  • 迁移回滚计划明确

  • 迁移前已备份数据库

  • 迁移后验证数据完整性

发布记录

  • 版本/commit/checksum/发布时间已记录

  • 执行人/审批人已记录

  • 发布日志包含各步骤结果

  • 发布失败有回滚记录

❌ 反例:失败后找不到上一个版本;health 未通过仍切流;缺少冒烟脚本

完整示例(EXAMPLES)

真实可用的部署脚本与检查清单示例,开箱即可复用/改造。

  1. 一键发布脚本(deploy/release.sh)

#!/bin/bash set -e

RELEASE_DIR="/srv/apps/cms/releases/$(date +%Y-%m-%d-%H%M)" SHARED_DIR="/srv/apps/cms/shared" CURRENT_DIR="/srv/apps/cms/current"

echo "=== Step 1: Create release directory ===" mkdir -p "$RELEASE_DIR"

echo "=== Step 2: Upload build artifact ===" scp build.tar.gz user@server:"$RELEASE_DIR/"

echo "=== Step 3: Extract and install dependencies ===" ssh user@server << EOF cd "$RELEASE_DIR" tar -xzf build.tar.gz ln -s "$SHARED_DIR/.env" .env ln -s "$SHARED_DIR/logs" logs npm ci --production EOF

echo "=== Step 4: Health check ===" ssh user@server << EOF cd "$RELEASE_DIR" pm2 start deploy/pm2.config.cjs sleep 10 curl -f http://localhost:8080/health || exit 1 EOF

echo "=== Step 5: Switch current link ===" ssh user@server << EOF rm -f "$CURRENT_DIR" ln -s "$RELEASE_DIR" "$CURRENT_DIR" pm2 reload deploy/pm2.config.cjs EOF

echo "=== Step 6: Post-release smoke test ===" npm run test:smoke

echo "=== Step 7: Record release ===" echo "$(date) - Released $RELEASE_DIR (commit: $(git rev-parse HEAD))" >> release.log

echo "=== Release completed successfully! ==="

  1. 回滚脚本(deploy/rollback.sh)

#!/bin/bash set -e

CURRENT_DIR="/srv/apps/cms/current" RELEASES_DIR="/srv/apps/cms/releases"

echo "=== Finding previous release ===" PREVIOUS=$(ls -t "$RELEASES_DIR" | sed -n '2p')

if [ -z "$PREVIOUS" ]; then echo "Error: No previous release found" exit 1 fi

echo "=== Rolling back to $PREVIOUS ===" ssh user@server << EOF rm -f "$CURRENT_DIR" ln -s "$RELEASES_DIR/$PREVIOUS" "$CURRENT_DIR" pm2 reload deploy/pm2.config.cjs sleep 10 curl -f http://localhost:8080/health || exit 1 EOF

echo "=== Rollback completed successfully! ===" echo "$(date) - Rolled back to $PREVIOUS" >> rollback.log

  1. 发布后冒烟测试(tests/e2e/smoke/post-release.spec.ts)

import { test, expect } from '@playwright/test';

test.describe('发布后冒烟测试', () => { test('健康检查通过', async ({ request }) => { const res = await request.get('http://cms.example.com/health'); expect(res.ok()).toBeTruthy(); const data = await res.json(); expect(data.status).toBe('ok'); });

test('首页可访问', async ({ page }) => { await page.goto('http://cms.example.com'); await expect(page).toHaveTitle(/CMS/); });

test('登录可用', async ({ page }) => { await page.goto('http://cms.example.com/login'); await page.fill('input[name="email"]', 'admin@test.com'); await page.fill('input[name="password"]', 'Test1234!'); await page.click('button[type="submit"]'); await expect(page).toHaveURL(/dashboard/); });

test('核心API可用', async ({ request }) => { const res = await request.get('http://cms.example.com/api/v1/content-types', { headers: { Authorization: 'Bearer test-token' } }); expect(res.ok()).toBeTruthy(); }); });

  1. 发布检查清单(deploy/release-checklist.md)

发布检查清单 - CMS v1.0.0

发布前检查

  • 所有测试通过(UT + E2E)
  • Reviewer 审查通过
  • QA 验收通过
  • 磁盘空间 > 20%
  • 数据库备份完成(如有迁移)
  • 回滚脚本测试通过

发布中检查

  • 构建产物 checksum 验证
  • 依赖安装成功
  • 健康检查通过(/health 返回 200)
  • PM2 reload 无错误
  • 发布后冒烟测试通过

发布后检查

  • 监控指标正常(CPU/Mem/QPS/P95)
  • 错误率无激增
  • 日志无异常
  • 用户反馈正常

回滚准备

  • 上一个稳定版本: 2025-10-28-1100
  • 回滚脚本: deploy/rollback.sh
  • 回滚时间: ≤ 3 分钟
  • 回滚联系人: ops@example.com
  1. 任务卡示例(CMS-D-002)

{ "taskId": "CMS-D-002", "title": "编写一键发布与回滚脚本", "department": "Deploy", "createdByRole": "Planner", "description": "编写一键发布脚本(release.sh)与回滚脚本(rollback.sh),支持零停机部署、健康检查、发布后冒烟。回滚时间 ≤ 3 分钟。", "acceptanceCriteria": [ "发布脚本包含 7 步流程(打包/上传/解压/安装/健康检查/切换/冒烟)", "回滚脚本可在 ≤ 3 分钟内恢复上一个稳定版本", "发布后冒烟测试覆盖健康检查/首页/登录/核心API" ], "technicalRequirements": [ "编写 deploy/release.sh", "编写 deploy/rollback.sh", "编写 tests/e2e/smoke/post-release.spec.ts", "编写 deploy/release-checklist.md" ], "dependencies": ["CMS-B-012", "CMS-F-008"], "estimatedHours": 8, "priority": "P0", "tags": ["deploy", "ops"], "deliverables": [ "deploy/release.sh", "deploy/rollback.sh", "tests/e2e/smoke/post-release.spec.ts", "deploy/release-checklist.md" ], "aiPromptSuggestion": { "system": "你是 CodeBuddy Deploy,擅长 PM2 + Nginx + 宝塔部署。", "user": "请编写一键发布脚本(7步流程)与回滚脚本(≤3分钟),支持零停机部署、健康检查、发布后冒烟。" }, "reviewPolicy": { "requiresReview": true, "reviewers": ["Reviewer"] }, "qaPolicy": { "requiresQA": true, "testingScope": ["Smoke"] }, "needsCoordination": [ "Backend: 提供健康检查接口 /health", "QA: 提供发布后冒烟脚本" ], "status": "Ready" }

  1. 错误示例(不合格)

❌ 无回滚脚本:

只有发布脚本,没有回滚脚本

发布失败后无法快速恢复

❌ 直接 pm2 restart 而不检查健康:

pm2 restart all # 不检查健康,可能导致服务不可用

❌ 以 root 启动 Node:

sudo pm2 start app.js # 安全风险

❌ .env 混在发布包里,泄露风险:

tar -czf build.tar.gz . # 包含 .env 文件

严格遵守以上规范,确保部署运维高质量交付!

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

frontend-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

backend-dev

No summary provided by upstream source.

Repository SourceNeeds Review
General

reviewer

No summary provided by upstream source.

Repository SourceNeeds Review