# Rust 后端服务 Workflow 模板 适用于 Rust 后端 API 服务、微服务、CLI 工具的 CI/CD workflow。 ## 适用场景 - Rust HTTP API 服务(Axum、Actix-Web、Warp) - gRPC 微服务 - CLI 工具 - 需要构建 Docker 镜像的 Rust 项目 - 跨平台编译需求 ## 环境要求 | 依赖 | Runner 要求 | |------|------------| | Rust 1.75+ | Runner 主机已安装 | | Docker | Runner 主机已安装 | | Cross 编译工具 | 可选,用于多平台构建 | ## Workflow 骨架模板 ```yaml name: API Hub CI/CD on: push: branches: [main] tags: ['v*'] pull_request: branches: [main] env: CARGO_TERM_COLOR: always SERVICE_NAME: api-hub jobs: test: name: 测试 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 安装 Rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable components: rustfmt, clippy - name: 缓存 Cargo 依赖 uses: actions/cache@v4 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: 检查代码格式 run: cargo fmt -- --check - name: 运行 Clippy 检查 run: cargo clippy -- -D warnings - name: 运行测试 run: cargo test --verbose - name: 构建 run: cargo build --release --verbose build-docker: name: 构建 Docker 镜像 needs: test if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 设置 Docker Buildx uses: docker/setup-buildx-action@v3 - name: 登录容器仓库 uses: docker/login-action@v3 with: registry: ${{ env.registry }} username: ${{ github.actor }} password: ${{ secrets.REGISTRY_TOKEN }} - name: 提取元数据 id: meta uses: docker/metadata-action@v5 with: images: ${{ env.registry }}/${{ github.repository }}/${{ env.SERVICE_NAME }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix=,suffix=,format=short - name: 构建并推送镜像 uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max health-check: name: 健康检查 needs: build-docker if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 运行健康检查测试 run: | # 启动服务 docker run -d --name api-hub-test -p 8080:8080 ${{ env.registry }}/${{ github.repository }}/${{ env.SERVICE_NAME }}:main # 等待服务启动 sleep 10 # 健康检查 echo "检查健康端点..." curl -f http://localhost:8080/health || exit 1 # 就绪检查 echo "检查就绪端点..." curl -f http://localhost:8080/ready || exit 1 # 存活检查 echo "检查存活端点..." curl -f http://localhost:8080/live || exit 1 echo "所有健康检查通过!" # 清理 docker stop api-hub-test docker rm api-hub-test release: name: 创建发布 needs: test if: startsWith(github.ref, 'refs/tags/v') runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 安装 Rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: stable targets: x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl - name: 构建 Release 二进制文件 run: | # Linux GNU 版本 cargo build --release --target x86_64-unknown-linux-gnu strip target/x86_64-unknown-linux-gnu/release/${{ env.SERVICE_NAME }} tar czf ${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-gnu.tar.gz \ -C target/x86_64-unknown-linux-gnu/release ${{ env.SERVICE_NAME }} # Linux MUSL 版本 (静态链接) cargo build --release --target x86_64-unknown-linux-musl strip target/x86_64-unknown-linux-musl/release/${{ env.SERVICE_NAME }} tar czf ${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-musl.tar.gz \ -C target/x86_64-unknown-linux-musl/release ${{ env.SERVICE_NAME }} - name: 生成 Changelog id: changelog run: | echo "CHANGELOG<> $GITHUB_OUTPUT if [ -f CHANGELOG.md ]; then # 提取当前版本的变更日志 awk '/^## \[${{ github.ref_name }}\]/{flag=1;next} /^## \[/{flag=0} flag' CHANGELOG.md || echo "查看完整变更日志:CHANGELOG.md" else echo "## ${{ github.ref_name }}" echo "" echo "### 变更内容" echo "- 发布版本 ${{ github.ref_name }}" echo "" echo "### 下载" echo "- \`${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-gnu.tar.gz\`: 标准 Linux 版本" echo "- \`${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-musl.tar.gz\`: 静态链接版本(推荐用于容器)" echo "" echo "### 部署" echo "\`\`\`bash" echo "# 下载并解压" echo "wget ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ github.ref_name }}/${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-musl.tar.gz" echo "tar xzf ${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-musl.tar.gz" echo "" echo "# 运行服务" echo "./${{ env.SERVICE_NAME }}" echo "\`\`\`" fi EOF - name: 创建 Release uses: softprops/action-gh-release@v1 with: name: ${{ env.SERVICE_NAME }} ${{ github.ref_name }} body: ${{ steps.changelog.outputs.CHANGELOG }} files: | ${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-gnu.tar.gz ${{ env.SERVICE_NAME }}-${{ github.ref_name }}-x86_64-linux-musl.tar.gz draft: false prerelease: ${{ contains(github.ref_name, '-') }} notify: name: 发送通知 needs: [test, build-docker, release] if: always() runs-on: ubuntu-latest steps: - name: 发送构建通知 run: | TEST_STATUS="${{ needs.test.result }}" BUILD_STATUS="${{ needs.build-docker.result }}" RELEASE_STATUS="${{ needs.release.result }}" if [[ "$TEST_STATUS" == "success" && ("$BUILD_STATUS" == "success" || "$BUILD_STATUS" == "skipped") && ("$RELEASE_STATUS" == "success" || "$RELEASE_STATUS" == "skipped") ]]; then STATUS="成功" else STATUS="失败" fi curl -X POST ${{ vars.WEBHOOK_URL }} \ -H "Content-Type: application/json" \ -d '{ "repository": "${{ github.repository }}", "ref": "${{ github.ref }}", "commit": "${{ github.sha }}", "status": "'"$STATUS"'", "workflow": "${{ github.workflow }}", "actor": "${{ github.actor }}", "test_result": "'"$TEST_STATUS"'", "build_result": "'"$BUILD_STATUS"'", "release_result": "'"$RELEASE_STATUS"'" }' || true ``` --- ## Dockerfile 模板 ### 多阶段构建(推荐) ```dockerfile # 构建阶段 FROM rust:1.75-slim as builder # 安装构建依赖 RUN apt-get update && apt-get install -y \ pkg-config \ libssl-dev \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # 复制依赖文件,利用 Docker 缓存 COPY Cargo.toml Cargo.lock ./ # 创建虚拟源文件用于编译依赖 RUN mkdir src && echo "fn main() {}" > src/main.rs RUN cargo build --release && rm -rf src # 复制实际源码并重新编译 COPY src ./src RUN touch src/main.rs && cargo build --release # 运行阶段 FROM debian:bookworm-slim # 安装运行时依赖 RUN apt-get update && apt-get install -y \ ca-certificates \ curl \ && rm -rf /var/lib/apt/lists/* WORKDIR /app # 复制二进制文件 COPY --from=builder /app/target/release/api-hub /app/api-hub # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD curl --fail http://localhost:8080/health || exit 1 EXPOSE 8080 ENTRYPOINT ["/app/api-hub"] ``` ### 简单构建 ```dockerfile FROM alpine:latest # 安装运行时依赖 RUN apk add --no-cache ca-certificates curl tzdata # 设置时区 ENV TZ=Asia/Shanghai WORKDIR /app # 复制预编译的二进制文件 COPY api-hub /app/api-hub RUN chmod +x /app/api-hub # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD curl --fail http://localhost:8080/health || exit 1 EXPOSE 8080 ENTRYPOINT ["/app/api-hub"] ``` --- ## 构建参数说明 ### 编译优化 ```bash # 交叉编译目标 x86_64-unknown-linux-gnu # 标准 Linux (glibc) x86_64-unknown-linux-musl # 静态链接 Linux # 编译标志 --release # 发布模式优化 --target # 指定目标平台 # 二进制优化 strip # 去除符号表,减小体积 ``` ### 缓存策略 ```yaml # Cargo 缓存路径 ~/.cargo/bin/ # 已安装的 cargo 工具 ~/.cargo/registry/index/ # 注册表索引 ~/.cargo/registry/cache/ # 下载的 crate 缓存 ~/.cargo/git/db/ # Git 依赖缓存 target/ # 编译输出缓存 # 缓存 Key 计算 key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} ``` --- ## Variables 和 Secrets 配置 ### Required Variables | Variable | 说明 | 示例 | |----------|------|------| | `WEBHOOK_URL` | 构建通知 Webhook | `https://api.example.com/webhook` | ### Required Secrets | Secret | 说明 | |--------|------| | `REGISTRY_TOKEN` | Container Registry 访问令牌 | ### Optional Secrets | Secret | 说明 | |--------|------| | 无 | 基础模板无额外 secrets | **注意**:Gitea Actions 不允许变量和密钥名称以 `GITEA_` 或 `GITHUB_` 开头 --- ## 触发条件 ### 标准触发 ```yaml on: push: branches: [main] # 仅 main 分支 tags: ['v*'] # 版本标签 pull_request: branches: [main] # PR 到 main ``` ### 路径过滤(单体仓库) ```yaml on: push: branches: [main] paths: - 'services/api-hub/**' # 仅特定服务目录变更 - 'shared/**' # 共享代码变更 - 'Cargo.toml' # 根依赖变更 ``` --- ## 发布流程 ### Release 创建 - **触发**:推送 `v*` 格式的 tag(如 `v1.0.0`) - **构建物**: - `{SERVICE_NAME}-{version}-x86_64-linux-gnu.tar.gz` - `{SERVICE_NAME}-{version}-x86_64-linux-musl.tar.gz` - **Changelog**: 自动从 `CHANGELOG.md` 提取或生成默认内容 ### 版本发布操作 ```bash # 创建并推送版本标签 git tag v1.0.0 git push origin v1.0.0 # 预发布版本(标记为 prerelease) git tag v1.0.0-beta.1 git push origin v1.0.0-beta.1 ``` --- ## 常见构建工具集成 根据项目使用的工具,在构建步骤中添加相应命令: | 框架/工具 | 命令 | |----------|------| | SeaORM | `sea-orm-cli generate entity -o src/entity` | | Diesel | `diesel migration run && diesel print-schema > src/schema.rs` | | tonic (gRPC) | `cargo build` (build.rs 自动处理) | | utoipa (OpenAPI) | 代码生成,无需额外命令 | | cargo-make | `cargo make ci` | --- ## Dockerfile.ci 模板(可选) 如果需要在 CI 中使用自定义 Dockerfile: ```dockerfile # 用于 CI 的轻量构建 FROM rust:1.75-alpine as builder RUN apk add --no-cache musl-dev openssl-dev WORKDIR /app COPY . . RUN cargo build --release --target x86_64-unknown-linux-musl # 运行时镜像 FROM alpine:latest RUN apk add --no-cache ca-certificates curl WORKDIR /app COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/api-hub . EXPOSE 8080 HEALTHCHECK CMD curl --fail http://localhost:8080/health || exit 1 ENTRYPOINT ["./api-hub"] ``` --- ## 使用步骤 1. **复制模板**到 `.gitea/workflows/{service}.yml` 2. **修改变量**: - `SERVICE_NAME`: 服务名称 - 触发条件中的分支和标签模式 3. **配置 Secrets**: - `REGISTRY_TOKEN`: Container registry 访问令牌 4. **可选配置**: - 健康检查端点和端口 - 构建目标平台 - Webhook 通知 URL 5. **推送代码**触发 workflow --- ## 高级功能 ### 多平台构建 ```yaml - name: 安装交叉编译工具 run: | rustup target add x86_64-unknown-linux-musl rustup target add aarch64-unknown-linux-musl # cargo install cross - name: 构建多平台二进制 run: | # x86_64 GNU cargo build --release --target x86_64-unknown-linux-gnu # x86_64 MUSL cargo build --release --target x86_64-unknown-linux-musl # ARM64 MUSL (使用 cross) # cross build --release --target aarch64-unknown-linux-musl ``` ### 集成测试 ```yaml - name: 集成测试 run: | # 启动依赖服务(数据库、Redis 等) docker compose up -d postgres redis # 等待服务就绪 sleep 5 # 运行集成测试 cargo test --test integration_tests # 清理 docker compose down ``` ### 安全扫描 ```yaml - name: 安全审计 run: | cargo install cargo-audit cargo audit ``` --- ## 版本 - **模板版本**: 1.0 - **最后更新**: 2026-01-29 - **基于项目**: API Hub - **优化重点**: 变量命名规范、简化配置、增强 Release 功能