diff --git a/.github/workflows/pr-coverage-by-team.yml b/.github/workflows/pr-coverage-by-team.yml new file mode 100644 index 00000000000..4c5992b1450 --- /dev/null +++ b/.github/workflows/pr-coverage-by-team.yml @@ -0,0 +1,181 @@ +name: PR Coverage by Team + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - '**/*.js' + - '**/*.jsx' + - '**/*.ts' + - '**/*.tsx' + - 'package.json' + - '.github/CODEOWNERS' + +permissions: {} + +jobs: + setup: + name: Setup codeowners manifest + runs-on: ubuntu-x64-small + permissions: + contents: read + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Setup Node.js + uses: ./.github/actions/setup-node + + - name: Install dependencies + run: yarn install --immutable + env: + PUPPETEER_SKIP_DOWNLOAD: true + CYPRESS_INSTALL_BINARY: 0 + + - name: Generate codeowners manifest + run: yarn codeowners-manifest + + - name: Upload codeowners manifest + uses: actions/upload-artifact@v5 + with: + name: codeowners-manifest + path: codeowners-manifest/ + retention-days: 1 + + coverage: + name: Coverage ${{ matrix.branch }} - ${{ matrix.team }} + needs: [setup] + runs-on: ubuntu-x64-large + permissions: + contents: read + strategy: + fail-fast: false + matrix: + # Opted-in teams for coverage tracking + team: &teams + - '@grafana/dataviz-squad' + branch: [pr, main] + steps: + - uses: actions/checkout@v5 + with: + ref: ${{ matrix.branch == 'main' && 'main' || github.ref }} + persist-credentials: false + + - name: Setup Node.js + uses: ./.github/actions/setup-node + + - name: Download codeowners manifest + uses: actions/download-artifact@v6 + with: + name: codeowners-manifest + path: codeowners-manifest/ + + - name: Install dependencies + run: yarn install --immutable + env: + PUPPETEER_SKIP_DOWNLOAD: true + CYPRESS_INSTALL_BINARY: 0 + + - name: Generate team slug + id: team-slug + run: | + node -e " + const { createOwnerFilenameSlug } = require('./scripts/codeowners-manifest/utils.js'); + console.log('team-slug=' + createOwnerFilenameSlug('${{ matrix.team }}')); + " >> "$GITHUB_OUTPUT" + + - name: Run coverage for ${{ matrix.team }} + run: node scripts/test-coverage-by-codeowner.js "${{ matrix.team }}" + env: + CODEOWNER_NAME: ${{ matrix.team }} + SHOULD_OPEN_COVERAGE_REPORT: 'false' + CI: 'true' + + - name: Upload coverage summary + uses: actions/upload-artifact@v5 + with: + name: coverage-${{ matrix.branch }}-${{ steps.team-slug.outputs.team-slug }} + path: coverage-summary.json + retention-days: 1 + + compare-and-report: + name: Compare & Report - ${{ matrix.team }} + needs: [coverage] + runs-on: ubuntu-x64-small + permissions: + contents: read + pull-requests: write + id-token: write + strategy: + fail-fast: false + matrix: + team: *teams + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Setup Node.js + uses: ./.github/actions/setup-node + + - name: Generate team slug + id: team-slug + run: | + node -e " + const { createOwnerFilenameSlug } = require('./scripts/codeowners-manifest/utils.js'); + console.log('team-slug=' + createOwnerFilenameSlug('${{ matrix.team }}')); + " >> "$GITHUB_OUTPUT" + + - name: Download PR coverage + uses: actions/download-artifact@v6 + with: + name: coverage-pr-${{ steps.team-slug.outputs.team-slug }} + path: ./coverage-pr + + - name: Download Main coverage + uses: actions/download-artifact@v6 + with: + name: coverage-main-${{ steps.team-slug.outputs.team-slug }} + path: ./coverage-main + + - name: Install dependencies for comparison script + run: yarn install --immutable + env: + PUPPETEER_SKIP_DOWNLOAD: true + CYPRESS_INSTALL_BINARY: 0 + + - name: Compare coverage + id: compare + run: | + node scripts/compare-coverage-by-codeowner.js + { + echo "markdown<> "$GITHUB_OUTPUT" + + - name: Get Vault secrets + id: get-secrets + if: github.event.pull_request.head.repo.fork == false + uses: grafana/shared-workflows/actions/get-vault-secrets@main + with: + repo_secrets: | + GITHUB_APP_ID=grafana_pr_automation_app:app_id + GITHUB_APP_PRIVATE_KEY=grafana_pr_automation_app:app_pem + + - name: Generate GitHub App token + id: generate_token + if: github.event.pull_request.head.repo.fork == false + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ env.GITHUB_APP_ID }} + private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }} + + - name: Post PR comment + if: github.event.pull_request.head.repo.fork == false + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: coverage-report-${{ matrix.team }} + message: ${{ steps.compare.outputs.markdown }} + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}