- 添加完整的 Rust 后端 CI/CD 工作流模板 - 更新 Android、Go、Node.js、微信小程序工作流模板 - 优化工作流生成器配置 - 更新 Gitea skill 主文档
541 lines
14 KiB
Markdown
541 lines
14 KiB
Markdown
# 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<<EOF" >> $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 <target> # 指定目标平台
|
||
|
||
# 二进制优化
|
||
strip <binary> # 去除符号表,减小体积
|
||
```
|
||
|
||
### 缓存策略
|
||
|
||
```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 功能 |