Skip to content

test(mcp): cover authenticateOAuth introspection failure + fallback b… #970

test(mcp): cover authenticateOAuth introspection failure + fallback b…

test(mcp): cover authenticateOAuth introspection failure + fallback b… #970

Workflow file for this run

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 }}