Files
Voson 5a05d5ab53 chore: 重构 OpenCode 命令和技能文档体系
- 新增:统一的 git 命令文档(add/commit/push/pull 等)
- 新增:整合的 Gitea 技能文档(API、运行器、工作流等)
- 新增:工作流模板(Android、Go、Node.js 等)
- 移除:已弃用的旧命令脚本和发布脚本
- 改进:.gitignore 添加敏感文件保护规则
- 改进:AGENTS.md 完善了开发规范和示例

此次重组统一了命令和技能的文档结构,便于后续维护和扩展。
2026-01-13 00:27:21 +08:00

9.1 KiB
Raw Permalink Blame History

Go 后端服务 Workflow 模板

适用于 Go 后端 API 服务、微服务、CLI 工具的 CI/CD workflow。

适用场景

  • Go HTTP API 服务
  • gRPC 微服务
  • CLI 工具
  • 需要构建 Docker 镜像的 Go 项目

环境要求

依赖 Runner 要求
Go 1.21+ Runner 主机已安装
Docker Runner 主机已安装

Workflow 骨架模板

name: Go Backend - Build & Publish

on:
  push:
    paths:
      - 'your-service/**'                   # 修改为实际目录
      - '.gitea/workflows/your-service.yml'
    tags:
      - 'your-service-*'                    # 修改为实际 tag 前缀

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  SERVICE_PREFIX: your-service              # 修改为实际服务名
  SERVICE_DIR: your-service                 # 修改为实际目录名
  GOPROXY: https://goproxy.cn,direct

jobs:
  build-and-publish:
    name: Build & Publish
    runs-on: darwin-arm64
    permissions:
      contents: read
      packages: write
    
    outputs:
      binary_name: ${{ steps.vars.outputs.binary_name }}
      git_tag: ${{ steps.vars.outputs.git_tag }}
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Verify Go environment
        run: |
          go version
          echo "GOPATH=$(go env GOPATH)"

      - name: Get go-hashfiles
        id: hash-go
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          HASH=$(sha256sum go.mod go.sum | sha256sum | awk '{print $1}' | head -c 16)
          echo "hash=${HASH}" >> "$GITHUB_OUTPUT"

      - name: Cache Go modules
        uses: https://github.com/actions/cache@v3
        with:
          path: |
            ~/go/pkg/mod
            ~/.cache/go-build
          key: go-${{ env.SERVICE_PREFIX }}-${{ steps.hash-go.outputs.hash }}
          restore-keys: go-${{ env.SERVICE_PREFIX }}-

      - name: Set variables
        id: vars
        run: |
          git_tag=$(git describe --tags --abbrev=0 --always)
          registry=$(echo ${{ github.server_url }} | cut -d '/' -f 3)
          binary_name="${{ github.event.repository.name }}-${{ env.SERVICE_PREFIX }}"
          image_repo="${{ github.event.repository.name }}"
          
          {
            echo "git_tag=${git_tag}"
            echo "registry=${registry}"
            echo "binary_name=${binary_name}"
            echo "image_repo=${image_repo}"
            echo "latest_tag=${{ env.SERVICE_PREFIX }}-latest"
          } >> $GITHUB_ENV
          
          echo "binary_name=${binary_name}" >> $GITHUB_OUTPUT
          echo "git_tag=${git_tag}" >> $GITHUB_OUTPUT

      - name: Build
        working-directory: ${{ env.SERVICE_DIR }}
        env:
          CGO_ENABLED: 0
          GOOS: linux
          GOARCH: amd64
        run: |
          # ============================================
          # 用户自定义构建步骤(按项目需求修改)
          # ============================================
          
          # 代码生成(按需启用)
          # go generate ./...
          # go tool ent generate ./schema
          # go tool wire ./...
          # go tool oapi-codegen -config oapi.yaml api.yaml
          # go tool stringer -type=MyType ./...
          
          # 测试(按需启用)
          # go test ./...
          # go vet ./...
          
          # 构建(必须)
          go build -o ${{ env.binary_name }} \
            -ldflags '-s -w -X main.GitTag=${{ env.git_tag }}'
          
          chmod +x ${{ env.binary_name }}

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.SERVICE_PREFIX }}-binary-linux-amd64
          path: ${{ env.SERVICE_DIR }}/${{ env.binary_name }}

      - name: Docker - Login
        uses: docker/login-action@v3
        with:
          registry: ${{ env.registry }}
          username: ${{ vars.REGISTRY_USERNAME }}
          password: ${{ secrets.REGISTRY_PASSWORD }}

      - name: Docker - Setup Buildx
        uses: docker/setup-buildx-action@v3

      - name: Docker - Build & Push
        uses: docker/build-push-action@v6
        with:
          context: ${{ env.SERVICE_DIR }}
          file: ./${{ env.SERVICE_DIR }}/Dockerfile.ci
          push: true
          platforms: linux/amd64
          tags: |
            ${{ env.registry }}/${{ github.repository_owner }}/${{ env.image_repo }}:${{ env.latest_tag }}
            ${{ env.registry }}/${{ github.repository_owner }}/${{ env.image_repo }}:${{ env.git_tag }}
          cache-from: type=registry,ref=${{ env.registry }}/${{ github.repository_owner }}/${{ env.image_repo }}:buildcache
          cache-to: type=registry,ref=${{ env.registry }}/${{ github.repository_owner }}/${{ env.image_repo }}:buildcache,mode=max

      - name: Notify
        if: always()
        continue-on-error: true
        env:
          WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
        run: |
          status="${{ job.status }}"
          [ "$status" = "success" ] && status_text="Build Success" || status_text="Build Failed"
          
          curl -s -H "Content-Type: application/json" -X POST -d \
            "{\"msg_type\":\"text\",\"content\":{\"text\":\"${{ env.binary_name }} ${status_text}\"}}" \
            "$WEBHOOK_URL" || true

  release:
    name: Create Release
    runs-on: darwin-arm64
    needs: build-and-publish
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Download artifact
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.SERVICE_PREFIX }}-binary-linux-amd64
          path: dist

      - name: Create Release
        env:
          GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
          BINARY_NAME: ${{ needs.build-and-publish.outputs.binary_name }}
        run: |
          git_tag=$(git describe --tags --abbrev=0)
          api_url="${{ github.server_url }}/api/v1"
          repo="${{ github.repository }}"
          
          # 生成校验和
          cd dist
          sha256sum "${BINARY_NAME}" > "${BINARY_NAME}.sha256"
          cd ..
          
          # 创建 Release
          release_id=$(curl -s -X POST \
            -H "Authorization: token $GITEA_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag}\"}" \
            "${api_url}/repos/${repo}/releases" | jq -r '.id')
          
          # 上传二进制文件
          curl -s -X POST \
            -H "Authorization: token $GITEA_TOKEN" \
            -F "attachment=@dist/${BINARY_NAME}" \
            "${api_url}/repos/${repo}/releases/${release_id}/assets"
          
          # 上传校验和
          curl -s -X POST \
            -H "Authorization: token $GITEA_TOKEN" \
            -F "attachment=@dist/${BINARY_NAME}.sha256" \
            "${api_url}/repos/${repo}/releases/${release_id}/assets"

Dockerfile.ci 模板

FROM alpine:latest

# 安装时区数据和证书
RUN apk add --no-cache tzdata ca-certificates

# 设置时区
ENV TZ=Asia/Shanghai

# 复制构建好的二进制文件
# 注意:需要在 docker build 时通过 --build-arg 传递 BINARY_NAME
# 或者直接写死二进制文件名
ARG BINARY_NAME=server
COPY ${BINARY_NAME} /app/server

WORKDIR /app

# 健康检查(按需修改端口和路径)
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

EXPOSE 8080

ENTRYPOINT ["/app/server"]

缓存配置

缓存路径

path: |
  ~/go/pkg/mod           # Go 模块缓存
  ~/.cache/go-build      # Go 构建缓存

Key 计算

HASH=$(sha256sum go.mod go.sum | sha256sum | awk '{print $1}' | head -c 16)

构建参数说明

CGO_ENABLED=0      # 禁用 CGO生成静态链接二进制
GOOS=linux         # 目标操作系统
GOARCH=amd64       # 目标架构

-ldflags '-s -w'   # 去除符号表和调试信息,减小体积
-X main.GitTag=... # 注入版本信息

Secrets 配置

Secret 用途
REGISTRY_PASSWORD Docker Registry 密码
RELEASE_TOKEN Gitea API 令牌(创建 Release

常见代码生成工具

根据项目使用的框架,在 Build 步骤中添加相应的生成命令:

框架/工具 命令
Ent (ORM) go tool ent generate ./schema
Wire (DI) go tool wire ./...
oapi-codegen go tool oapi-codegen -config oapi.yaml api.yaml
Stringer go tool stringer -type=MyType ./...
Protobuf protoc --go_out=. --go-grpc_out=. *.proto
go generate go generate ./...

使用步骤

  1. 复制上方 workflow 模板到 .gitea/workflows/your-service.yml
  2. 修改 SERVICE_PREFIXSERVICE_DIR 为实际值
  3. 修改 pathstags 触发条件
  4. 根据项目需求填充 "用户自定义构建步骤" 部分
  5. 创建 Dockerfile.ci 文件
  6. 配置 Secrets
  7. 推送代码触发 workflow

版本发布

# 创建并推送 tag
git tag your-service-1.0.0
git push origin your-service-1.0.0