test(mcp): cover authenticateOAuth introspection failure + fallback b… #970
Workflow file for this run
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] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| go-version: ["1.26.4"] | |
| os: [ubuntu-latest, windows-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 | |
| with: | |
| go-version: ${{ matrix.go-version }} | |
| - name: Build | |
| run: go build ./... | |
| - name: Vet | |
| run: go vet ./... | |
| - name: Install staticcheck | |
| if: runner.os != 'Windows' | |
| run: go install honnef.co/go/tools/cmd/staticcheck@latest | |
| - name: Staticcheck | |
| if: runner.os != 'Windows' | |
| run: staticcheck ./... | |
| - name: Install govulncheck | |
| if: runner.os != 'Windows' | |
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Vulnerability check | |
| if: runner.os != 'Windows' | |
| run: govulncheck ./... | |
| - name: Test | |
| if: runner.os != 'Windows' | |
| run: go test -p=1 -race -coverprofile coverage.out ./... | |
| - name: Test (Windows) | |
| if: runner.os == 'Windows' | |
| run: go test -short -p=1 -race -coverprofile coverage.out ./... | |
| - name: Coverage report | |
| if: runner.os != 'Windows' | |
| run: | | |
| COVERAGE_REPORT=$(go tool cover -func=coverage.out) | |
| printf '%s\n' "$COVERAGE_REPORT" | tail -1 | |
| - name: Coverage threshold | |
| if: runner.os != 'Windows' | |
| run: | | |
| COVERAGE_REPORT=$(go tool cover -func=coverage.out) | |
| COVERAGE=$(printf '%s\n' "$COVERAGE_REPORT" | awk '/^total:/ {print substr($3, 1, length($3)-1)}') | |
| if [ -z "$COVERAGE" ]; then | |
| echo "::error::Failed to parse total coverage from go tool cover output" | |
| exit 1 | |
| fi | |
| echo "Total coverage: ${COVERAGE}%" | |
| if [ "$(echo "$COVERAGE < 75" | bc -l)" -eq 1 ]; then | |
| echo "::error::Coverage ${COVERAGE}% is below 75% threshold" | |
| exit 1 | |
| fi | |
| - name: Check coverage wiki | |
| if: runner.os != 'Windows' && github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| id: coverage_wiki | |
| run: | | |
| if git ls-remote --exit-code "https://github.com/${GITHUB_REPOSITORY}.wiki" HEAD >/dev/null 2>&1; then | |
| echo "exists=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "exists=false" >> "$GITHUB_OUTPUT" | |
| echo "::notice::Skipping coverage badge because ${GITHUB_REPOSITORY}.wiki is not enabled" | |
| fi | |
| - name: Coverage badge | |
| if: runner.os != 'Windows' && github.ref == 'refs/heads/main' && github.event_name == 'push' && steps.coverage_wiki.outputs.exists == 'true' | |
| continue-on-error: true | |
| uses: ncruces/go-coverage-report@dfc237255099f2d25066babde51253992175e365 # v0 | |
| with: | |
| coverage-file: coverage.out | |
| report: true | |
| chart: true | |
| amend: true | |
| secrets-scan: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| - uses: trufflesecurity/trufflehog@d411fff7b8879a62509f3fa98c07f247ac089a51 # main | |
| with: | |
| extra_args: --only-verified | |
| # Fast layer of the dependency-vulnerability gate: scans go.mod/go.sum against | |
| # the OSV database on every PR and push. Fails the build on any known, fixable | |
| # vuln so a security fix lands with the change that introduces (or fails to | |
| # bump past) it — not weeks later. govulncheck (in the `test` job) stays as the | |
| # reachability-aware Go signal; osv-scanner is broader — it flags vulnerable | |
| # deps even when no reachable call path exists. Accepted/unfixable vulns are | |
| # time-boxed in .github/osv-scanner.toml. The release.yml `security-gate` job | |
| # is the backstop. (Docker base-image CVEs need a separate trivy scan; follow-up.) | |
| osv-scan: | |
| name: OSV vulnerability scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Scan Go dependencies against OSV | |
| uses: google/osv-scanner-action/osv-scanner-action@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8 | |
| with: | |
| # --no-call-analysis=all: gate on the dependency manifest only, never | |
| # the embedded govulncheck source pass. That pass runs inside the | |
| # osv-scanner action's container against ITS bundled Go toolchain; if | |
| # that Go is older than this repo's go.mod requirement it cannot build, | |
| # fails, and then reports every stdlib advisory as a spurious finding | |
| # (it red-failed CI exactly this way). Manifest-only is deterministic | |
| # and matches Dependabot semantics (flag a vulnerable dependency | |
| # version whether or not it is reachable). Reachability stays covered | |
| # by the govulncheck step in the `test` job, on the correct toolchain. | |
| scan-args: |- | |
| --config=.github/osv-scanner.toml | |
| --no-call-analysis=all | |
| --recursive | |
| ./ | |
| release: | |
| needs: test | |
| runs-on: ubuntu-latest | |
| # Disabled: the canonical release pipeline lives in release.yml (macOS | |
| # codesign + cosign + Homebrew + docker + npm + mcp-registry). Running | |
| # goreleaser here too raced release.yml to create the same GitHub release. | |
| if: false | |
| permissions: | |
| contents: write | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 | |
| with: | |
| go-version: "1.26.4" | |
| # Register QEMU user-static interpreters so buildx can emit | |
| # linux/arm64 images on the amd64 GitHub-hosted runner. | |
| - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 | |
| - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2 | |
| with: | |
| version: "~> v2" | |
| args: release --clean | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # goreleaser-action defaults GOTOOLCHAIN=local, which blocks the Go | |
| # toolchain auto-download in the before-hooks. go.mod requires | |
| # >= 1.26.4 (stdlib CVE fixes GO-2026-5037/5039) but GitHub runners | |
| # may still ship 1.26.3, so pin the toolchain so go fetches 1.26.4 | |
| # for the hooks and the release build. | |
| GOTOOLCHAIN: "go1.26.4" | |
| # HOMEBREW_TAP_TOKEN: a GitHub personal access token (classic) with | |
| # `repo` scope, stored as a repository secret. Goreleaser uses it to | |
| # push the auto-generated Homebrew formula to | |
| # MikkoParkkola/homebrew-tap. Until the secret is created the brews | |
| # step is skipped gracefully (goreleaser treats empty token as skip). | |
| HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} | |
| npm-publish: | |
| needs: release | |
| runs-on: ubuntu-latest | |
| # Disabled: npm is published by the canonical release.yml pipeline. | |
| if: false | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: "20" | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Update npm package version | |
| run: | | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| cd npm | |
| npm version "$VERSION" --no-git-tag-version --allow-same-version | |
| - name: Publish to npm | |
| run: npm publish --access public | |
| working-directory: npm | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} |