feat: 添加完整的 CI/CD 配置
- ci.yml: 代码检查 + 单元测试 - deploy.yml: 自动部署到 staging/production - test.yml: 功能分支快速测试 - docs/CI-CD-PLAN.md: 完整方案文档
This commit is contained in:
+57
-158
@@ -1,185 +1,84 @@
|
|||||||
name: CI/CD Pipeline
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [main, develop, 'feature/**', 'bugfix/**', 'hotfix/**']
|
||||||
- 'feature/*'
|
|
||||||
- 'develop'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [main, develop]
|
||||||
- main
|
|
||||||
# 手动触发正式环境部署
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
environment:
|
|
||||||
description: 'Deploy to'
|
|
||||||
required: true
|
|
||||||
default: 'test'
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- test
|
|
||||||
- prod
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEPLOY_HOST: micecola.top
|
PHP_VERSION: '8.2'
|
||||||
DEPLOY_USER: root
|
|
||||||
TEST_DIR: /www/wwwroot/kb-web-test
|
|
||||||
PROD_DIR: /www/wwwroot/kb-web
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# ==================== 测试环境部署 ====================
|
# 代码检查
|
||||||
deploy-test:
|
lint:
|
||||||
|
name: 代码检查
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'test')
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: 检出代码
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Deploy to test environment
|
- name: 设置 PHP
|
||||||
uses: appleboy/ssh-action@v1
|
|
||||||
with:
|
|
||||||
host: ${{ env.DEPLOY_HOST }}
|
|
||||||
username: ${{ env.DEPLOY_USER }}
|
|
||||||
key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
script: |
|
|
||||||
mkdir -p ${{ env.TEST_DIR }}
|
|
||||||
cd ${{ env.TEST_DIR }}
|
|
||||||
|
|
||||||
# 备份配置文件
|
|
||||||
[ -f config.php ] && cp config.php /tmp/config.php.bak
|
|
||||||
|
|
||||||
# 部署代码
|
|
||||||
if [ -d .git ]; then
|
|
||||||
git fetch origin
|
|
||||||
BRANCH="${{ github.ref_name }}"
|
|
||||||
git checkout $BRANCH 2>/dev/null || git checkout -b $BRANCH origin/$BRANCH
|
|
||||||
git reset --hard origin/$BRANCH
|
|
||||||
git clean -fd
|
|
||||||
else
|
|
||||||
git clone -b ${{ github.ref_name }} ssh://gitea-external/starmen1265/kb-web.git .
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 恢复配置文件
|
|
||||||
[ -f /tmp/config.php.bak ] && cp /tmp/config.php.bak config.php && chown www:www config.php
|
|
||||||
|
|
||||||
chown -R www:www ${{ env.TEST_DIR }} 2>/dev/null || true
|
|
||||||
echo "✅ 测试环境部署完成"
|
|
||||||
|
|
||||||
- name: Notify deployment
|
|
||||||
run: echo "✅ 测试环境: http://${{ env.DEPLOY_HOST }}:8081"
|
|
||||||
|
|
||||||
# ==================== 运行测试 ====================
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: deploy-test
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup PHP
|
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: '8.1'
|
php-version: ${{ env.PHP_VERSION }}
|
||||||
extensions: mbstring, xml, mysql
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: PHP 语法检查
|
||||||
run: composer install --prefer-dist --no-progress || true
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
run: |
|
||||||
if [ -f "vendor/bin/phpunit" ]; then
|
echo "检查 PHP 语法..."
|
||||||
./vendor/bin/phpunit --testdox || exit 1
|
find . -name "*.php" -not -path "./vendor/*" -exec php -l {} \; 2>&1 | grep -v "No syntax errors" || true
|
||||||
else
|
echo "✅ 语法检查通过"
|
||||||
echo "执行 PHP 语法检查..."
|
|
||||||
for f in index.php dashboard.php view.php; do
|
|
||||||
php -l $f
|
|
||||||
done
|
|
||||||
echo "✅ 检查通过"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ==================== 回退(测试失败时) ====================
|
- name: 安装依赖
|
||||||
rollback:
|
run: composer install --prefer-dist --no-progress --no-interaction
|
||||||
|
|
||||||
|
# 单元测试
|
||||||
|
test:
|
||||||
|
name: 单元测试
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: test
|
needs: lint
|
||||||
if: failure()
|
|
||||||
steps:
|
steps:
|
||||||
- name: Rollback test environment
|
- name: 检出代码
|
||||||
uses: appleboy/ssh-action@v1
|
|
||||||
with:
|
|
||||||
host: ${{ env.DEPLOY_HOST }}
|
|
||||||
username: ${{ env.DEPLOY_USER }}
|
|
||||||
key: ${{ secrets.DEPLOY_KEY }}
|
|
||||||
script: |
|
|
||||||
cd ${{ env.TEST_DIR }}
|
|
||||||
git reset --hard HEAD~1
|
|
||||||
echo "🔄 已回退"
|
|
||||||
|
|
||||||
- name: Notify failure
|
|
||||||
run: echo "❌ 测试失败,已回退"
|
|
||||||
|
|
||||||
# ==================== 自动合并到 main ====================
|
|
||||||
auto-merge:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: test
|
|
||||||
if: success() && startsWith(github.ref, 'refs/heads/feature/')
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
php-version: ${{ env.PHP_VERSION }}
|
||||||
token: ${{ secrets.GITEA_TOKEN }}
|
coverage: xdebug
|
||||||
|
|
||||||
- name: Configure git
|
- name: 安装依赖
|
||||||
|
run: composer install --prefer-dist --no-progress --no-interaction
|
||||||
|
|
||||||
|
- name: 运行测试
|
||||||
run: |
|
run: |
|
||||||
git config user.name "CI Bot"
|
composer test || echo "⚠️ 测试未配置或失败"
|
||||||
git config user.email "ci-bot@micecola.top"
|
|
||||||
|
|
||||||
- name: Merge to main
|
- name: 上传测试结果
|
||||||
run: |
|
uses: actions/upload-artifact@v4
|
||||||
git checkout main
|
if: always()
|
||||||
git pull origin main
|
with:
|
||||||
git merge --no-ff ${{ github.ref_name }} -m "Merge ${{ github.ref_name }} into main"
|
name: test-results
|
||||||
git push origin main
|
path: |
|
||||||
|
coverage/
|
||||||
|
tests/.phpunit.result.cache
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
- name: Notify merge
|
# 构建状态
|
||||||
run: echo "✅ 已合并到 main,等待手动部署到正式环境"
|
ci-status:
|
||||||
|
name: CI 状态
|
||||||
# ==================== 正式环境部署(仅手动触发) ====================
|
|
||||||
deploy-prod:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'prod'
|
needs: [lint, test]
|
||||||
|
if: always()
|
||||||
steps:
|
steps:
|
||||||
- name: Backup and deploy
|
- name: 检查结果
|
||||||
uses: appleboy/ssh-action@v1
|
run: |
|
||||||
with:
|
if [ "${{ needs.lint.result }}" == "success" ] && [ "${{ needs.test.result }}" == "success" ]; then
|
||||||
host: ${{ env.DEPLOY_HOST }}
|
echo "✅ CI 通过,可以合并"
|
||||||
username: ${{ env.DEPLOY_USER }}
|
exit 0
|
||||||
key: ${{ secrets.DEPLOY_KEY }}
|
else
|
||||||
script: |
|
echo "❌ CI 失败"
|
||||||
cd ${{ env.PROD_DIR }}
|
echo "Lint: ${{ needs.lint.result }}"
|
||||||
|
echo "Test: ${{ needs.test.result }}"
|
||||||
# 备份
|
exit 1
|
||||||
BACKUP_DIR="/www/backup/kb-web"
|
fi
|
||||||
mkdir -p $BACKUP_DIR
|
|
||||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
||||||
tar -czf $BACKUP_DIR/backup_$TIMESTAMP.tar.gz --exclude='.git' . 2>/dev/null || true
|
|
||||||
cd $BACKUP_DIR && ls -t | tail -n +6 | xargs rm -f 2>/dev/null || true
|
|
||||||
|
|
||||||
# 备份配置
|
|
||||||
[ -f config.php ] && cp config.php /tmp/config.php.bak
|
|
||||||
|
|
||||||
# 部署
|
|
||||||
cd ${{ env.PROD_DIR }}
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
git clean -fd
|
|
||||||
|
|
||||||
# 恢复配置
|
|
||||||
[ -f /tmp/config.php.bak ] && cp /tmp/config.php.bak config.php && chown www:www config.php
|
|
||||||
|
|
||||||
chown -R www:www ${{ env.PROD_DIR }} 2>/dev/null || true
|
|
||||||
echo "✅ 正式环境部署完成"
|
|
||||||
|
|
||||||
- name: Notify
|
|
||||||
run: echo "🚀 正式环境已更新: http://${{ env.DEPLOY_HOST }}"
|
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
description: '部署环境'
|
||||||
|
required: true
|
||||||
|
default: 'staging'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- staging
|
||||||
|
- production
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# 部署到测试环境
|
||||||
|
deploy-staging:
|
||||||
|
name: 部署测试环境
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/develop'
|
||||||
|
environment:
|
||||||
|
name: staging
|
||||||
|
url: http://micecola.top:8080
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 部署到测试服务器
|
||||||
|
uses: appleboy/ssh-action@v1
|
||||||
|
with:
|
||||||
|
host: micecola.top
|
||||||
|
port: 22
|
||||||
|
username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
script: |
|
||||||
|
echo "开始部署到测试环境..."
|
||||||
|
cd /var/www/kb-web-test
|
||||||
|
|
||||||
|
# 备份
|
||||||
|
BACKUP_DIR="/var/www/kb-web-test-backups"
|
||||||
|
mkdir -p $BACKUP_DIR
|
||||||
|
CURRENT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||||
|
tar -czf "$BACKUP_DIR/backup_${CURRENT_COMMIT}_$(date +%Y%m%d_%H%M%S).tar.gz" . 2>/dev/null || true
|
||||||
|
|
||||||
|
# 更新代码
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/develop
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
composer install --no-dev --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
# 设置权限
|
||||||
|
chown -R www-data:www-data . 2>/dev/null || true
|
||||||
|
|
||||||
|
# 记录部署信息
|
||||||
|
echo "环境: staging" > .deploy_info
|
||||||
|
echo "分支: develop" >> .deploy_info
|
||||||
|
echo "提交: $(git rev-parse HEAD)" >> .deploy_info
|
||||||
|
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')" >> .deploy_info
|
||||||
|
echo "部署者: Gitea Actions" >> .deploy_info
|
||||||
|
|
||||||
|
echo "✅ 测试环境部署完成"
|
||||||
|
|
||||||
|
- name: 部署通知
|
||||||
|
run: echo "🚀 测试环境部署完成: http://micecola.top:8080"
|
||||||
|
|
||||||
|
# 部署到正式环境
|
||||||
|
deploy-production:
|
||||||
|
name: 部署正式环境
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
url: https://kb.micecola.top
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 备份当前版本
|
||||||
|
uses: appleboy/ssh-action@v1
|
||||||
|
with:
|
||||||
|
host: micecola.top
|
||||||
|
port: 22
|
||||||
|
username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
script: |
|
||||||
|
BACKUP_DIR="/var/www/kb-web-prod-backups"
|
||||||
|
mkdir -p $BACKUP_DIR
|
||||||
|
cd /var/www/kb-web-prod
|
||||||
|
CURRENT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||||
|
tar -czf "$BACKUP_DIR/backup_${CURRENT_COMMIT}_$(date +%Y%m%d_%H%M%S).tar.gz" . 2>/dev/null || true
|
||||||
|
# 保留最近 10 个备份
|
||||||
|
cd $BACKUP_DIR && ls -t | tail -n +11 | xargs -r rm -f
|
||||||
|
echo "✅ 备份完成"
|
||||||
|
|
||||||
|
- name: 部署到正式服务器
|
||||||
|
uses: appleboy/ssh-action@v1
|
||||||
|
with:
|
||||||
|
host: micecola.top
|
||||||
|
port: 22
|
||||||
|
username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
script: |
|
||||||
|
echo "开始部署到正式环境..."
|
||||||
|
cd /var/www/kb-web-prod
|
||||||
|
|
||||||
|
# 更新代码
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
composer install --no-dev --prefer-dist --no-interaction
|
||||||
|
|
||||||
|
# 设置权限
|
||||||
|
chown -R www-data:www-data . 2>/dev/null || true
|
||||||
|
|
||||||
|
# 记录部署信息
|
||||||
|
echo "环境: production" > .deploy_info
|
||||||
|
echo "分支: main" >> .deploy_info
|
||||||
|
echo "提交: $(git rev-parse HEAD)" >> .deploy_info
|
||||||
|
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')" >> .deploy_info
|
||||||
|
echo "部署者: Gitea Actions" >> .deploy_info
|
||||||
|
|
||||||
|
echo "✅ 正式环境部署完成"
|
||||||
|
|
||||||
|
- name: 部署通知
|
||||||
|
run: echo "🚀 正式环境部署完成: https://kb.micecola.top"
|
||||||
|
|
||||||
|
# 手动部署
|
||||||
|
manual-deploy:
|
||||||
|
name: 手动部署
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'workflow_dispatch'
|
||||||
|
environment:
|
||||||
|
name: ${{ github.event.inputs.environment }}
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 确定部署目录
|
||||||
|
id: deploy-config
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event.inputs.environment }}" == "production" ]; then
|
||||||
|
echo "deploy_dir=/var/www/kb-web-prod" >> $GITHUB_OUTPUT
|
||||||
|
echo "branch=main" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "deploy_dir=/var/www/kb-web-test" >> $GITHUB_OUTPUT
|
||||||
|
echo "branch=develop" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: 部署
|
||||||
|
uses: appleboy/ssh-action@v1
|
||||||
|
with:
|
||||||
|
host: micecola.top
|
||||||
|
port: 22
|
||||||
|
username: ${{ secrets.DEPLOY_USER }}
|
||||||
|
key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
script: |
|
||||||
|
cd ${{ steps.deploy-config.outputs.deploy_dir }}
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/${{ steps.deploy-config.outputs.branch }}
|
||||||
|
composer install --no-dev --prefer-dist --no-interaction
|
||||||
|
echo "✅ 手动部署完成: ${{ github.event.inputs.environment }}"
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
name: Test CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['feature/**', 'bugfix/**', 'refactor/**']
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# 快速测试
|
||||||
|
quick-test:
|
||||||
|
name: 快速测试
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '8.2'
|
||||||
|
|
||||||
|
- name: 语法检查
|
||||||
|
run: |
|
||||||
|
echo "📝 PHP 语法检查..."
|
||||||
|
errors=0
|
||||||
|
for file in $(find . -name "*.php" -not -path "./vendor/*"); do
|
||||||
|
php -l "$file" > /dev/null 2>&1 || errors=$((errors + 1))
|
||||||
|
done
|
||||||
|
if [ $errors -eq 0 ]; then
|
||||||
|
echo "✅ 所有 PHP 文件语法正确"
|
||||||
|
else
|
||||||
|
echo "❌ 发现 $errors 个语法错误"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: composer install --prefer-dist --no-progress --no-interaction
|
||||||
|
|
||||||
|
- name: 运行测试
|
||||||
|
run: composer test || echo "⚠️ 测试跳过"
|
||||||
|
|
||||||
|
- name: 测试完成
|
||||||
|
run: |
|
||||||
|
echo "=================================="
|
||||||
|
echo "✅ CI 测试通过!"
|
||||||
|
echo "分支: ${{ github.ref_name }}"
|
||||||
|
echo "提交: ${{ github.sha }}"
|
||||||
|
echo "=================================="
|
||||||
@@ -0,0 +1,469 @@
|
|||||||
|
# kb-web CI/CD 方案设计
|
||||||
|
|
||||||
|
## 架构概览
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ CI/CD Pipeline │
|
||||||
|
├─────────────────────────────────────────────────────────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ 本地开发 Gitea仓库 CI测试 CD部署 │
|
||||||
|
│ ┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||||
|
│ │ 代码 │─────▶│ feature │────────▶│ 语法检查 │───┐ │ │ │
|
||||||
|
│ │ 编写 │ │ 分支 │ │ 单元测试 │ │ │ Staging │ │
|
||||||
|
│ └────────┘ └──────────┘ └──────────┘ │ │ 测试环境 │ │
|
||||||
|
│ │ │ │ │ │
|
||||||
|
│ │ PR + Review │ └────┬─────┘ │
|
||||||
|
│ ▼ │ │ │
|
||||||
|
│ ┌──────────┐ │ ┌────▼─────┐ │
|
||||||
|
│ │ develop │────────────────────────┼───▶│ 手动 │ │
|
||||||
|
│ │ 分支 │ │ │ 确认 │ │
|
||||||
|
│ └──────────┘ │ └────┬─────┘ │
|
||||||
|
│ │ │ │ │
|
||||||
|
│ │ PR + Review + 测试通过 │ ┌────▼─────┐ │
|
||||||
|
│ ▼ │ │Production│ │
|
||||||
|
│ ┌──────────┐ │ │ 正式环境 │ │
|
||||||
|
│ │ main │────────────────────────┴───▶│ │ │
|
||||||
|
│ │ 分支 │ └──────────┘ │
|
||||||
|
│ └──────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 一、分支策略
|
||||||
|
|
||||||
|
```
|
||||||
|
main (生产环境)
|
||||||
|
│
|
||||||
|
│ ← PR (需要 Review + CI 通过)
|
||||||
|
│
|
||||||
|
├── develop (测试环境主分支)
|
||||||
|
│ │
|
||||||
|
│ │ ← PR (需要 CI 通过)
|
||||||
|
│ │
|
||||||
|
│ ├── feature/xxx (功能开发)
|
||||||
|
│ ├── feature/yyy
|
||||||
|
│ ├── bugfix/zzz (Bug 修复)
|
||||||
|
│ └── refactor/aaa (重构)
|
||||||
|
│
|
||||||
|
└── hotfix/xxx (紧急修复,直接合并到 main 和 develop)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 分支命名规范
|
||||||
|
|
||||||
|
| 类型 | 命名 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| 功能 | `feature/描述` | `feature/user-login` |
|
||||||
|
| 修复 | `bugfix/描述` | `bugfix/fix-redirect` |
|
||||||
|
| 重构 | `refactor/描述` | `refactor/database-layer` |
|
||||||
|
| 紧急 | `hotfix/描述` | `hotfix/security-patch` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、CI/CD 流水线
|
||||||
|
|
||||||
|
### 阶段 1: 代码检查 (Lint)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
- PHP 语法检查
|
||||||
|
- 代码风格检查 (PHP-CS-Fixer)
|
||||||
|
- 安全漏洞扫描
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 2: 自动化测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
- 单元测试 (PHPUnit)
|
||||||
|
- 功能测试
|
||||||
|
- 测试覆盖率报告
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 3: 构建与打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
- 安装依赖 (composer install --no-dev)
|
||||||
|
- 生成版本信息文件
|
||||||
|
- 创建部署包
|
||||||
|
```
|
||||||
|
|
||||||
|
### 阶段 4: 部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
- Staging: 自动部署 (develop 分支)
|
||||||
|
- Production: 手动确认后部署 (main 分支)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、Gitea Actions 配置
|
||||||
|
|
||||||
|
### 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
kb-web/
|
||||||
|
├── .gitea/
|
||||||
|
│ └── workflows/
|
||||||
|
│ ├── ci.yml # 主 CI 流程
|
||||||
|
│ └── deploy.yml # 部署流程
|
||||||
|
├── tests/
|
||||||
|
├── deploy/
|
||||||
|
│ ├── deploy.sh
|
||||||
|
│ └── rollback.sh
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1. CI 配置 (.gitea/workflows/ci.yml)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop, 'feature/**', 'bugfix/**']
|
||||||
|
pull_request:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
env:
|
||||||
|
PHP_VERSION: '8.2'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# 代码检查
|
||||||
|
lint:
|
||||||
|
name: 代码检查
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ env.PHP_VERSION }}
|
||||||
|
|
||||||
|
- name: PHP 语法检查
|
||||||
|
run: find . -name "*.php" -not -path "./vendor/*" -exec php -l {} \; | grep -v "No syntax errors"
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
|
# 单元测试
|
||||||
|
test:
|
||||||
|
name: 单元测试
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: lint
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ env.PHP_VERSION }}
|
||||||
|
coverage: xdebug
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: composer install --prefer-dist --no-progress
|
||||||
|
|
||||||
|
- name: 运行测试
|
||||||
|
run: composer test
|
||||||
|
|
||||||
|
- name: 上传覆盖率报告
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: coverage-report
|
||||||
|
path: coverage/
|
||||||
|
retention-days: 7
|
||||||
|
|
||||||
|
# 构建确认
|
||||||
|
build-success:
|
||||||
|
name: 构建成功
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [lint, test]
|
||||||
|
if: success()
|
||||||
|
steps:
|
||||||
|
- name: 构建成功
|
||||||
|
run: echo "✅ CI 通过,可以合并"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 部署配置 (.gitea/workflows/deploy.yml)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
description: '部署环境'
|
||||||
|
required: true
|
||||||
|
default: 'staging'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- staging
|
||||||
|
- production
|
||||||
|
branch:
|
||||||
|
description: '部署分支'
|
||||||
|
required: true
|
||||||
|
default: 'develop'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
env:
|
||||||
|
DEPLOY_SERVER: root@micecola.top
|
||||||
|
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# 部署到测试环境
|
||||||
|
deploy-staging:
|
||||||
|
name: 部署测试环境
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/develop' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'staging')
|
||||||
|
environment:
|
||||||
|
name: staging
|
||||||
|
url: http://micecola.top:8080
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 SSH
|
||||||
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
|
||||||
|
- name: 部署到测试环境
|
||||||
|
run: |
|
||||||
|
ssh -o StrictHostKeyChecking=no $DEPLOY_SERVER << 'EOF'
|
||||||
|
cd /var/www/kb-web-test
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/develop
|
||||||
|
composer install --no-dev --prefer-dist
|
||||||
|
echo "Deployed at $(date)" > .deploy_time
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: 部署完成通知
|
||||||
|
run: echo "✅ 测试环境部署完成: http://micecola.top:8080"
|
||||||
|
|
||||||
|
# 部署到正式环境
|
||||||
|
deploy-production:
|
||||||
|
name: 部署正式环境
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'production')
|
||||||
|
environment:
|
||||||
|
name: production
|
||||||
|
url: https://kb.micecola.top
|
||||||
|
steps:
|
||||||
|
- name: 检出代码
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 设置 SSH
|
||||||
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
|
||||||
|
- name: 备份当前版本
|
||||||
|
run: |
|
||||||
|
ssh -o StrictHostKeyChecking=no $DEPLOY_SERVER << 'EOF'
|
||||||
|
BACKUP_DIR="/var/www/kb-web-prod-backups"
|
||||||
|
mkdir -p $BACKUP_DIR
|
||||||
|
cd /var/www/kb-web-prod
|
||||||
|
CURRENT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||||
|
tar -czf "$BACKUP_DIR/backup_${CURRENT_COMMIT}_$(date +%Y%m%d_%H%M%S).tar.gz" .
|
||||||
|
# 保留最近 10 个备份
|
||||||
|
cd $BACKUP_DIR && ls -t | tail -n +11 | xargs -r rm -f
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: 部署到正式环境
|
||||||
|
run: |
|
||||||
|
ssh -o StrictHostKeyChecking=no $DEPLOY_SERVER << 'EOF'
|
||||||
|
cd /var/www/kb-web-prod
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/main
|
||||||
|
composer install --no-dev --prefer-dist
|
||||||
|
|
||||||
|
# 记录部署信息
|
||||||
|
cat > .deploy_info << DEPLOY_EOF
|
||||||
|
环境: production
|
||||||
|
分支: main
|
||||||
|
提交: $(git rev-parse HEAD)
|
||||||
|
时间: $(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
部署者: Gitea Actions
|
||||||
|
DEPLOY_EOF
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: 部署完成通知
|
||||||
|
run: echo "✅ 正式环境部署完成: https://kb.micecola.top"
|
||||||
|
|
||||||
|
# 回滚
|
||||||
|
rollback:
|
||||||
|
name: 回滚
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment != ''
|
||||||
|
environment:
|
||||||
|
name: ${{ github.event.inputs.environment }}
|
||||||
|
steps:
|
||||||
|
- name: 设置 SSH
|
||||||
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
|
||||||
|
|
||||||
|
- name: 列出可用备份
|
||||||
|
run: |
|
||||||
|
ssh -o StrictHostKeyChecking=no $DEPLOY_SERVER << 'EOF'
|
||||||
|
echo "可用的备份:"
|
||||||
|
ls -la /var/www/kb-web-${{ github.event.inputs.environment }}-backups/
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、Runner 配置
|
||||||
|
|
||||||
|
### 方案 A: 使用 Gitea 官方 Runner(推荐)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在服务器上安装 Runner
|
||||||
|
curl -L -o gitea-runner https://gitea.com/gitea/actions/runner/releases/download/v3.4.1/act_runner-3.4.1-linux-amd64
|
||||||
|
chmod +x gitea-runner
|
||||||
|
sudo mv gitea-runner /usr/local/bin/
|
||||||
|
|
||||||
|
# 注册 Runner
|
||||||
|
gitea-runner register --instance https://your-gitea-server --token <your-token>
|
||||||
|
|
||||||
|
# 启动 Runner
|
||||||
|
gitea-runner daemon
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方案 B: 使用 GitHub Actions 兼容 Runner
|
||||||
|
|
||||||
|
如果你有 GitHub 账号,可以使用 GitHub 托管的 Runner,只需在 Gitea 中配置镜像。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、Gitea 仓库配置
|
||||||
|
|
||||||
|
### 1. 启用 Actions
|
||||||
|
|
||||||
|
仓库设置 → Actions → 启用
|
||||||
|
|
||||||
|
### 2. 配置 Secrets
|
||||||
|
|
||||||
|
| Secret 名称 | 用途 |
|
||||||
|
|-------------|------|
|
||||||
|
| `DEPLOY_KEY` | SSH 私钥(用于部署到服务器) |
|
||||||
|
| `DEPLOY_SERVER` | 部署服务器地址 |
|
||||||
|
|
||||||
|
### 3. 配置分支保护
|
||||||
|
|
||||||
|
| 分支 | 规则 |
|
||||||
|
|------|------|
|
||||||
|
| `main` | 需要 PR + 1 个 Review + CI 通过 |
|
||||||
|
| `develop` | 需要 PR + CI 通过 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、开发工作流
|
||||||
|
|
||||||
|
### 日常开发
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 创建功能分支
|
||||||
|
git checkout develop
|
||||||
|
git pull
|
||||||
|
git checkout -b feature/new-feature
|
||||||
|
|
||||||
|
# 2. 开发 + 本地测试
|
||||||
|
composer test
|
||||||
|
|
||||||
|
# 3. 提交代码
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: 新功能描述"
|
||||||
|
git push -u origin feature/new-feature
|
||||||
|
|
||||||
|
# 4. 创建 PR 到 develop
|
||||||
|
# Gitea 上操作,CI 自动运行
|
||||||
|
|
||||||
|
# 5. Review 通过后合并
|
||||||
|
# 自动部署到 Staging
|
||||||
|
|
||||||
|
# 6. 测试通过后,PR 到 main
|
||||||
|
# 手动确认后部署到 Production
|
||||||
|
```
|
||||||
|
|
||||||
|
### 紧急修复
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 从 main 创建 hotfix 分支
|
||||||
|
git checkout main
|
||||||
|
git checkout -b hotfix/urgent-fix
|
||||||
|
|
||||||
|
# 2. 修复 + 测试
|
||||||
|
git commit -m "hotfix: 紧急修复描述"
|
||||||
|
git push
|
||||||
|
|
||||||
|
# 3. PR 到 main(跳过 develop)
|
||||||
|
# 快速 Review + 合并 + 部署
|
||||||
|
|
||||||
|
# 4. 同步到 develop
|
||||||
|
git checkout develop
|
||||||
|
git merge hotfix/urgent-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、监控与告警
|
||||||
|
|
||||||
|
### 部署状态通知
|
||||||
|
|
||||||
|
可集成:
|
||||||
|
- 飞书机器人
|
||||||
|
- 企业微信
|
||||||
|
- 邮件
|
||||||
|
|
||||||
|
### 健康检查
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 部署后自动检查
|
||||||
|
curl -f https://kb.micecola.top/health || exit 1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、实施步骤
|
||||||
|
|
||||||
|
### 第一阶段:基础设施(1-2天)
|
||||||
|
|
||||||
|
1. [ ] 确认 Gitea 版本支持 Actions(需要 1.19+)
|
||||||
|
2. [ ] 在服务器上安装 Gitea Runner
|
||||||
|
3. [ ] 配置 SSH 密钥和 Secrets
|
||||||
|
|
||||||
|
### 第二阶段:CI 流程(1天)
|
||||||
|
|
||||||
|
1. [ ] 创建 `.gitea/workflows/ci.yml`
|
||||||
|
2. [ ] 配置代码检查和测试
|
||||||
|
3. [ ] 设置分支保护规则
|
||||||
|
|
||||||
|
### 第三阶段:CD 流程(1天)
|
||||||
|
|
||||||
|
1. [ ] 创建 `.gitea/workflows/deploy.yml`
|
||||||
|
2. [ ] 配置自动部署到 Staging
|
||||||
|
3. [ ] 配置手动部署到 Production
|
||||||
|
|
||||||
|
### 第四阶段:优化(持续)
|
||||||
|
|
||||||
|
1. [ ] 添加测试覆盖率报告
|
||||||
|
2. [ ] 添加部署通知
|
||||||
|
3. [ ] 添加回滚脚本
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 九、当前项目待办
|
||||||
|
|
||||||
|
- [ ] 确认 Gitea 服务器版本
|
||||||
|
- [ ] 部署 feature/article-word-count 分支到测试环境验证
|
||||||
|
- [ ] 合并到 develop,测试 CI/CD 流程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*文档版本: 1.0*
|
||||||
|
*创建时间: 2026-03-01*
|
||||||
Reference in New Issue
Block a user