feat(gitea): 添加 Dockerfile 模板和 Rust 支持,优化 runner 网络配置说明
- 新增 Go、Node.js、Rust 服务的 Dockerfile 模板 - 新增 Rust 快速参考指南 - 新增 Rust 后端工作流模板 - 优化 create-runner.md,明确 host 网络模式为缓存必需条件 - 更新 gitea skill 主文档
This commit is contained in:
443
skill/gitea/rust-quick-reference.md
Normal file
443
skill/gitea/rust-quick-reference.md
Normal file
@@ -0,0 +1,443 @@
|
||||
# Rust 项目 Gitea CI/CD 快速参考
|
||||
|
||||
快速设置 Rust 项目的 CI/CD 流程。
|
||||
|
||||
## 最小化配置(3 步)
|
||||
|
||||
### 1. 创建 Dockerfile.ci
|
||||
|
||||
在项目根目录创建 `Dockerfile.ci`:
|
||||
|
||||
```dockerfile
|
||||
FROM alpine:3.21
|
||||
|
||||
RUN apk add --no-cache ca-certificates tzdata curl && \
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
|
||||
WORKDIR /app
|
||||
COPY your-binary-name .
|
||||
|
||||
ENV TZ=Asia/Shanghai
|
||||
ENV RUST_LOG=info
|
||||
|
||||
EXPOSE 9090
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD curl -sf http://localhost:9090/healthz || exit 1
|
||||
|
||||
CMD ["./your-binary-name"]
|
||||
```
|
||||
|
||||
**修改项**:
|
||||
- `your-binary-name` → 你的二进制文件名(通常和 `Cargo.toml` 中的 `name` 一致)
|
||||
- `9090` → 你的服务端口
|
||||
|
||||
### 2. 创建 workflow 文件
|
||||
|
||||
创建 `.gitea/workflows/your-service.yml`:
|
||||
|
||||
```yaml
|
||||
name: Your Service - Build & Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- '**' # 修改为实际监听路径
|
||||
tags:
|
||||
- 'v*' # 修改为实际 tag 格式
|
||||
|
||||
env:
|
||||
SERVICE_PREFIX: your-service # 修改为实际服务名
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
RUSTUP_DIST_SERVER: https://rsproxy.cn
|
||||
RUSTUP_UPDATE_ROOT: https://rsproxy.cn/rustup
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
runs-on: ubuntu-latest # 修改为你的 Runner 标签
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Rust
|
||||
run: |
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh -s -- -y
|
||||
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
||||
source "$HOME/.cargo/env"
|
||||
rustup target add x86_64-unknown-linux-musl
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cargo build --release --target x86_64-unknown-linux-musl
|
||||
cp target/x86_64-unknown-linux-musl/release/your-binary-name .
|
||||
|
||||
- name: Docker Login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ github.server_url }}
|
||||
username: ${{ vars.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.RELEASE_TOKEN }}
|
||||
|
||||
- name: Build & Push Image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.ci
|
||||
push: true
|
||||
tags: |
|
||||
${{ github.server_url }}/${{ github.repository }}:latest
|
||||
${{ github.server_url }}/${{ github.repository }}:${{ github.sha }}
|
||||
```
|
||||
|
||||
**修改项**:
|
||||
- `your-service` → 你的服务名
|
||||
- `your-binary-name` → 你的二进制文件名
|
||||
- `ubuntu-latest` → 你的 Runner 标签
|
||||
- `paths` → 触发构建的路径
|
||||
- `tags` → 触发构建的 tag 格式
|
||||
|
||||
### 3. 推送代码并打 tag
|
||||
|
||||
```bash
|
||||
git add .gitea Dockerfile.ci
|
||||
git commit -m "ci: 添加 CI/CD 配置"
|
||||
git push
|
||||
|
||||
# 触发构建
|
||||
git tag v0.1.0
|
||||
git push origin v0.1.0
|
||||
```
|
||||
|
||||
## 进阶配置
|
||||
|
||||
### 添加交叉编译支持
|
||||
|
||||
如果你的 Runner 是 ARM64,但需要构建 x86_64 镜像:
|
||||
|
||||
```yaml
|
||||
- name: Install Zig and cargo-zigbuild
|
||||
run: |
|
||||
wget -q https://ziglang.org/download/0.13.0/zig-linux-aarch64-0.13.0.tar.xz
|
||||
tar -xf zig-linux-aarch64-0.13.0.tar.xz
|
||||
mv zig-linux-aarch64-0.13.0 /opt/zig
|
||||
echo "/opt/zig" >> $GITHUB_PATH
|
||||
cargo install cargo-zigbuild
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cargo zigbuild --release --target x86_64-unknown-linux-musl
|
||||
```
|
||||
|
||||
### 添加 Rust 缓存
|
||||
|
||||
```yaml
|
||||
- name: Cache Rust dependencies
|
||||
uses: https://github.com/Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: . -> target
|
||||
cache-targets: true
|
||||
```
|
||||
|
||||
### 添加版本号注入
|
||||
|
||||
**1. 创建 `build.rs`**:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
if let Ok(git_tag) = std::env::var("GIT_TAG") {
|
||||
println!("cargo:rustc-env=GIT_TAG={}", git_tag);
|
||||
}
|
||||
println!("cargo:rerun-if-env-changed=GIT_TAG");
|
||||
}
|
||||
```
|
||||
|
||||
**2. 在 workflow 中设置环境变量**:
|
||||
|
||||
```yaml
|
||||
- name: Build
|
||||
env:
|
||||
GIT_TAG: ${{ github.ref_name }}
|
||||
run: cargo build --release
|
||||
```
|
||||
|
||||
**3. 在代码中使用**:
|
||||
|
||||
```rust
|
||||
let version = option_env!("GIT_TAG").unwrap_or("dev");
|
||||
println!("Version: {}", version);
|
||||
```
|
||||
|
||||
### 添加 Release 创建
|
||||
|
||||
```yaml
|
||||
release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-publish
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
steps:
|
||||
- name: Create Release
|
||||
run: |
|
||||
curl -X POST "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases" \
|
||||
-H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"tag_name\": \"${{ github.ref_name }}\",
|
||||
\"name\": \"Release ${{ github.ref_name }}\",
|
||||
\"body\": \"自动构建的 Release\"
|
||||
}"
|
||||
```
|
||||
|
||||
## 健康检查端点实现
|
||||
|
||||
如果你的服务还没有健康检查端点,快速添加:
|
||||
|
||||
### 使用 Axum
|
||||
|
||||
```rust
|
||||
use axum::{Router, routing::get};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let app = Router::new()
|
||||
.route("/healthz", get(|| async { "OK" }));
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:9090")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
### 使用 Actix-web
|
||||
|
||||
```rust
|
||||
use actix_web::{web, App, HttpServer, HttpResponse};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.route("/healthz", web::get().to(|| async { HttpResponse::Ok().body("OK") }))
|
||||
})
|
||||
.bind("0.0.0.0:9090")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
```
|
||||
|
||||
### 使用 Rocket
|
||||
|
||||
```rust
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
#[get("/healthz")]
|
||||
fn healthz() -> &'static str {
|
||||
"OK"
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
rocket::build().mount("/", routes![healthz])
|
||||
}
|
||||
```
|
||||
|
||||
## Cargo.toml 优化配置
|
||||
|
||||
```toml
|
||||
[profile.release]
|
||||
opt-level = 3 # 最高优化级别
|
||||
lto = true # 链接时优化
|
||||
codegen-units = 1 # 单个代码生成单元
|
||||
strip = true # 去除符号表
|
||||
panic = 'abort' # panic 时直接退出
|
||||
```
|
||||
|
||||
## .dockerignore 示例
|
||||
|
||||
创建 `.dockerignore` 减小构建上下文:
|
||||
|
||||
```
|
||||
target/
|
||||
.git/
|
||||
.gitignore
|
||||
*.md
|
||||
tests/
|
||||
benches/
|
||||
examples/
|
||||
.github/
|
||||
.gitea/workflows/
|
||||
Dockerfile*
|
||||
docker-compose.yml
|
||||
```
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
### 在 workflow 中
|
||||
|
||||
```yaml
|
||||
env:
|
||||
RUST_LOG: info # 日志级别
|
||||
CONFIG_FILE: production.yaml # 配置文件
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }} # 数据库连接
|
||||
```
|
||||
|
||||
### 在 Dockerfile 中
|
||||
|
||||
```dockerfile
|
||||
ENV RUST_LOG=info
|
||||
ENV CONFIG_FILE=production.yaml
|
||||
```
|
||||
|
||||
### 在运行时
|
||||
|
||||
```bash
|
||||
docker run -e RUST_LOG=debug -e CONFIG_FILE=custom.yaml your-image
|
||||
```
|
||||
|
||||
## 常见 Runner 标签
|
||||
|
||||
| 标签 | 说明 |
|
||||
|------|------|
|
||||
| `ubuntu-latest` | Ubuntu 最新版本 |
|
||||
| `darwin-arm64` | macOS ARM64 |
|
||||
| `darwin-amd64` | macOS x86_64 |
|
||||
| `linux-amd64` | Linux x86_64 |
|
||||
| `linux-arm64` | Linux ARM64 |
|
||||
|
||||
查看可用 Runner:
|
||||
|
||||
```bash
|
||||
/gitea-list-runners
|
||||
```
|
||||
|
||||
## 触发条件参考
|
||||
|
||||
### 推送到特定分支
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
```
|
||||
|
||||
### 推送特定路径
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'Cargo.toml'
|
||||
- 'Cargo.lock'
|
||||
```
|
||||
|
||||
### 特定 tag 格式
|
||||
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*' # v1.0.0, v2.1.3
|
||||
- 'device-rs-*' # device-rs-1.0.0
|
||||
```
|
||||
|
||||
### Pull Request
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
```
|
||||
|
||||
### 定时触发
|
||||
|
||||
```yaml
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # 每天凌晨 2 点
|
||||
```
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 查看 workflow 日志
|
||||
|
||||
在 Gitea 仓库页面:
|
||||
1. 点击 "Actions"
|
||||
2. 选择对应的 workflow run
|
||||
3. 查看每个 step 的日志
|
||||
|
||||
### 本地测试构建
|
||||
|
||||
```bash
|
||||
# 测试 Rust 构建
|
||||
cargo build --release --target x86_64-unknown-linux-musl
|
||||
|
||||
# 测试 Docker 构建
|
||||
docker build -f Dockerfile.ci -t test:latest .
|
||||
|
||||
# 测试容器运行
|
||||
docker run -p 9090:9090 test:latest
|
||||
```
|
||||
|
||||
### 使用 act 本地运行 workflow
|
||||
|
||||
```bash
|
||||
# 安装 act(如果使用 Gitea Actions)
|
||||
# 注意:act 主要支持 GitHub Actions,Gitea Actions 可能有兼容性问题
|
||||
|
||||
# 列出可用的 actions
|
||||
act -l
|
||||
|
||||
# 运行特定 job
|
||||
act -j build-and-publish
|
||||
```
|
||||
|
||||
## 完整配置示例
|
||||
|
||||
参考 BMS 项目的 device-rs:
|
||||
|
||||
- Workflow: [device-rs.yml](https://git.voson.top/tianchu/bms/src/branch/main/.gitea/workflows/device-rs.yml)
|
||||
- Dockerfile: [Dockerfile.ci](https://git.voson.top/tianchu/bms/src/branch/main/device-rs/Dockerfile.ci)
|
||||
- 项目结构: [device-rs/](https://git.voson.top/tianchu/bms/src/branch/main/device-rs)
|
||||
|
||||
## 故障排查清单
|
||||
|
||||
### 构建失败
|
||||
|
||||
- [ ] 检查 Rust 版本是否满足要求
|
||||
- [ ] 检查依赖是否正确(`Cargo.lock` 是否提交)
|
||||
- [ ] 检查 musl 目标是否安装(`rustup target list --installed`)
|
||||
- [ ] 查看完整构建日志
|
||||
|
||||
### Docker 推送失败
|
||||
|
||||
- [ ] 检查 Docker Registry 地址是否正确
|
||||
- [ ] 检查 `REGISTRY_USERNAME` 变量是否设置
|
||||
- [ ] 检查 `RELEASE_TOKEN` secret 是否正确
|
||||
- [ ] 检查 Token 权限(需要 packages write 权限)
|
||||
|
||||
### 容器启动失败
|
||||
|
||||
- [ ] 检查二进制文件名是否正确
|
||||
- [ ] 检查端口是否正确
|
||||
- [ ] 检查健康检查端点是否存在
|
||||
- [ ] 查看容器日志(`docker logs <container>`)
|
||||
|
||||
### Runner 无法连接
|
||||
|
||||
- [ ] 检查 Runner 是否在运行(`/gitea-list-runners`)
|
||||
- [ ] 检查 Runner labels 是否匹配 workflow 中的 `runs-on`
|
||||
- [ ] 检查网络连接
|
||||
- [ ] 查看 Runner 日志(`~/.config/gitea/runners/<runner-name>/*.log`)
|
||||
|
||||
## 更多资源
|
||||
|
||||
- [完整 Workflow 模板](./workflow-templates/rust-backend.md)
|
||||
- [Dockerfile 模板详解](./dockerfile-templates/rust-service.md)
|
||||
- [Gitea Actions 文档](https://docs.gitea.com/usage/actions/quickstart)
|
||||
- [Rust CI 最佳实践](https://doc.rust-lang.org/cargo/guide/continuous-integration.html)
|
||||
Reference in New Issue
Block a user