ci: 添加 Forgejo Actions 工作流配置
Some checks are pending
CI / 代码检查和类型检查 (push) Waiting to run
CI / 构建应用 (push) Blocked by required conditions
CI / 安全扫描 (push) Waiting to run
Deploy / 构建并推送 Docker 镜像 (push) Waiting to run
Deploy / 部署到生产环境 (push) Blocked by required conditions
Deploy / 部署到测试环境 (push) Blocked by required conditions
Deploy / 部署通知 (push) Blocked by required conditions
Some checks are pending
CI / 代码检查和类型检查 (push) Waiting to run
CI / 构建应用 (push) Blocked by required conditions
CI / 安全扫描 (push) Waiting to run
Deploy / 构建并推送 Docker 镜像 (push) Waiting to run
Deploy / 部署到生产环境 (push) Blocked by required conditions
Deploy / 部署到测试环境 (push) Blocked by required conditions
Deploy / 部署通知 (push) Blocked by required conditions
添加 CI/CD 工作流配置文件,包括: - ci.yml: 代码检查、构建和安全扫描 - deploy.yml: 构建 Docker 镜像和部署到不同环境 - database.yml: 数据库迁移、备份和回滚操作 - README.md: 工作流使用说明和配置指南
This commit is contained in:
parent
6e50bee438
commit
1c1c82ae07
4 changed files with 500 additions and 0 deletions
129
.forgejo/workflows/README.md
Normal file
129
.forgejo/workflows/README.md
Normal file
|
@ -0,0 +1,129 @@
|
|||
# Forgejo Actions 工作流配置
|
||||
|
||||
本项目使用 Forgejo Actions 进行 CI/CD 自动化,包含以下工作流:
|
||||
|
||||
## 工作流文件
|
||||
|
||||
### 1. CI 工作流 (`ci.yml`)
|
||||
- **触发条件**: 推送到 `main`、`develop` 分支或创建 Pull Request
|
||||
- **功能**:
|
||||
- 代码风格检查 (`yarn lint`)
|
||||
- TypeScript 类型检查 (`yarn typecheck`)
|
||||
- 应用构建 (`yarn build`)
|
||||
- 安全漏洞扫描 (`yarn audit`)
|
||||
|
||||
### 2. 部署工作流 (`deploy.yml`)
|
||||
- **触发条件**: 推送到 `main` 分支、创建标签或手动触发
|
||||
- **功能**:
|
||||
- 构建并推送 Docker 镜像
|
||||
- 部署到生产环境
|
||||
- 部署到测试环境(手动触发)
|
||||
- 部署结果通知
|
||||
|
||||
### 3. 数据库工作流 (`database.yml`)
|
||||
- **触发条件**: 手动触发
|
||||
- **功能**:
|
||||
- 数据库迁移
|
||||
- 数据库备份
|
||||
- 数据库回滚
|
||||
|
||||
## 必需的环境变量和密钥
|
||||
|
||||
### Repository Secrets
|
||||
在 Forgejo 仓库设置中配置以下密钥:
|
||||
|
||||
#### Docker 相关
|
||||
```
|
||||
DOCKER_USERNAME=your_docker_username
|
||||
DOCKER_PASSWORD=your_docker_password
|
||||
```
|
||||
|
||||
#### 数据库相关
|
||||
```
|
||||
DATABASE_URL=postgresql://user:password@host:port/database
|
||||
POSTGRES_HOST=your_postgres_host
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_DB=your_database_name
|
||||
POSTGRES_USER=your_postgres_user
|
||||
POSTGRES_PASSWORD=your_postgres_password
|
||||
```
|
||||
|
||||
#### 部署相关
|
||||
```
|
||||
DEPLOY_USER=your_deploy_user
|
||||
DEPLOY_HOST=your_server_host
|
||||
DEPLOY_SSH_KEY=your_private_ssh_key
|
||||
```
|
||||
|
||||
#### 通知相关(可选)
|
||||
```
|
||||
WEBHOOK_URL=your_notification_webhook_url
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
在工作流中使用的环境变量:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
NODE_VERSION: '20'
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: windfonts
|
||||
```
|
||||
|
||||
## 环境配置
|
||||
|
||||
### Production Environment
|
||||
- 用于生产环境部署
|
||||
- 需要配置所有必需的密钥
|
||||
- 自动触发(推送到 main 分支)
|
||||
|
||||
### Staging Environment
|
||||
- 用于测试环境部署
|
||||
- 手动触发
|
||||
- 可以使用测试数据库
|
||||
|
||||
### Development Environment
|
||||
- 用于开发环境数据库操作
|
||||
- 仅用于数据库工作流
|
||||
|
||||
## 使用指南
|
||||
|
||||
### 1. 首次设置
|
||||
1. 在 Forgejo 仓库设置中添加所有必需的 Secrets
|
||||
2. 确保 Docker Registry 访问权限正确
|
||||
3. 配置服务器 SSH 访问权限
|
||||
|
||||
### 2. 日常开发
|
||||
- 推送代码到 `develop` 分支会触发 CI 检查
|
||||
- 创建 Pull Request 会自动运行 CI 流程
|
||||
- 合并到 `main` 分支会触发部署流程
|
||||
|
||||
### 3. 数据库操作
|
||||
- 在 Actions 页面手动触发数据库工作流
|
||||
- 选择操作类型(migrate/backup/rollback)
|
||||
- 选择目标环境
|
||||
|
||||
### 4. 手动部署
|
||||
- 在 Actions 页面手动触发部署工作流
|
||||
- 选择部署环境(production/staging)
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **安全性**: 确保所有敏感信息都通过 Secrets 配置,不要在代码中硬编码
|
||||
2. **权限**: 确保 Forgejo Actions 有足够的权限访问 Docker Registry 和部署服务器
|
||||
3. **备份**: 在执行数据库迁移前建议先创建备份
|
||||
4. **监控**: 关注工作流执行结果,及时处理失败的任务
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 常见问题
|
||||
1. **Docker 推送失败**: 检查 Docker 凭证是否正确
|
||||
2. **部署失败**: 检查 SSH 密钥和服务器访问权限
|
||||
3. **数据库连接失败**: 检查数据库连接字符串和网络访问
|
||||
4. **构建失败**: 检查依赖安装和环境变量配置
|
||||
|
||||
### 调试方法
|
||||
1. 查看 Actions 执行日志
|
||||
2. 检查环境变量和密钥配置
|
||||
3. 在本地环境复现问题
|
||||
4. 使用 `workflow_dispatch` 手动触发测试
|
105
.forgejo/workflows/ci.yml
Normal file
105
.forgejo/workflows/ci.yml
Normal file
|
@ -0,0 +1,105 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20'
|
||||
|
||||
jobs:
|
||||
lint-and-typecheck:
|
||||
name: 代码检查和类型检查
|
||||
runs-on: docker
|
||||
container:
|
||||
image: node:20-alpine
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 设置 Node.js 缓存
|
||||
uses: https://code.forgejo.org/actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.yarn/cache
|
||||
node_modules
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: 安装依赖
|
||||
run: |
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: 代码风格检查
|
||||
run: yarn lint
|
||||
|
||||
- name: TypeScript 类型检查
|
||||
run: yarn typecheck
|
||||
|
||||
build:
|
||||
name: 构建应用
|
||||
runs-on: docker
|
||||
container:
|
||||
image: node:20-alpine
|
||||
needs: lint-and-typecheck
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 设置 Node.js 缓存
|
||||
uses: https://code.forgejo.org/actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.yarn/cache
|
||||
node_modules
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node-
|
||||
|
||||
- name: 安装依赖
|
||||
run: |
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: 构建应用
|
||||
run: yarn build
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
- name: 上传构建产物
|
||||
uses: https://code.forgejo.org/actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-files
|
||||
path: |
|
||||
.next/
|
||||
public/
|
||||
retention-days: 7
|
||||
|
||||
security-scan:
|
||||
name: 安全扫描
|
||||
runs-on: docker
|
||||
container:
|
||||
image: node:20-alpine
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: 安装依赖
|
||||
run: |
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: 安全漏洞扫描
|
||||
run: yarn audit --audit-level moderate
|
||||
continue-on-error: true
|
134
.forgejo/workflows/database.yml
Normal file
134
.forgejo/workflows/database.yml
Normal file
|
@ -0,0 +1,134 @@
|
|||
name: Database Migration
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
action:
|
||||
description: '数据库操作'
|
||||
required: true
|
||||
default: 'migrate'
|
||||
type: choice
|
||||
options:
|
||||
- migrate
|
||||
- backup
|
||||
- rollback
|
||||
environment:
|
||||
description: '目标环境'
|
||||
required: true
|
||||
default: 'production'
|
||||
type: choice
|
||||
options:
|
||||
- production
|
||||
- staging
|
||||
- development
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20'
|
||||
|
||||
jobs:
|
||||
database-migrate:
|
||||
name: 数据库迁移
|
||||
runs-on: docker
|
||||
container:
|
||||
image: node:20-alpine
|
||||
if: github.event.inputs.action == 'migrate'
|
||||
environment: ${{ github.event.inputs.environment }}
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: 安装依赖
|
||||
run: |
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: 数据库迁移
|
||||
run: |
|
||||
echo "执行数据库迁移..."
|
||||
yarn drizzle-kit migrate
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }}
|
||||
POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }}
|
||||
POSTGRES_DB: ${{ secrets.POSTGRES_DB }}
|
||||
POSTGRES_USER: ${{ secrets.POSTGRES_USER }}
|
||||
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
|
||||
- name: 验证迁移结果
|
||||
run: |
|
||||
echo "验证数据库迁移结果..."
|
||||
# 可以添加数据库连接测试
|
||||
node -e "
|
||||
const { drizzle } = require('drizzle-orm/postgres-js');
|
||||
const postgres = require('postgres');
|
||||
const sql = postgres(process.env.DATABASE_URL);
|
||||
const db = drizzle(sql);
|
||||
console.log('数据库连接成功');
|
||||
sql.end();
|
||||
"
|
||||
|
||||
database-backup:
|
||||
name: 数据库备份
|
||||
runs-on: docker
|
||||
container:
|
||||
image: postgres:15-alpine
|
||||
if: github.event.inputs.action == 'backup'
|
||||
environment: ${{ github.event.inputs.environment }}
|
||||
|
||||
steps:
|
||||
- name: 创建数据库备份
|
||||
run: |
|
||||
echo "创建数据库备份..."
|
||||
BACKUP_FILE="backup_$(date +%Y%m%d_%H%M%S).sql"
|
||||
pg_dump $DATABASE_URL > $BACKUP_FILE
|
||||
echo "备份文件: $BACKUP_FILE"
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
|
||||
- name: 上传备份文件
|
||||
uses: https://code.forgejo.org/actions/upload-artifact@v4
|
||||
with:
|
||||
name: database-backup-${{ github.event.inputs.environment }}
|
||||
path: "*.sql"
|
||||
retention-days: 30
|
||||
|
||||
database-rollback:
|
||||
name: 数据库回滚
|
||||
runs-on: docker
|
||||
container:
|
||||
image: node:20-alpine
|
||||
if: github.event.inputs.action == 'rollback'
|
||||
environment: ${{ github.event.inputs.environment }}
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
|
||||
- name: 安装依赖
|
||||
run: |
|
||||
yarn config set registry https://registry.npmmirror.com
|
||||
yarn install --frozen-lockfile
|
||||
|
||||
- name: 数据库回滚
|
||||
run: |
|
||||
echo "执行数据库回滚..."
|
||||
# 注意:drizzle-kit 可能不直接支持回滚,需要手动处理
|
||||
echo "请手动执行回滚操作或使用备份恢复"
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
|
||||
notify-result:
|
||||
name: 通知结果
|
||||
runs-on: docker
|
||||
container:
|
||||
image: alpine:latest
|
||||
needs: [database-migrate, database-backup, database-rollback]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: 发送通知
|
||||
run: |
|
||||
echo "数据库操作完成: ${{ github.event.inputs.action }}"
|
||||
echo "环境: ${{ github.event.inputs.environment }}"
|
||||
# 可以集成通知服务
|
132
.forgejo/workflows/deploy.yml
Normal file
132
.forgejo/workflows/deploy.yml
Normal file
|
@ -0,0 +1,132 @@
|
|||
name: Deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
tags: [ 'v*' ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: '部署环境'
|
||||
required: true
|
||||
default: 'production'
|
||||
type: choice
|
||||
options:
|
||||
- production
|
||||
- staging
|
||||
|
||||
env:
|
||||
REGISTRY: docker.io
|
||||
IMAGE_NAME: windfonts
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
name: 构建并推送 Docker 镜像
|
||||
runs-on: docker
|
||||
container:
|
||||
image: docker:24-dind
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: https://code.forgejo.org/actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 设置 Docker Buildx
|
||||
uses: https://github.com/docker/setup-buildx-action@v3
|
||||
|
||||
- name: 登录到 Docker Registry
|
||||
uses: https://github.com/docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: 提取元数据
|
||||
id: meta
|
||||
uses: https://github.com/docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix={{branch}}-
|
||||
|
||||
- name: 构建并推送 Docker 镜像
|
||||
uses: https://github.com/docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
deploy-production:
|
||||
name: 部署到生产环境
|
||||
runs-on: docker
|
||||
container:
|
||||
image: alpine:latest
|
||||
needs: build-and-push
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- name: 安装必要工具
|
||||
run: |
|
||||
apk add --no-cache curl openssh-client
|
||||
|
||||
- name: 部署到服务器
|
||||
run: |
|
||||
echo "部署到生产环境..."
|
||||
# 这里可以添加具体的部署脚本
|
||||
# 例如:通过 SSH 连接到服务器并更新容器
|
||||
# ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \
|
||||
# "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main && \
|
||||
# docker-compose up -d --no-deps app"
|
||||
|
||||
- name: 健康检查
|
||||
run: |
|
||||
echo "执行健康检查..."
|
||||
# 可以添加健康检查逻辑
|
||||
# curl -f https://app.windfonts.com/api/health || exit 1
|
||||
|
||||
deploy-staging:
|
||||
name: 部署到测试环境
|
||||
runs-on: docker
|
||||
container:
|
||||
image: alpine:latest
|
||||
needs: build-and-push
|
||||
if: github.event.inputs.environment == 'staging'
|
||||
environment: staging
|
||||
|
||||
steps:
|
||||
- name: 安装必要工具
|
||||
run: |
|
||||
apk add --no-cache curl openssh-client
|
||||
|
||||
- name: 部署到测试环境
|
||||
run: |
|
||||
echo "部署到测试环境..."
|
||||
# 测试环境部署逻辑
|
||||
|
||||
notify:
|
||||
name: 部署通知
|
||||
runs-on: docker
|
||||
container:
|
||||
image: alpine:latest
|
||||
needs: [deploy-production, deploy-staging]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: 发送通知
|
||||
run: |
|
||||
echo "发送部署结果通知..."
|
||||
# 可以集成钉钉、企业微信等通知服务
|
||||
# curl -X POST ${{ secrets.WEBHOOK_URL }} \
|
||||
# -H 'Content-Type: application/json' \
|
||||
# -d '{"text": "部署完成: ${{ github.ref }}"}'
|
Loading…
Add table
Add a link
Reference in a new issue