Merge branch 'claude/project-setup-dependencies-jimwcl' #477
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
| name: Release Guardrails | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| # 连续推送时取消上一轮未完成的运行:守护的是分支最新提交, | |
| # 排队叠加的旧运行只烧 runner 不产出信息(旧提交显示 cancelled 属预期)。 | |
| concurrency: | |
| group: release-guardrails-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| static-checks: | |
| name: static-checks | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Lint | |
| run: pnpm run lint | |
| - name: Typecheck | |
| run: pnpm run typecheck | |
| test-client: | |
| name: test-client | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Test Client | |
| run: pnpm run test:client | |
| test-server: | |
| name: test-server | |
| runs-on: ubuntu-latest | |
| # 提速双杠杆(实测过):三分片矩阵横向摊(每片 ~1/3 文件), | |
| # 批内文件并行打开(本地全量 6m→3m31s 全绿)。挂起保护不变: | |
| # 批超时 + 二分定位机制仍在,超时上限按并行大批次放宽到 300s。 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: ["1/3", "2/3", "3/3"] | |
| env: | |
| TEST_SERVER_SHARD: ${{ matrix.shard }} | |
| TEST_SERVER_BATCH_SIZE: 40 | |
| TEST_SERVER_SINGLE_FORK: "0" | |
| TEST_SERVER_FILE_PARALLELISM: "1" | |
| TEST_SERVER_BATCH_TIMEOUT_MS: 300000 | |
| TEST_SERVER_KILL_GRACE_MS: 10000 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| # a2a 会话/注册中心已是 Python 拥有(services/a2a_runtime.py),Node 端 | |
| # A2AClient 是跨进程 thin proxy——server 测试里这些子进程需要 pydantic 等 | |
| # Python 依赖,否则 a2a 路由测试全部 degraded 失败。 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: slide-rule-python/requirements.txt | |
| - name: Install Python Dependencies | |
| run: pip install -r slide-rule-python/requirements.txt | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Test Server | |
| run: pnpm run test:server | |
| test-executor: | |
| name: test-executor | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Test Executor | |
| run: pnpm run test:executor | |
| build: | |
| name: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build | |
| run: pnpm run build | |
| python-live-delegation: | |
| name: python-live-delegation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| run_install: false | |
| - name: Setup Node | |
| uses: actions/setup-node@v5 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| cache-dependency-path: pnpm-lock.yaml | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: slide-rule-python/requirements.txt | |
| - name: Install Python Dependencies | |
| run: pip install -r slide-rule-python/requirements.txt | |
| - name: Start slide-rule-python (uvicorn :9700, no LLM key) | |
| working-directory: slide-rule-python | |
| run: | | |
| nohup python -m uvicorn app:app --host 127.0.0.1 --port 9700 > uvicorn.log 2>&1 & | |
| echo "waiting for slide-rule-python health on :9700" | |
| for i in $(seq 1 60); do | |
| if curl -sf http://localhost:9700/health > /dev/null; then | |
| echo "slide-rule-python healthy after ${i}s" | |
| exit 0 | |
| fi | |
| sleep 1 | |
| done | |
| echo "slide-rule-python did not become healthy in time" >&2 | |
| cat uvicorn.log >&2 || true | |
| exit 1 | |
| - name: Install Dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Live Node -> Python Delegation Smoke | |
| run: pnpm run smoke:live-delegation | |
| - name: Dump uvicorn log on failure | |
| if: failure() | |
| run: cat slide-rule-python/uvicorn.log || true | |
| quality-gates: | |
| name: quality-gates | |
| if: always() | |
| runs-on: ubuntu-latest | |
| needs: | |
| - static-checks | |
| - test-client | |
| - test-server | |
| - test-executor | |
| - build | |
| steps: | |
| - name: Summarize dependency results | |
| run: | | |
| echo "static-checks=${{ needs.static-checks.result }}" | |
| echo "test-client=${{ needs.test-client.result }}" | |
| echo "test-server=${{ needs.test-server.result }}" | |
| echo "test-executor=${{ needs.test-executor.result }}" | |
| echo "build=${{ needs.build.result }}" | |
| - name: Fail if any dependency failed | |
| run: | | |
| if [ "${{ needs.static-checks.result }}" != "success" ] || \ | |
| [ "${{ needs.test-client.result }}" != "success" ] || \ | |
| [ "${{ needs.test-server.result }}" != "success" ] || \ | |
| [ "${{ needs.test-executor.result }}" != "success" ] || \ | |
| [ "${{ needs.build.result }}" != "success" ]; then | |
| echo "One or more quality gate jobs failed." | |
| exit 1 | |
| fi |