Skip to content

fix(backend): convert flat cached info map to structured info in hand… #67

fix(backend): convert flat cached info map to structured info in hand…

fix(backend): convert flat cached info map to structured info in hand… #67

Workflow file for this run

# ===================================
# API Monitor Unified CI/CD Pipeline
# ===================================
# 触发条件:
# - 推送到 main / dev 分支
# - 提 PR 到 main / dev 分支
# - 手动触发
#
# 功能:
# - 阶段 1 (CI):前端 ESLint 检查、测试、构建验证
# - 阶段 2 (Build Agent):并行编译 5 平台 Rust Agent,上传产物并启用缓存
# - 阶段 3 (CD - Docker):多架构 Docker 镜像自动构建与发布(共享新编译的 Agent)
# - 阶段 4 (Merge):合并多架构 Docker Manifest 并生成相应标签(main -> latest, dev -> dev)
name: CI/CD Pipeline
on:
push:
branches: [main, dev]
paths-ignore:
- "**.md"
- "docs/**"
- ".gitignore"
- "LICENSE"
pull_request:
branches: [main, dev]
paths-ignore:
- "**.md"
- "docs/**"
workflow_dispatch:
inputs:
tag:
description: "Docker 镜像自定义标签(可选)"
required: false
default: ""
permissions:
contents: write
packages: write
security-events: write
env:
IMAGE_NAME: api-monitor
REGISTRY: ghcr.io
DOCKERHUB_REPO: ${{ github.repository_owner }}/api-monitor
jobs:
# ==========================================
# 阶段 1: 前端项目 CI 校验
# ==========================================
ci-frontend:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2
- name: Setup Node.js 20.x
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.2.0
with:
node-version: 20.x
cache: "npm"
- name: Disable pnpm enforcement
run: echo "npm_config_user_agent=pnpm/9.0.0 npm/? node/?" >> $GITHUB_ENV
- name: Install dependencies
run: npm install --legacy-peer-deps
- name: Run ESLint
run: npm run lint
- name: Run Tests
run: npm run test
- name: Three-side governance check
run: npm run governance:check
- name: Build Frontend Validation
run: npm run build
env:
VITE_USE_CDN: false
- name: Check build output
run: |
ls -la dist/
test -f dist/index.html
# ==========================================
# 阶段 1.5: Go 后端 CI 校验
# ==========================================
ci-backend:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2
- name: Setup Go 1.23
uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v5.2.0
with:
go-version: '1.23'
cache-dependency-path: backend-go/go.sum
- name: Run Go Tests
working-directory: backend-go
run: go test ./... -v -race -coverprofile=coverage.out
- name: Build Go Backend
working-directory: backend-go
run: |
go build -v -o api-monitor ./cmd/api-monitor
ls -lh api-monitor
test -x api-monitor
- name: Upload coverage to Codecov
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.0.2
continue-on-error: true
with:
files: backend-go/coverage.out
flags: backend-go
token: ${{ secrets.CODECOV_TOKEN }}
# ==========================================
# 阶段 2: 编译 Rust Agent (5 平台)
# ==========================================
build-agent:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
output_name: agent-linux-amd64
use_cross: false
- target: aarch64-unknown-linux-musl
os: ubuntu-latest
output_name: agent-linux-arm64
use_cross: true
- target: x86_64-pc-windows-msvc
os: windows-latest
output_name: agent-windows-amd64.exe
use_cross: false
- target: x86_64-apple-darwin
os: macos-latest
output_name: agent-darwin-amd64
use_cross: false
- target: aarch64-apple-darwin
os: macos-latest
output_name: agent-darwin-arm64
use_cross: false
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2
- name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1.10.1
with:
target: ${{ matrix.target }}
cache-workspaces: agent-rust
- name: Install musl-tools (Linux amd64)
if: matrix.target == 'x86_64-unknown-linux-musl'
run: |
sudo apt-get update
sudo apt-get install -y musl-tools
- name: Install cross (ARM64 Linux)
if: matrix.use_cross
shell: bash
run: |
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
cargo binstall --no-confirm --force cross
- name: Remove cargo mirror config in CI
shell: bash
run: rm -f agent-rust/.cargo/config.toml
- name: Build Agent
working-directory: agent-rust
shell: bash
run: |
if [ "${{ matrix.use_cross }}" = "true" ]; then
cross build --target ${{ matrix.target }} --release
else
cargo build --target ${{ matrix.target }} --release
fi
- name: Copy & Rename Binary
shell: bash
run: |
mkdir -p dist
if [[ "${{ matrix.target }}" == *"windows"* ]]; then
cp agent-rust/target/${{ matrix.target }}/release/api-monitor-agent.exe dist/${{ matrix.output_name }}
else
cp agent-rust/target/${{ matrix.target }}/release/api-monitor-agent dist/${{ matrix.output_name }}
fi
ls -lh dist/
- name: Upload agent artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.0
with:
name: ${{ matrix.output_name }}
path: dist/${{ matrix.output_name }}
retention-days: 1
# ==========================================
# 阶段 3: 多架构 Docker 镜像分平台构建 (仅 push 触发)
# ==========================================
build-docker:
needs: [ci-frontend, ci-backend, build-agent]
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
suffix: amd64
- platform: linux/arm64
runner: ubuntu-24.04-arm
suffix: arm64
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.2.2
# 💥 核心优化:直接从上游 build-agent 工作流下载最新编译出来的 Agent 二进制包
- name: Download compiled agent binaries
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.1.8
with:
path: agent-rust
pattern: agent-*
merge-multiple: true
- name: List downloaded agents
run: ls -lh agent-rust/
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.10.0
- name: Login to GitHub Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.3.0
continue-on-error: true
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.6.1
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_REPO }}
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=raw,value=dev,enable=${{ github.ref == 'refs/heads/dev' }}
type=sha,prefix=
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag != '' }}
labels: |
org.opencontainers.image.title=API Monitor
org.opencontainers.image.description=API聚合监控面板
org.opencontainers.image.vendor=iwvw
maintainer=iwvw
- name: Build and push by digest
id: build
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.13.0
with:
context: .
file: ./Dockerfile
platforms: ${{ matrix.platform }}
no-cache: true
push: true
tags: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:build-${{ github.run_id }}-${{ matrix.suffix }}
${{ env.DOCKERHUB_REPO }}:build-${{ github.run_id }}-${{ matrix.suffix }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
build-args: |
NODE_ENV=production
- name: Export digest
run: |
mkdir -p /tmp/digests
echo "${{ steps.build.outputs.digest }}" > /tmp/digests/${{ matrix.suffix }}
- name: Upload digest
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.0
with:
name: digests-${{ matrix.suffix }}
path: /tmp/digests/*
retention-days: 1
# ==========================================
# 阶段 4: 合并多架构 manifest 并打上分支对应标签 (latest / dev)
# ==========================================
merge-docker:
needs: build-docker
runs-on: ubuntu-latest
steps:
- name: Download digests
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.1.8
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.10.0
- name: Login to GitHub Container Registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker Hub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.3.0
continue-on-error: true
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.6.1
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_REPO }}
tags: |
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
type=raw,value=dev,enable=${{ github.ref == 'refs/heads/dev' }}
type=sha,prefix=
type=raw,value=${{ github.event.inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag != '' }}
- name: Create and push manifest
env:
TAGS: ${{ steps.meta.outputs.tags }}
REPO_OWNER: ${{ github.repository_owner }}
run: |
AMD64_DIGEST=$(cat /tmp/digests/amd64)
ARM64_DIGEST=$(cat /tmp/digests/arm64)
echo "AMD64 Digest: $AMD64_DIGEST"
echo "ARM64 Digest: $ARM64_DIGEST"
echo "$TAGS" | while IFS= read -r TAG; do
[ -z "$TAG" ] && continue
if [[ "$TAG" == "$REGISTRY"* ]]; then
SRC_PREFIX="$REGISTRY/$REPO_OWNER/$IMAGE_NAME"
else
SRC_PREFIX="$DOCKERHUB_REPO"
fi
echo "🔗 Creating manifest: $TAG"
for i in {1..3}; do
docker buildx imagetools create -t "$TAG" \
"${SRC_PREFIX}@${AMD64_DIGEST}" \
"${SRC_PREFIX}@${ARM64_DIGEST}" && break || {
if [ $i -lt 3 ]; then
echo " ⚠ Retry in 10s ($i/3)..."
sleep 10
else
echo " ❌ Failed to create manifest for $TAG"
exit 1
fi
}
done
done
- name: Summary
env:
TAGS: ${{ steps.meta.outputs.tags }}
run: |
echo "## 🐳 Docker 镜像构建成功" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**标签:**" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "$TAGS" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**架构**: linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY
# ==========================================
# 阶段 5: 清理临时镜像
# ==========================================
cleanup-docker:
needs: merge-docker
runs-on: ubuntu-latest
if: always()
continue-on-error: true
steps:
- name: Delete temporary build images
uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
with:
package-name: ${{ env.IMAGE_NAME }}
package-type: container
min-versions-to-keep: 0
delete-only-untagged-versions: false
ignore-versions: "^(?!build-${{ github.run_id }}).*$"
continue-on-error: true
# ==========================================
# 阶段 6: 安全扫描
# ==========================================
security-scan:
needs: merge-docker
runs-on: ubuntu-latest
continue-on-error: true
steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest
format: "sarif"
output: "trivy-results.sarif"
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@d77b13a0df3134d64a457ea9003f600b09fa1c8a # v3.28.10
with:
sarif_file: "trivy-results.sarif"