mirror of
https://github.com/rnvm9wjdtj-bot/myaps_api.git
synced 2026-06-02 05:54:40 +00:00
9063c5522a
配置Docker Buildx的构建器名称并启用持久化,在任务结束时始终清理Buildx缓存
463 lines
16 KiB
YAML
463 lines
16 KiB
YAML
name: CI/CD Pipeline
|
||
|
||
on:
|
||
push:
|
||
branches:
|
||
- master
|
||
|
||
workflow_dispatch:
|
||
|
||
env:
|
||
TEST_DB_PASSWORD: 'test_password'
|
||
TEST_DB_NAME: 'myaps_test'
|
||
POSTGRES_PORT: '5432'
|
||
DOCKER_PLATFORMS: 'linux/amd64,linux/arm64'
|
||
SHORT_RETENTION_DAYS: '7'
|
||
RELEASE_RETENTION_DAYS: '30'
|
||
|
||
jobs:
|
||
lint-and-format:
|
||
name: 代码检查
|
||
runs-on: ubuntu-latest
|
||
if: github.repository == 'rnvm9wjdtj-bot/myaps_api'
|
||
steps:
|
||
- name: 检出代码
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 设置 Python 3.12
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: '3.12'
|
||
|
||
- name: 安装 lint 工具
|
||
run: |
|
||
python -m pip install --upgrade pip
|
||
pip install black isort ruff mypy
|
||
|
||
- name: 使用 Black 检查代码格式
|
||
run: |
|
||
echo "⚠️ 注意:项目未配置正式lint工具,此检查仅作参考"
|
||
black --check --diff . || echo "Black检查失败,请考虑格式化代码"
|
||
continue-on-error: true
|
||
|
||
- name: 使用 isort 检查导入顺序
|
||
run: |
|
||
echo "⚠️ 注意:项目未配置正式lint工具,此检查仅作参考"
|
||
isort --check-only --diff . || echo "isort检查失败,请考虑调整导入顺序"
|
||
continue-on-error: true
|
||
|
||
- name: 使用 Ruff 进行代码检查
|
||
run: |
|
||
echo "⚠️ 注意:项目未配置正式lint工具,此检查仅作参考"
|
||
ruff check . || echo "Ruff检查失败,请考虑修复代码质量问题"
|
||
continue-on-error: true
|
||
|
||
build-and-test:
|
||
name: 构建与测试
|
||
runs-on: ubuntu-latest
|
||
needs: lint-and-format
|
||
if: github.repository == 'rnvm9wjdtj-bot/myaps_api'
|
||
|
||
services:
|
||
postgres:
|
||
image: postgres:15
|
||
env:
|
||
POSTGRES_PASSWORD: test_password
|
||
POSTGRES_DB: myaps_test
|
||
ports:
|
||
- 5432:5432
|
||
options: >-
|
||
--health-cmd pg_isready
|
||
--health-interval 10s
|
||
--health-timeout 5s
|
||
--health-retries 5
|
||
|
||
redis:
|
||
image: redis:7
|
||
ports:
|
||
- 6379:6379
|
||
options: >-
|
||
--health-cmd "redis-cli ping"
|
||
--health-interval 10s
|
||
--health-timeout 5s
|
||
--health-retries 5
|
||
|
||
steps:
|
||
- name: 检出代码
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 设置 Python 3.12
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: '3.12'
|
||
cache: 'pip'
|
||
|
||
- name: 安装依赖
|
||
run: |
|
||
python -m pip install --upgrade pip
|
||
pip install -r requirements.txt
|
||
pip install pytest pytest-asyncio pytest-cov
|
||
|
||
- name: 创建环境变量文件
|
||
run: |
|
||
cat > .env << EOF
|
||
#################################################################################
|
||
# 系统参数
|
||
#################################################################################
|
||
SERVICE_NAME=MyAPS_API
|
||
HOST=0.0.0.0
|
||
PORT=8000
|
||
IP_WHITELIST=
|
||
API_KEY=
|
||
TIMEZONE=+8
|
||
USE_LOGURU=true
|
||
|
||
#################################################################################
|
||
# 项目参数
|
||
#################################################################################
|
||
LOG_LEVEL=INFO
|
||
LOG_RETENTION=2
|
||
PROJECT_DIR=
|
||
PROJECT_JSON=dev
|
||
|
||
TURNON_BINLOG_LISTENER=false
|
||
ENABLE_BINLOG_POSITION=false
|
||
TRUNON_SCHEDULER=false
|
||
SCHEDULER_HOUR=*
|
||
SCHEDULER_MINUTE=*/5
|
||
MAX_EVENTS_BATCH_SIZE=1
|
||
MAX_EVENTS_PER_SECOND=10
|
||
|
||
#################################################################################
|
||
# 基础设施配置
|
||
#################################################################################
|
||
# Redis 配置
|
||
REDIS_HOST=127.0.0.1
|
||
REDIS_PORT=6379
|
||
REDIS_DB=0
|
||
REDIS_PASSWORD=
|
||
|
||
# PostgreSQL 数据库配置(服务自有数据库)
|
||
THIS_DB_HOST=127.0.0.1
|
||
THIS_DB_PORT=${{ env.POSTGRES_PORT }}
|
||
THIS_DB_USER=postgres
|
||
THIS_DB_PASSWORD=${{ env.TEST_DB_PASSWORD }}
|
||
THIS_DB_NAME=${{ env.TEST_DB_NAME }}
|
||
|
||
# MySQL 数据库配置(三方系统既有数据库,CI 环境无需配置)
|
||
# MYAPS_DB_HOST=
|
||
# MYAPS_DB_PORT=3306
|
||
# MYAPS_DB_USER=
|
||
# MYAPS_DB_PASSWORD=
|
||
# MYAPS_DB_SET=
|
||
# MYAPS_MAIN_DB=
|
||
|
||
#################################################################################
|
||
# 部署参数
|
||
#################################################################################
|
||
WORKERS=4
|
||
GUNICORN_BIND=127.0.0.1:8000
|
||
GUNICORN_TIMEOUT=30
|
||
APP_USER=root
|
||
APP_ROOT=/opt/myaps_api/myaps_api
|
||
EOF
|
||
|
||
- name: 检查应用能否启动
|
||
run: |
|
||
echo "检查FastAPI应用能否正常创建..."
|
||
if timeout 10s python -c "from main import app; print('✓ 应用创建成功')"; then
|
||
echo "✅ 应用启动检查通过"
|
||
else
|
||
echo "⚠️ 应用启动检查失败,但继续执行后续步骤"
|
||
fi
|
||
|
||
- name: 运行测试
|
||
run: |
|
||
echo "检查测试目录..."
|
||
if [ -d "tests" ] && [ -n "$(find tests -name '*.py' -type f)" ]; then
|
||
echo "发现测试文件,运行测试..."
|
||
pytest tests/ -v --cov=. --cov-report=xml --cov-report=html
|
||
else
|
||
echo "📝 未发现测试文件,跳过测试步骤"
|
||
echo "建议:创建tests/目录并添加测试用例"
|
||
fi
|
||
|
||
- name: 上传测试覆盖率报告
|
||
uses: actions/upload-artifact@v4
|
||
if: always()
|
||
with:
|
||
name: coverage-report
|
||
path: |
|
||
htmlcov/
|
||
coverage.xml
|
||
retention-days: ${{ env.SHORT_RETENTION_DAYS }}
|
||
|
||
security-scan:
|
||
name: 安全扫描
|
||
runs-on: ubuntu-latest
|
||
needs: lint-and-format
|
||
if: github.repository == 'rnvm9wjdtj-bot/myaps_api'
|
||
steps:
|
||
- name: 检出代码
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 设置 Python 3.12
|
||
uses: actions/setup-python@v5
|
||
with:
|
||
python-version: '3.12'
|
||
|
||
- name: 安装安全检查工具
|
||
run: |
|
||
python -m pip install --upgrade pip
|
||
pip install bandit safety
|
||
|
||
- name: 运行 Bandit 安全检查
|
||
run: |
|
||
echo "🔒 运行Bandit代码安全扫描..."
|
||
bandit -r . -f json -o bandit-report.json || echo "Bandit扫描完成(可能有警告)"
|
||
continue-on-error: true
|
||
|
||
- name: 检查依赖安全漏洞
|
||
run: |
|
||
echo "📦 检查依赖包安全漏洞..."
|
||
safety check -r requirements.txt --json || echo "Safety检查完成(可能有警告)"
|
||
continue-on-error: true
|
||
|
||
- name: 上传安全扫描报告
|
||
uses: actions/upload-artifact@v4
|
||
if: always()
|
||
with:
|
||
name: security-report
|
||
path: bandit-report.json
|
||
retention-days: ${{ env.SHORT_RETENTION_DAYS }}
|
||
|
||
build-artifacts:
|
||
name: 构建交付物
|
||
runs-on: ubuntu-latest
|
||
needs: [build-and-test, security-scan]
|
||
if: github.repository == 'rnvm9wjdtj-bot/myaps_api' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||
|
||
outputs:
|
||
image-tag: ${{ steps.meta.outputs.version }}
|
||
|
||
steps:
|
||
- name: 检出代码
|
||
uses: actions/checkout@v4
|
||
|
||
- name: 设置 Docker Buildx
|
||
uses: docker/setup-buildx-action@v3
|
||
with:
|
||
name: myaps-builder
|
||
use: true
|
||
|
||
- name: 登录镜像仓库
|
||
uses: docker/login-action@v3
|
||
with:
|
||
registry: docker.io
|
||
username: ${{ secrets.DOCKER_USERNAME }}
|
||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||
|
||
- name: 提取镜像元数据
|
||
id: meta
|
||
uses: docker/metadata-action@v5
|
||
with:
|
||
images: docker.io/${{ secrets.DOCKER_USERNAME }}/myaps-api
|
||
tags: |
|
||
type=sha,prefix=
|
||
type=ref,event=branch
|
||
type=semver,pattern={{version}},prefix=v
|
||
|
||
- name: 构建并推送镜像
|
||
uses: docker/build-push-action@v5
|
||
with:
|
||
context: .
|
||
push: true
|
||
platforms: ${{ env.DOCKER_PLATFORMS }}
|
||
tags: ${{ steps.meta.outputs.tags }}
|
||
labels: ${{ steps.meta.outputs.labels }}
|
||
cache-from: type=gha
|
||
cache-to: type=gha,mode=max
|
||
build-args: USE_ALIYUN_MIRROR=false
|
||
|
||
- name: 添加架构标签
|
||
if: startsWith(github.ref, 'refs/tags/')
|
||
env:
|
||
VERSION: ${{ steps.meta.outputs.version }}
|
||
IMAGE: docker.io/${{ secrets.DOCKER_USERNAME }}/myaps-api
|
||
run: |
|
||
echo "为版本 ${VERSION} 添加架构标签..."
|
||
MANIFEST=$(docker buildx imagetools inspect ${IMAGE}:${VERSION} --raw)
|
||
AMD64_DIGEST=$(echo "$MANIFEST" | jq -r '.manifests[] | select(.platform.architecture == "amd64") | .digest')
|
||
ARM64_DIGEST=$(echo "$MANIFEST" | jq -r '.manifests[] | select(.platform.architecture == "arm64") | .digest')
|
||
docker buildx imagetools create --tag ${IMAGE}:amd64-${VERSION} ${IMAGE}@${AMD64_DIGEST}
|
||
docker buildx imagetools create --tag ${IMAGE}:arm64-${VERSION} ${IMAGE}@${ARM64_DIGEST}
|
||
echo "✅ 架构标签创建完成: amd64-${VERSION}, arm64-${VERSION}"
|
||
|
||
- name: 生成环境变量模板
|
||
run: |
|
||
cat > .env.template << 'EOF'
|
||
#################################################################################
|
||
# MyAPS API 环境变量配置模板
|
||
# 说明:各租户部署时,复制此文件并修改相关配置
|
||
#################################################################################
|
||
|
||
#################################################################################
|
||
# 系统参数
|
||
#################################################################################
|
||
SERVICE_NAME=MyAPS_API
|
||
HOST=0.0.0.0
|
||
PORT=8000
|
||
IP_WHITELIST=
|
||
API_KEY=
|
||
TIMEZONE=+8
|
||
USE_LOGURU=true
|
||
|
||
#################################################################################
|
||
# 项目参数
|
||
#################################################################################
|
||
LOG_LEVEL=INFO
|
||
LOG_RETENTION=2
|
||
PROJECT_DIR=
|
||
PROJECT_JSON=prod
|
||
|
||
TURNON_BINLOG_LISTENER=false
|
||
ENABLE_BINLOG_POSITION=false
|
||
TRUNON_SCHEDULER=false
|
||
SCHEDULER_HOUR=*
|
||
SCHEDULER_MINUTE=*/5
|
||
MAX_EVENTS_BATCH_SIZE=1
|
||
MAX_EVENTS_PER_SECOND=10
|
||
|
||
#################################################################################
|
||
# 基础设施配置(租户需修改)
|
||
#################################################################################
|
||
# Redis 配置
|
||
REDIS_HOST=<租户 Redis 地址>
|
||
REDIS_PORT=6379
|
||
REDIS_DB=0
|
||
REDIS_PASSWORD=<租户 Redis 密码>
|
||
|
||
# PostgreSQL 数据库配置(服务自有数据库)
|
||
THIS_DB_HOST=<租户 PostgreSQL 地址>
|
||
THIS_DB_PORT=5432
|
||
THIS_DB_USER=<租户 PostgreSQL 用户>
|
||
THIS_DB_PASSWORD=<租户 PostgreSQL 密码>
|
||
THIS_DB_NAME=<租户数据库名>
|
||
|
||
# MySQL 数据库配置(三方系统既有数据库)
|
||
MYAPS_DB_HOST=<三方 MySQL 地址>
|
||
MYAPS_DB_PORT=3306
|
||
MYAPS_DB_USER=<MySQL 用户>
|
||
MYAPS_DB_PASSWORD=<MySQL 密码>
|
||
MYAPS_DB_SET=<允许操作的账套数据库列表>
|
||
MYAPS_MAIN_DB=<主账套名称>
|
||
|
||
#################################################################################
|
||
# 部署参数
|
||
#################################################################################
|
||
WORKERS=4
|
||
GUNICORN_BIND=0.0.0.0:8000
|
||
GUNICORN_TIMEOUT=30
|
||
APP_USER=root
|
||
APP_ROOT=/opt/myaps_api/myaps_api
|
||
EOF
|
||
|
||
- name: 生成部署说明文档
|
||
run: |
|
||
cat > DEPLOY.md << 'EOF'
|
||
# MyAPS API 部署指南
|
||
|
||
## 交付物
|
||
- **Docker 镜像**: `${IMAGE_NAME}:${IMAGE_TAG}`
|
||
- **支持架构**: `linux/amd64`(Intel)和 `linux/arm64`(ARM/Apple Silicon)
|
||
- **环境变量模板**: `.env.template`
|
||
|
||
## 部署步骤
|
||
|
||
### 1. 拉取镜像
|
||
```bash
|
||
docker pull ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
||
```
|
||
|
||
### 2. 准备环境变量
|
||
```bash
|
||
# 复制模板
|
||
cp .env.template .env
|
||
|
||
# 编辑配置(根据租户实际情况修改)
|
||
vim .env
|
||
```
|
||
|
||
### 3. 启动服务
|
||
```bash
|
||
docker run -d \
|
||
--name myaps-api \
|
||
--env-file .env \
|
||
-p 8000:8000 \
|
||
${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
||
```
|
||
|
||
### 4. 使用 Docker Compose(推荐)
|
||
```yaml
|
||
services:
|
||
myaps-api:
|
||
image: ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
||
env_file: .env
|
||
ports:
|
||
- "8000:8000"
|
||
restart: unless-stopped
|
||
```
|
||
|
||
## 架构说明
|
||
- 镜像已支持 `linux/amd64` 和 `linux/arm64` 双架构
|
||
- Docker 会自动根据部署机器的架构拉取对应版本
|
||
- Apple Silicon(M系列)用户无需额外配置
|
||
|
||
## 配置要点
|
||
1. 必须配置 `THIS_DB_*`(PostgreSQL)
|
||
2. 必须配置 `REDIS_*`
|
||
3. 根据需要配置 `MYAPS_DB_*`(三方 MySQL)
|
||
4. 生产环境建议设置 `LOG_LEVEL=INFO` 或 `WARNING`
|
||
EOF
|
||
|
||
# 替换占位符
|
||
sed -i "s|\${IMAGE_NAME}|${{ secrets.DOCKER_USERNAME }}/myaps-api|g" DEPLOY.md
|
||
sed -i "s|\${IMAGE_TAG}|${{ steps.meta.outputs.version }}|g" DEPLOY.md
|
||
sed -i "s|\${REGISTRY}|docker.io|g" DEPLOY.md
|
||
|
||
- name: 上传交付物
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: release-artifacts-${{ steps.meta.outputs.version }}
|
||
path: |
|
||
.env.template
|
||
DEPLOY.md
|
||
retention-days: ${{ env.RELEASE_RETENTION_DAYS }}
|
||
|
||
- name: 输出部署信息
|
||
run: |
|
||
echo "=========================================="
|
||
echo "构建完成!交付物信息:"
|
||
echo "=========================================="
|
||
echo "多架构镜像: docker.io/${{ secrets.DOCKER_USERNAME }}/myaps-api:${{ steps.meta.outputs.version }}"
|
||
echo "支持架构: linux/amd64, linux/arm64"
|
||
echo "平台标签: ${{ steps.meta.outputs.tags }}"
|
||
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||
echo "架构专属标签:"
|
||
echo " AMD64: docker.io/${{ secrets.DOCKER_USERNAME }}/myaps-api:amd64-${{ steps.meta.outputs.version }}"
|
||
echo " ARM64: docker.io/${{ secrets.DOCKER_USERNAME }}/myaps-api:arm64-${{ steps.meta.outputs.version }}"
|
||
fi
|
||
echo "=========================================="
|
||
echo "部署方式:"
|
||
echo "1. 从 GitHub Artifacts 下载 .env.template 和 DEPLOY.md"
|
||
echo "2. 按租户需求修改环境变量"
|
||
echo "3. 使用统一镜像部署,注入租户配置"
|
||
echo "=========================================="
|
||
|
||
- name: 清理 Buildx 缓存
|
||
if: always()
|
||
run: |
|
||
echo "清理 Buildx 构建缓存..."
|
||
docker buildx prune -f
|
||
echo "✅ 清理完成"
|