Bump Microsoft.AspNetCore.Components.WebAssembly from 8.0.24 to 8.0.2… #136
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: GC Auto Approve | ||
| on: | ||
| workflow_run: | ||
| workflows: ["Code Quality", "Build and Push F1 API", "CodeQL"] | ||
| types: [completed] | ||
| permissions: | ||
| contents: read | ||
| checks: read | ||
| pull-requests: write | ||
| jobs: | ||
| approve-pr: | ||
| runs-on: ubuntu-latest | ||
| if: ${{ secrets.GC_PAT != '' }} | ||
| steps: | ||
| - name: GC Approval | ||
| uses: actions/github-script@v8 | ||
| with: | ||
| github-token: ${{ secrets.GC_PAT }} | ||
| script: | | ||
| const run = context.payload.workflow_run; | ||
| if (run.event !== 'pull_request') { | ||
| core.info(`Skipping: workflow_run event is '${run.event}', not 'pull_request'.`); | ||
| return; | ||
| } | ||
| if (!run.pull_requests || run.pull_requests.length === 0) { | ||
| core.info('Skipping: no pull request found on workflow_run payload.'); | ||
| return; | ||
| } | ||
| const pullNumber = run.pull_requests[0].number; | ||
| const pr = await github.rest.pulls.get({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: pullNumber | ||
| }); | ||
| if (pr.data.state !== 'open') { | ||
| core.info(`Skipping: PR #${pullNumber} is not open.`); | ||
| return; | ||
| } | ||
| const headSha = pr.data.head.sha; | ||
| const authUser = await github.rest.users.getAuthenticated(); | ||
| const reviewerLogin = authUser.data.login; | ||
| const existingReviews = await github.paginate(github.rest.pulls.listReviews, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: pullNumber, | ||
| per_page: 100 | ||
| }); | ||
| const hasApprovalForHead = existingReviews.some((review) => | ||
| review.user?.login === reviewerLogin && | ||
| review.state === 'APPROVED' && | ||
| review.commit_id === headSha | ||
| ); | ||
| if (hasApprovalForHead) { | ||
| core.info(`Skipping: ${reviewerLogin} already approved head commit ${headSha}.`); | ||
| return; | ||
| } | ||
| const checkRuns = await github.paginate(github.rest.checks.listForRef, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| ref: headSha, | ||
| per_page: 100 | ||
| }); | ||
| // Exclude this workflow's own check run to avoid self-blocking while in progress. | ||
| const relevantRuns = checkRuns.filter((check) => !check.name.startsWith('GC Auto Approve /')); | ||
| if (relevantRuns.length === 0) { | ||
| core.info('Skipping: no relevant check runs found for PR head commit.'); | ||
| return; | ||
| } | ||
| const notCompleted = relevantRuns.filter((check) => check.status !== 'completed'); | ||
| if (notCompleted.length > 0) { | ||
| core.info(`Skipping: waiting for checks to complete: ${notCompleted.map((c) => c.name).join(', ')}`); | ||
| return; | ||
| } | ||
| const invalidConclusions = relevantRuns.filter( | ||
| (check) => check.conclusion !== 'success' && check.conclusion !== 'skipped' | ||
| ); | ||
| if (invalidConclusions.length > 0) { | ||
| core.info( | ||
| `Skipping: checks not in success/skipped state: ${invalidConclusions | ||
| .map((c) => `${c.name}=${c.conclusion}`) | ||
| .join(', ')}` | ||
| ); | ||
| return; | ||
| } | ||
| const unresolvedQuery = ` | ||
| query($owner: String!, $repo: String!, $pullNumber: Int!, $cursor: String) { | ||
| repository(owner: $owner, name: $repo) { | ||
| pullRequest(number: $pullNumber) { | ||
| reviewThreads(first: 100, after: $cursor) { | ||
| nodes { | ||
| isResolved | ||
| } | ||
| pageInfo { | ||
| hasNextPage | ||
| endCursor | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| `; | ||
| let unresolvedThreadCount = 0; | ||
| let cursor = null; | ||
| do { | ||
| const response = await github.graphql(unresolvedQuery, { | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pullNumber, | ||
| cursor | ||
| }); | ||
| const threads = response.repository.pullRequest.reviewThreads; | ||
| unresolvedThreadCount += threads.nodes.filter((thread) => !thread.isResolved).length; | ||
| cursor = threads.pageInfo.hasNextPage ? threads.pageInfo.endCursor : null; | ||
| } while (cursor); | ||
| if (unresolvedThreadCount > 0) { | ||
| core.info(`Skipping: unresolved review threads: ${unresolvedThreadCount}`); | ||
| return; | ||
| } | ||
| const verifiedChecks = relevantRuns.map((check) => ({ | ||
| name: check.name, | ||
| conclusion: check.conclusion | ||
| })); | ||
| const body = [ | ||
| 'GC Agent Auto-Review', | ||
| '', | ||
| 'Verified checks:', | ||
| ...verifiedChecks.map((check) => `- ${check.name}: ${check.conclusion}`), | ||
| '- All review comments resolved', | ||
| '', | ||
| '```json', | ||
| JSON.stringify( | ||
| { | ||
| decision: 'APPROVE', | ||
| verifiedChecks, | ||
| unresolvedReviewThreads: unresolvedThreadCount, | ||
| headSha | ||
| }, | ||
| null, | ||
| 2 | ||
| ), | ||
| '```' | ||
| ].join('\n'); | ||
| await github.rest.pulls.createReview({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| pull_number: pullNumber, | ||
| event: 'APPROVE', | ||
| body | ||
| }); | ||