From f1cc2d81de1b81689ce459c5897c706c026f2f5a Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Fri, 11 Apr 2025 12:18:17 -0700 Subject: [PATCH] Workflow refactoring and improvements (#273) * Remove code coverage PR commenting * Only run markdown-link-check when markdown files are updated * Declare CI workflow permissions * Refactor release workflow and declare permissions * Pin all actions to SHAs * Run CI manually, on all pushes to main, or if code changes in a PR * NuGet publishing doesn't need any permissions --- .../workflows/{ci.yml => ci-build-test.yml} | 28 +++++-- ...code-coverage.yml => ci-code-coverage.yml} | 22 ++--- .github/workflows/docs.yml | 12 +-- .github/workflows/markdown-link-check.yml | 17 ++-- .github/workflows/release.yml | 82 +++++++++++++++---- 5 files changed, 112 insertions(+), 49 deletions(-) rename .github/workflows/{ci.yml => ci-build-test.yml} (72%) rename .github/workflows/{code-coverage.yml => ci-code-coverage.yml} (74%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-build-test.yml similarity index 72% rename from .github/workflows/ci.yml rename to .github/workflows/ci-build-test.yml index f3a799f..9a66ccd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-build-test.yml @@ -1,10 +1,26 @@ name: Build and Test on: + # Manual trigger + workflow_dispatch: + + # Run CI for all pushes to main push: branches: ["main"] + + # Run CI for pull requests to all branches, but only if code changed pull_request: - branches: ["main"] + paths: + - ".github/workflows/ci-*.yml" + - "*.sln" + - "*.props" + - "Makefile" + - "src/**" + - "tests/**" + - "samples/**" + +permissions: + contents: read jobs: build: @@ -18,12 +34,12 @@ jobs: steps: - name: Clone the repo - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: | 9.0.x @@ -35,7 +51,7 @@ jobs: run: sudo apt-get install -y mono-devel - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 with: node-version: '20' @@ -68,7 +84,7 @@ jobs: - name: Upload test results artifact if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: testresults-${{ matrix.os }}-${{ matrix.configuration }} path: testresults/** @@ -76,5 +92,5 @@ jobs: publish-coverage: if: github.actor != 'dependabot[bot]' needs: build - uses: ./.github/workflows/code-coverage.yml + uses: ./.github/workflows/ci-code-coverage.yml secrets: inherit diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/ci-code-coverage.yml similarity index 74% rename from .github/workflows/code-coverage.yml rename to .github/workflows/ci-code-coverage.yml index d678f27..dc86e65 100644 --- a/.github/workflows/code-coverage.yml +++ b/.github/workflows/ci-code-coverage.yml @@ -3,20 +3,23 @@ name: Code Coverage on: workflow_call: +permissions: + contents: read + jobs: publish-coverage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: | 9.0.x 8.0.x - name: Download test results - uses: actions/download-artifact@v4 + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: pattern: testresults-* @@ -33,14 +36,14 @@ jobs: toolpath: "reportgeneratortool" - name: Upload combined coverage XML - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage path: ${{ github.workspace }}/report retention-days: 7 - name: Publish code coverage report - uses: irongut/CodeCoverageSummary@v1.3.0 + uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0 with: filename: "report/Cobertura.xml" badge: true @@ -53,19 +56,12 @@ jobs: thresholds: "60 80" - name: Upload combined coverage markdown - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-markdown path: ${{ github.workspace }}/code-coverage-results.md retention-days: 7 - - name: Add Coverage PR Comment - uses: marocchino/sticky-pull-request-comment@v2 - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository - with: - recreate: true - path: ${{ github.workspace }}/code-coverage-results.md - - name: Coverage on step summary if: always() run: cat "${{ github.workspace }}/report/SummaryGithub.md" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 04259a5..866b577 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,9 +7,9 @@ on: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: - actions: read + contents: read pages: write - id-token: write + id-token: write # Required for actions/deploy-pages # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. @@ -27,10 +27,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: .NET Setup - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: 9.x @@ -38,10 +38,10 @@ jobs: run: make generate-docs - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: 'artifacts/_site' - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/markdown-link-check.yml b/.github/workflows/markdown-link-check.yml index 3229db0..6a49bec 100644 --- a/.github/workflows/markdown-link-check.yml +++ b/.github/workflows/markdown-link-check.yml @@ -1,20 +1,25 @@ name: Check Markdown links on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] + push: + branches: [ "main" ] + paths: "**.md" + pull_request: + branches: [ "main" ] + paths: "**.md" + +permissions: + contents: read jobs: markdown-link-check: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@main + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Markup Link Checker (mlc) - uses: becheran/mlc@v0.21.0 + uses: becheran/mlc@c925f90a9a25e16e4c4bfa29058f6f9ffa9f0d8c # v0.21.0 with: # Ignore external links that result in 403 errors during CI. Do not warn for redirects where we want to keep the vanity URL in the markdown or for GitHub links that redirect to the login. args: --ignore-links "https://www.anthropic.com/*,https://hackerone.com/anthropic-vdp/*" --do-not-warn-for-redirect-to "https://modelcontextprotocol.io/*,https://github.com/login?*" ./ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 35d6053..9ae26f8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,14 +40,17 @@ jobs: runs-on: ${{ matrix.os }} + permissions: + contents: read + steps: - name: Clone the repo - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up .NET - uses: actions/setup-dotnet@v4 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: 9.0.x @@ -61,14 +64,17 @@ jobs: runs-on: windows-latest needs: build-all-configs + permissions: + contents: read + env: version_suffix_args: ${{ github.event_name != 'release' && format('--version-suffix "{0}"', inputs.version_suffix_override || format('ci.{0}', github.run_number)) || '' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup .NET - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: | 9.0.x @@ -81,32 +87,29 @@ jobs: --output "${{ github.workspace }}/artifacts/packages" - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: ${{ !cancelled() }} with: name: build-artifacts path: ${{ github.workspace }}/artifacts - publish-package: + publish-github: needs: build-package runs-on: ubuntu-latest + + permissions: + packages: write + steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup .NET - uses: actions/setup-dotnet@v2 + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 with: dotnet-version: 9.0.x - name: Download build artifacts - uses: actions/download-artifact@v4 - - - name: Upload release asset - if: github.event_name == 'release' - run: gh release upload ${{ github.event.release.tag_name }} - ${{ github.workspace }}/build-artifacts/packages/*.*nupkg - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 - name: Authenticate to GitHub registry run: dotnet nuget add source @@ -123,9 +126,52 @@ jobs: --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate + publish-release: + if: github.event_name == 'release' + needs: build-package + runs-on: ubuntu-latest + + permissions: + contents: write + packages: write + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup .NET + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 + with: + dotnet-version: 9.0.x + + - name: Download build artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + + - name: Upload release asset + run: gh release upload ${{ github.event.release.tag_name }} + ${{ github.workspace }}/build-artifacts/packages/*.*nupkg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-nuget: + # Only publish to NuGet.org from the modelcontextprotocol/csharp-sdk repository + if: ${{ github.event_name == 'release' && github.repository == 'modelcontextprotocol/csharp-sdk' }} + needs: build-package + runs-on: ubuntu-latest + + permissions: { } + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup .NET + uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1 + with: + dotnet-version: 9.0.x + + - name: Download build artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + - name: Publish to NuGet.org (Releases only) - # Only publish to NuGet.org from the modelcontextprotocol/csharp-sdk repository - if: ${{ github.event_name == 'release' && github.repository == 'modelcontextprotocol/csharp-sdk' }} run: dotnet nuget push ${{github.workspace}}/build-artifacts/packages/*.nupkg --source https://api.nuget.org/v3/index.json