chore(deps): bump protobufjs from 7.5.4 to 7.5.5 in /server #1080
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: CI | |
| on: | |
| push: | |
| branches: [main, develop] | |
| paths-ignore: | |
| - "**.md" | |
| - "docs/**" | |
| - ".github/*.md" | |
| - "LICENSE" | |
| pull_request: | |
| branches: [main] | |
| paths-ignore: | |
| - "**.md" | |
| - "docs/**" | |
| - ".github/*.md" | |
| - "LICENSE" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| NODE_ENV: test | |
| NODE_LTS: "22.x" | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| actions: read | |
| jobs: | |
| # ============================================================ | |
| # Stage 1: Fast validation (single Node LTS) | |
| # Deterministic checks that don't depend on Node version | |
| # ============================================================ | |
| lint: | |
| name: Lint & Validate | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_LTS }} | |
| cache: npm | |
| cache-dependency-path: server/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| - name: Validate contracts | |
| run: npm run validate:contracts | |
| - name: Validate metadata | |
| run: npm run validate:metadata | |
| - name: Validate versions | |
| run: npm run validate:versions | |
| - name: Typecheck | |
| run: npm run typecheck | |
| - name: Lint (ratchet) | |
| run: npm run lint:ratchet | |
| - name: Lint Python hooks (Ruff) | |
| uses: astral-sh/ruff-action@v3 | |
| with: | |
| src: ./hooks | |
| - name: Format Python hooks (Ruff) | |
| uses: astral-sh/ruff-action@v3 | |
| with: | |
| src: ./hooks | |
| args: format --check | |
| - name: Typecheck Python hooks (Pyrefly) | |
| working-directory: . | |
| run: | | |
| pip install pyrefly --quiet | |
| pyrefly check --baseline hooks/.pyrefly-baseline.json | |
| architecture-scope: | |
| name: Architecture Scope | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_run: ${{ steps.scope.outputs.should_run }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect architecture-relevant changes | |
| id: scope | |
| run: | | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| git fetch origin "${{ github.base_ref }}" --depth=1 | |
| CHANGED_FILES=$(git diff --name-only "origin/${{ github.base_ref }}"...HEAD) | |
| elif [ -n "${{ github.event.before }}" ] && [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then | |
| CHANGED_FILES=$(git diff --name-only "${{ github.event.before }}"...HEAD) | |
| else | |
| CHANGED_FILES=$(git diff-tree --no-commit-id --name-only -r HEAD) | |
| fi | |
| echo "$CHANGED_FILES" | |
| if printf '%s\n' "$CHANGED_FILES" | grep -Eq '^(server/src/mcp/tools/|server/src/infra/http/transport/|server/src/runtime/)'; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # ============================================================ | |
| # Stage 2: Build (single Node LTS, upload artifact) | |
| # Build once, share with test matrix | |
| # ============================================================ | |
| build: | |
| name: Build | |
| needs: lint | |
| if: ${{ always() && needs.lint.result != 'cancelled' && (github.event_name == 'pull_request' || needs.lint.result == 'success') }} | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_LTS }} | |
| cache: npm | |
| cache-dependency-path: server/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| - name: Build bundled distribution | |
| run: npm run build | |
| - name: Startup smoke test | |
| run: npm run start:test | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: dist | |
| path: server/dist/ | |
| retention-days: 1 | |
| # ============================================================ | |
| # Stage 3: Test matrix (LTS versions only) | |
| # Download artifact, run tests on multiple Node versions | |
| # ============================================================ | |
| test: | |
| name: Test (Node ${{ matrix.node }}) | |
| needs: build | |
| if: ${{ always() && needs.build.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| node: ["22.x"] | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| cache-dependency-path: server/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| - name: Download build artifact | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: dist | |
| path: server/dist/ | |
| - name: Unit tests | |
| run: npm run test:ci | |
| timeout-minutes: 15 | |
| - name: Coverage threshold check | |
| if: matrix.node == '22.x' | |
| run: npm run test:coverage | |
| timeout-minutes: 15 | |
| - name: E2E tests | |
| run: npm run test:e2e | |
| # ============================================================ | |
| # Stage 4: Architecture validation (MCP paths only) | |
| # Runs only when MCP/runtime code changes | |
| # ============================================================ | |
| architecture: | |
| name: Architecture Validation | |
| needs: [lint, architecture-scope] | |
| runs-on: ubuntu-latest | |
| if: | | |
| always() && | |
| needs.lint.result != 'cancelled' && | |
| needs.architecture-scope.result == 'success' && | |
| needs.architecture-scope.outputs.should_run == 'true' && | |
| ( | |
| github.event_name == 'pull_request' || | |
| needs.lint.result == 'success' | |
| ) | |
| defaults: | |
| run: | |
| working-directory: server | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_LTS }} | |
| cache: npm | |
| cache-dependency-path: server/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --prefer-offline --no-audit | |
| - name: Validate architecture rules | |
| run: npm run validate:arch | |
| # ============================================================ | |
| # PR Summary: Comment with validation results | |
| # ============================================================ | |
| pr-summary: | |
| name: PR Summary | |
| needs: [lint, build, test, architecture] | |
| if: always() && github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Analyze changed files | |
| id: changes | |
| run: | | |
| if git diff --name-only origin/${{ github.base_ref }}...HEAD > changed_files.txt 2>/dev/null; then | |
| echo "files=$(cat changed_files.txt | tr '\n' ' ')" >> $GITHUB_OUTPUT | |
| else | |
| git diff --name-only HEAD~1 HEAD > changed_files.txt 2>/dev/null || echo "No changes" > changed_files.txt | |
| echo "files=$(cat changed_files.txt | tr '\n' ' ')" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Comment PR with results | |
| uses: actions/github-script@v8 | |
| env: | |
| LINT_RESULT: ${{ needs.lint.result }} | |
| BUILD_RESULT: ${{ needs.build.result }} | |
| TEST_RESULT: ${{ needs.test.result }} | |
| ARCH_RESULT: ${{ needs.architecture.result }} | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| let changedFiles = 'Unable to determine'; | |
| try { | |
| changedFiles = fs.readFileSync('changed_files.txt', 'utf8').trim() || 'No changes detected'; | |
| } catch (e) { | |
| console.log(`Could not read changed_files.txt: ${e.message}`); | |
| } | |
| const lintResult = process.env.LINT_RESULT || 'unknown'; | |
| const buildResult = process.env.BUILD_RESULT || 'unknown'; | |
| const testResult = process.env.TEST_RESULT || 'unknown'; | |
| const archResult = process.env.ARCH_RESULT || 'unknown'; | |
| const runUrl = `${context.payload.repository.html_url}/actions/runs/${context.runId}`; | |
| const statusEmoji = (result) => result === 'success' ? '✅' : result === 'skipped' ? '⏭️' : '❌'; | |
| const allPassed = lintResult === 'success' && buildResult === 'success' && testResult === 'success' && (archResult === 'success' || archResult === 'skipped'); | |
| const message = [ | |
| allPassed ? '## ✅ CI Passed' : '## ❌ CI Failed', | |
| '', | |
| '| Stage | Status |', | |
| '|-------|--------|', | |
| `| Lint & Validate | ${statusEmoji(lintResult)} ${lintResult} |`, | |
| `| Build | ${statusEmoji(buildResult)} ${buildResult} |`, | |
| `| Test (Node 22) | ${statusEmoji(testResult)} ${testResult} |`, | |
| `| Architecture | ${statusEmoji(archResult)} ${archResult} |`, | |
| '', | |
| '<details>', | |
| '<summary>Files changed</summary>', | |
| '', | |
| '```', | |
| changedFiles, | |
| '```', | |
| '</details>', | |
| '', | |
| `[View workflow run](${runUrl})` | |
| ].join('\n'); | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number | |
| }); | |
| const botComment = comments.data.find(c => c.user.type === 'Bot' && (c.body.includes('CI Passed') || c.body.includes('CI Failed'))); | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: message | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: message | |
| }); | |
| } |