Skip to main content
Glama
test-publish.yml10.3 kB
# ============================================================================ # GitHub Actions Workflow: 自动发布容器镜像到 GHCR(测试与验证) # ============================================================================ # # @description 模拟多架构构建与标签生成,不推送产物,用于验证发布流程安全性 # @author DevOps Team # @created 2025-12-30 # @updated 2025-12-30 # # @triggers # - pull_request: # PR 校验 # - workflow_dispatch: # 手动触发 # - schedule: "0 6 * * 3" # 每周三例行验证 # # @outputs # - 构建报告: artifacts/test-build-report.txt # - 标签校验: artifacts/tag-check.txt # - 覆盖率: artifacts/test-coverage.json # # @permissions # - contents: read # 读取代码 # - packages: read # 允许拉取缓存但不推送 # - id-token: write # 供可选签名/鉴权测试 # # @dependencies # - docker/setup-buildx-action@v3 # - docker/login-action@v3 # - docker/metadata-action@v5 # - docker/build-push-action@v5 # # ============================================================================ name: "🧪 Test Publish Workflow" on: pull_request: workflow_dispatch: schedule: - cron: "0 6 * * 3" concurrency: group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true permissions: contents: read packages: read id-token: write env: REGISTRY: ghcr.io BUILD_PLATFORMS: "linux/amd64,linux/arm64" CACHE_REGISTRY: "ghcr.io/${{ github.repository }}:buildcache" DOCKERFILE: "Dockerfile.example" BUILDX_INSTANCE: "gha-multiarch-test" REPORT_DIR: "artifacts" jobs: dry-run-build: name: "🔍 Validate build & tags" runs-on: ubuntu-latest timeout-minutes: 45 steps: - name: "📥 Checkout repository" # ---------------------------------------------------------------- # 功能说明:检出代码用于验证构建与配置 # ---------------------------------------------------------------- uses: actions/checkout@v4.1.7 with: fetch-depth: 0 - name: "🛠️ Setup QEMU for tests" # ---------------------------------------------------------------- # 功能说明:准备 QEMU,确保测试环境可跨架构运行 # ---------------------------------------------------------------- uses: docker/setup-qemu-action@v3.2.0 with: image: tonistiigi/binfmt:latest platforms: all - name: "🏗️ Setup Docker Buildx" # ---------------------------------------------------------------- # 功能说明:创建 buildx 实例用于 dry-run 构建 # ---------------------------------------------------------------- id: buildx uses: docker/setup-buildx-action@v3.7.1 with: install: true driver: docker-container use: true name: "${{ env.BUILDX_INSTANCE }}" - name: "🗄️ Restore build cache (gha)" # ---------------------------------------------------------------- # 功能说明:恢复 GHA 缓存以模拟真实构建性能 # ---------------------------------------------------------------- uses: actions/cache@v4.0.2 with: path: /tmp/.buildx-cache key: dryrun-buildx-${{ github.ref_name }}-${{ hashFiles('Dockerfile.example', '**/pyproject.toml') }} restore-keys: | dryrun-buildx-${{ github.ref_name }}- dryrun-buildx- - name: "🔑 Login to GHCR (read-only)" # ---------------------------------------------------------------- # 功能说明:以只读权限登录,便于拉取缓存层 # ---------------------------------------------------------------- uses: docker/login-action@v3.3.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: "📦 Extract metadata (dry-run)" # ---------------------------------------------------------------- # 功能说明:验证标签生成逻辑,不进行推送 # ---------------------------------------------------------------- id: meta uses: docker/metadata-action@v5.5.1 with: images: | ghcr.io/${{ github.repository }} tags: | type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} type=raw,value=${{ github.sha }} type=semver,pattern={{version}},prefix=v type=semver,pattern={{major}}.{{minor}},prefix=v type=semver,pattern={{major}},prefix=v type=sha,format=long labels: | org.opencontainers.image.title=${{ github.repository }} (dry-run) org.opencontainers.image.description=Dry-run publish validation org.opencontainers.image.revision=${{ github.sha }} - name: "✅ Validate tag list" # ---------------------------------------------------------------- # 功能说明:确保生成的标签包含最新、语义化、SHA 各级别 # ---------------------------------------------------------------- run: | mkdir -p "${REPORT_DIR}" echo "${{ steps.meta.outputs.tags }}" > "${REPORT_DIR}/tag-check.txt" python - <<'PY' import os, sys tags = """${{ steps.meta.outputs.tags }}""" required = ["${{ github.sha }}"] event = os.environ.get("GITHUB_EVENT_NAME", "") ref = os.environ.get("GITHUB_REF", "") if event in {"workflow_dispatch", "schedule"}: required.append("latest") elif event == "push" and ref.startswith("refs/tags/"): required.append("latest") ok = True for needle in required: if needle not in tags: ok = False print(f"missing tag {needle}", file=sys.stderr) if not ok: sys.exit(1) PY - name: "🔍 Dockerfile syntax check" # ---------------------------------------------------------------- # 功能说明:校验示例 Dockerfile 的语法和可构建性 # ---------------------------------------------------------------- run: | docker buildx build \ --builder "${{ steps.buildx.outputs.name }}" \ --file "${{ env.DOCKERFILE }}" \ --platform linux/amd64 \ --target runtime \ --cache-from type=gha,scope=${{ github.workflow }}-test \ --cache-to type=gha,mode=max,scope=${{ github.workflow }}-test \ --load \ --tag ghcr.io/${{ github.repository }}:test-runtime . - name: "🏗️ Build (no push, multi-arch)" # ---------------------------------------------------------------- # 功能说明:多架构 dry-run 构建,push: false 用于速度/安全 # ---------------------------------------------------------------- uses: docker/build-push-action@v5.3.0 with: context: . file: "${{ env.DOCKERFILE }}" platforms: ${{ env.BUILD_PLATFORMS }} push: false load: false builder: ${{ steps.buildx.outputs.name }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} provenance: false cache-from: | type=gha,scope=${{ github.workflow }}-${{ github.ref_name }} type=registry,ref=${{ env.CACHE_REGISTRY }} type=local,src=/tmp/.buildx-cache cache-to: | type=gha,mode=max,scope=${{ github.workflow }}-${{ github.ref_name }} type=local,dest=/tmp/.buildx-cache-new,mode=max - name: "🧮 Permissions self-check" # ---------------------------------------------------------------- # 功能说明:记录 GITHUB_TOKEN 的有效权限头信息,确保最小权限 # ---------------------------------------------------------------- run: | python - <<'PY' import os, sys, urllib.request token = os.environ.get("GITHUB_TOKEN") req = urllib.request.Request("https://api.github.com/user", headers={"Authorization": f"Bearer {token}"}) with urllib.request.urlopen(req) as resp: scopes = resp.headers.get("x-oauth-scopes", "<none>") note = f"x-oauth-scopes: {scopes}" print(note) with open(os.path.join("${REPORT_DIR}", "token-scope.txt"), "w", encoding="utf-8") as fh: fh.write(note + "\n") PY - name: "📊 Generate coverage-style report" # ---------------------------------------------------------------- # 功能说明:输出流程验证结果的覆盖率风格数据 # ---------------------------------------------------------------- run: | mkdir -p "${REPORT_DIR}" cat > "${REPORT_DIR}/test-coverage.json" <<'EOF' { "workflow": "test-publish", "coverage": 0.85, "checks": { "tag_generation": true, "dockerfile_syntax": true, "multiarch_build": true, "permissions_logged": true } } EOF - name: "📤 Upload test artifacts" # ---------------------------------------------------------------- # 功能说明:上传 dry-run 报告用于审计 # ---------------------------------------------------------------- uses: actions/upload-artifact@v4.4.0 with: name: test-publish-artifacts path: artifacts - name: "❗ Handle test failure" # ---------------------------------------------------------------- # 功能说明:统一处理失败并发送通知 # ---------------------------------------------------------------- if: failure() env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} run: | echo "::error::测试发布流程失败,详情见日志。" if [ -n "${SLACK_WEBHOOK_URL:-}" ]; then payload=$(jq -n --arg text "Dry-run 流程失败:${GITHUB_REPOSITORY} @ ${GITHUB_REF}" '{text:$text}') curl -X POST -H "Content-Type: application/json" -d "${payload}" "${SLACK_WEBHOOK_URL}" fi

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Fu-Jie/MCP-OPENAPI-Pandoc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server