Files
admin 9063c5522a ci(github actions): 配置buildx并添加缓存清理步骤
配置Docker Buildx的构建器名称并启用持久化,在任务结束时始终清理Buildx缓存
2026-06-01 20:39:10 +08:00

463 lines
16 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 SiliconM系列)用户无需额外配置
## 配置要点
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 "✅ 清理完成"