fix(agent): filter out virtual/pseudo filesystems and deduplicate mou… #9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # =================================== | |
| # 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 | |
| continue-on-error: true | |
| - name: Run Tests | |
| run: npm run test | |
| - 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 | |
| # ========================================== | |
| # 阶段 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, 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" |