feat(gitea): 新增 Rust 后端工作流模板并更新现有模板
- 添加完整的 Rust 后端 CI/CD 工作流模板 - 更新 Android、Go、Node.js、微信小程序工作流模板 - 优化工作流生成器配置 - 更新 Gitea skill 主文档
This commit is contained in:
@@ -121,7 +121,13 @@ C:\Users\YourUsername\.config\gitea\
|
|||||||
- 可在所有个人仓库的 Actions workflow 中使用
|
- 可在所有个人仓库的 Actions workflow 中使用
|
||||||
- 使用方式:`${{ vars.USERNAME }}`、`${{ vars.WEBHOOK_URL }}`
|
- 使用方式:`${{ vars.USERNAME }}`、`${{ vars.WEBHOOK_URL }}`
|
||||||
|
|
||||||
**重要**:Gitea 不允许 variable 名称以 `GITEA_` 或 `GITHUB_` 开头
|
**重要:变量命名规范**
|
||||||
|
- Gitea Actions 不允许变量和密钥名称以 `GITEA_` 或 `GITHUB_` 开头
|
||||||
|
- 推荐命名:
|
||||||
|
- `REGISTRY_TOKEN`(替代 `GITEA_TOKEN`)
|
||||||
|
- `REGISTRY_URL` → 使用内置 `${{ env.registry }}`
|
||||||
|
- `USERNAME` → 使用内置 `${{ github.actor }}`
|
||||||
|
- `WEBHOOK_URL`(已自动注册为 variable)
|
||||||
|
|
||||||
详见:[环境配置指南](./setup-guide.md)
|
详见:[环境配置指南](./setup-guide.md)
|
||||||
|
|
||||||
@@ -387,6 +393,7 @@ Runner 信息
|
|||||||
|
|
||||||
| 类型 | 模板文档 | 适用场景 |
|
| 类型 | 模板文档 | 适用场景 |
|
||||||
|------|---------|---------|
|
|------|---------|---------|
|
||||||
|
| **Rust 后端** | [rust-backend.md](./workflow-templates/rust-backend.md) | **Rust API 服务、微服务、CLI 工具** |
|
||||||
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
|
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
|
||||||
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
|
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
|
||||||
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
|
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
|
||||||
@@ -408,6 +415,38 @@ AI 会自动:
|
|||||||
|
|
||||||
详见:[API 参考](./api-reference.md)
|
详见:[API 参考](./api-reference.md)
|
||||||
|
|
||||||
|
## 变量命名规范
|
||||||
|
|
||||||
|
**⚠️ 重要限制**:Gitea Actions 不允许变量和密钥名称以 `GITEA_` 或 `GITHUB_` 开头
|
||||||
|
|
||||||
|
### 推荐命名约定
|
||||||
|
|
||||||
|
| 原名称 | 推荐替代 | 说明 |
|
||||||
|
|--------|----------|------|
|
||||||
|
| `GITEA_TOKEN` | `REGISTRY_TOKEN` | Container registry 访问令牌 |
|
||||||
|
| `GITEA_URL` | `${{ env.registry }}` | 使用内置变量自动获取当前实例地址 |
|
||||||
|
| `GITEA_USERNAME` | `${{ github.actor }}` | 使用内置变量获取当前用户 |
|
||||||
|
| `GITHUB_TOKEN` | `RELEASE_TOKEN` | 用于创建 Release 的 API 令牌 |
|
||||||
|
|
||||||
|
### 内置变量利用
|
||||||
|
|
||||||
|
Gitea Actions 提供的内置变量(推荐优先使用):
|
||||||
|
- `${{ env.registry }}`: 当前 Gitea 实例的 registry 地址
|
||||||
|
- `${{ github.actor }}`: 触发 workflow 的用户名
|
||||||
|
- `${{ github.repository }}`: 当前仓库的 `owner/repo` 格式
|
||||||
|
- `${{ github.server_url }}`: Gitea 实例的基础 URL
|
||||||
|
|
||||||
|
### Variables vs Secrets
|
||||||
|
|
||||||
|
**Variables**(明文存储,适用于非敏感配置):
|
||||||
|
- `USERNAME`: 用户名(自动从配置同步)
|
||||||
|
- `WEBHOOK_URL`: 通知 webhook 地址
|
||||||
|
- `DEFAULT_ORG`: 默认组织名
|
||||||
|
|
||||||
|
**Secrets**(加密存储,适用于敏感信息):
|
||||||
|
- `REGISTRY_TOKEN`: Container registry 密码
|
||||||
|
- `RELEASE_TOKEN`: Release 创建 API 令牌
|
||||||
|
|
||||||
## 安全性
|
## 安全性
|
||||||
|
|
||||||
- 配置文件权限:`600`(仅所有者可读写)
|
- 配置文件权限:`600`(仅所有者可读写)
|
||||||
@@ -427,9 +466,9 @@ AI 会自动:
|
|||||||
|
|
||||||
## 版本
|
## 版本
|
||||||
|
|
||||||
- **Skill Version**: 1.2
|
- **Skill Version**: 1.3
|
||||||
- **Last Updated**: 2026-01-28
|
- **Last Updated**: 2026-01-29
|
||||||
- **整合内容**: gitea-runner + gitea-workflow + 增强仓库管理 + SSH 密钥管理
|
- **整合内容**: gitea-runner + gitea-workflow + 增强仓库管理 + SSH 密钥管理 + Rust 模板
|
||||||
- **主要改进**:
|
- **主要改进**:
|
||||||
- 仓库创建智能解析(优先使用指定组织)
|
- 仓库创建智能解析(优先使用指定组织)
|
||||||
- **简化验证**:默认假设组织存在,API失败时提示创建组织
|
- **简化验证**:默认假设组织存在,API失败时提示创建组织
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Gitea Actions 使用 GitHub Actions 兼容的 workflow 语法,定义在 `.gite
|
|||||||
|
|
||||||
| 类型 | 模板文档 | 适用场景 |
|
| 类型 | 模板文档 | 适用场景 |
|
||||||
|------|---------|---------|
|
|------|---------|---------|
|
||||||
|
| **Rust 后端** | [rust-backend.md](./workflow-templates/rust-backend.md) | **Rust API 服务、微服务、CLI 工具** |
|
||||||
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
|
| Go 后端 | [go-backend.md](./workflow-templates/go-backend.md) | API 服务、微服务、CLI 工具 |
|
||||||
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
|
| Node.js 前端 | [nodejs-frontend.md](./workflow-templates/nodejs-frontend.md) | React/Vue/Vite/Next.js |
|
||||||
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
|
| Android 应用 | [android-app.md](./workflow-templates/android-app.md) | Kotlin/Java/Jetpack Compose |
|
||||||
@@ -28,6 +29,11 @@ Gitea Actions 使用 GitHub Actions 兼容的 workflow 语法,定义在 `.gite
|
|||||||
当用户说"为我的项目生成 workflow"时,AI 会自动检测项目类型:
|
当用户说"为我的项目生成 workflow"时,AI 会自动检测项目类型:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Rust 项目特征
|
||||||
|
if [ -f "Cargo.toml" ] || [ -f "src/main.rs" ]; then
|
||||||
|
project_type="rust"
|
||||||
|
fi
|
||||||
|
|
||||||
# Go 项目特征
|
# Go 项目特征
|
||||||
if [ -f "go.mod" ] || [ -f "main.go" ]; then
|
if [ -f "go.mod" ] || [ -f "main.go" ]; then
|
||||||
project_type="go"
|
project_type="go"
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
VERSION_NAME: ${{ needs.build.outputs.version_name }}
|
VERSION_NAME: ${{ needs.build.outputs.version_name }}
|
||||||
APK_NAME: ${{ needs.build.outputs.apk_name }}
|
APK_NAME: ${{ needs.build.outputs.apk_name }}
|
||||||
run: |
|
run: |
|
||||||
@@ -221,20 +221,20 @@ jobs:
|
|||||||
|
|
||||||
# 创建 Release
|
# 创建 Release
|
||||||
release_id=$(curl -s -X POST \
|
release_id=$(curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag} (v${VERSION_NAME})\"}" \
|
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag} (v${VERSION_NAME})\"}" \
|
||||||
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
||||||
|
|
||||||
# 上传 APK
|
# 上传 APK
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${APK_NAME}.apk" \
|
-F "attachment=@dist/${APK_NAME}.apk" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
|
|
||||||
# 上传校验和
|
# 上传校验和
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${APK_NAME}.apk.sha256" \
|
-F "attachment=@dist/${APK_NAME}.apk.sha256" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ jobs:
|
|||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.registry }}
|
registry: ${{ env.registry }}
|
||||||
username: ${{ vars.REGISTRY_USERNAME }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Docker - Setup Buildx
|
- name: Docker - Setup Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
@@ -183,9 +183,9 @@ jobs:
|
|||||||
name: ${{ env.SERVICE_PREFIX }}-binary-linux-amd64
|
name: ${{ env.SERVICE_PREFIX }}-binary-linux-amd64
|
||||||
path: dist
|
path: dist
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
BINARY_NAME: ${{ needs.build-and-publish.outputs.binary_name }}
|
BINARY_NAME: ${{ needs.build-and-publish.outputs.binary_name }}
|
||||||
run: |
|
run: |
|
||||||
git_tag=$(git describe --tags --abbrev=0)
|
git_tag=$(git describe --tags --abbrev=0)
|
||||||
@@ -199,20 +199,20 @@ jobs:
|
|||||||
|
|
||||||
# 创建 Release
|
# 创建 Release
|
||||||
release_id=$(curl -s -X POST \
|
release_id=$(curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
|
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
|
||||||
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
||||||
|
|
||||||
# 上传二进制文件
|
# 上传二进制文件
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${BINARY_NAME}" \
|
-F "attachment=@dist/${BINARY_NAME}" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
|
|
||||||
# 上传校验和
|
# 上传校验和
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${BINARY_NAME}.sha256" \
|
-F "attachment=@dist/${BINARY_NAME}.sha256" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
```
|
```
|
||||||
@@ -284,7 +284,7 @@ GOARCH=amd64 # 目标架构
|
|||||||
|
|
||||||
| Secret | 用途 |
|
| Secret | 用途 |
|
||||||
|--------|------|
|
|--------|------|
|
||||||
| `REGISTRY_PASSWORD` | Docker Registry 密码 |
|
| `REGISTRY_TOKEN` | Docker Registry 密码 |
|
||||||
| `RELEASE_TOKEN` | Gitea API 令牌(创建 Release) |
|
| `RELEASE_TOKEN` | Gitea API 令牌(创建 Release) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ jobs:
|
|||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.registry }}
|
registry: ${{ env.registry }}
|
||||||
username: ${{ vars.REGISTRY_USERNAME }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Docker - Setup Buildx
|
- name: Docker - Setup Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
@@ -183,7 +183,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
git_tag=$(git describe --tags --abbrev=0)
|
git_tag=$(git describe --tags --abbrev=0)
|
||||||
api_url="${{ github.server_url }}/api/v1"
|
api_url="${{ github.server_url }}/api/v1"
|
||||||
@@ -197,14 +197,14 @@ jobs:
|
|||||||
|
|
||||||
# 创建 Release
|
# 创建 Release
|
||||||
release_id=$(curl -s -X POST \
|
release_id=$(curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
|
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
|
||||||
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
||||||
|
|
||||||
# 上传附件
|
# 上传附件
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${{ env.SERVICE_PREFIX }}-dist.zip" \
|
-F "attachment=@dist/${{ env.SERVICE_PREFIX }}-dist.zip" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
```
|
```
|
||||||
@@ -357,7 +357,7 @@ env:
|
|||||||
|
|
||||||
| Secret | 用途 |
|
| Secret | 用途 |
|
||||||
|--------|------|
|
|--------|------|
|
||||||
| `REGISTRY_PASSWORD` | Docker Registry 密码 |
|
| `REGISTRY_TOKEN` | Docker Registry 密码 |
|
||||||
| `RELEASE_TOKEN` | Gitea API 令牌(创建 Release) |
|
| `RELEASE_TOKEN` | Gitea API 令牌(创建 Release) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
541
skill/gitea/workflow-templates/rust-backend.md
Normal file
541
skill/gitea/workflow-templates/rust-backend.md
Normal file
@@ -0,0 +1,541 @@
|
|||||||
|
# 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 功能
|
||||||
@@ -243,7 +243,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
VERSION: ${{ needs.build-and-upload.outputs.version }}
|
VERSION: ${{ needs.build-and-upload.outputs.version }}
|
||||||
run: |
|
run: |
|
||||||
git_tag=$(git describe --tags --abbrev=0)
|
git_tag=$(git describe --tags --abbrev=0)
|
||||||
@@ -252,14 +252,14 @@ jobs:
|
|||||||
|
|
||||||
# 创建 Release
|
# 创建 Release
|
||||||
release_id=$(curl -s -X POST \
|
release_id=$(curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag} (v${VERSION})\"}" \
|
-d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag} (v${VERSION})\"}" \
|
||||||
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
"${api_url}/repos/${repo}/releases" | jq -r '.id')
|
||||||
|
|
||||||
# 上传源码包
|
# 上传源码包
|
||||||
curl -s -X POST \
|
curl -s -X POST \
|
||||||
-H "Authorization: token $GITEA_TOKEN" \
|
-H "Authorization: token $RELEASE_TOKEN" \
|
||||||
-F "attachment=@dist/${{ env.SERVICE_PREFIX }}-${VERSION}-source.tar.gz" \
|
-F "attachment=@dist/${{ env.SERVICE_PREFIX }}-${VERSION}-source.tar.gz" \
|
||||||
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
"${api_url}/repos/${repo}/releases/${release_id}/assets"
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user