diff --git a/.github/workflows/notify-author-attention.yml b/.github/workflows/notify-author-attention.yml new file mode 100644 index 0000000000..4799e9efd1 --- /dev/null +++ b/.github/workflows/notify-author-attention.yml @@ -0,0 +1,35 @@ +name: Notify Author attention needed + +on: + pull_request_target: + types: [labeled] + +jobs: + notify-author: + # Only run when 'Author attention needed' label is added to a PR + if: >- + github.repository == 'dotnet/SqlClient' && + github.event.label.name == 'Author attention needed' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Post comment to PR author + uses: actions/github-script@v9 + with: + script: | + const issue_number = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + const author = context.payload.pull_request.user.login; + + const body = `@${author} This pull request has been marked as **Author attention needed**.\n\nWhen you have addressed the reviewer feedback and are ready for another review, please post a comment with \`/ready\` to remove the label and re-engage reviewers.`; + + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body, + }); + core.info(`Posted notification comment on PR #${issue_number}`); diff --git a/.github/workflows/remove-author-attention-label.yml b/.github/workflows/remove-author-attention-label.yml new file mode 100644 index 0000000000..808de9b9c2 --- /dev/null +++ b/.github/workflows/remove-author-attention-label.yml @@ -0,0 +1,83 @@ +name: Remove Author attention needed Label + +on: + issue_comment: + types: [created] + +jobs: + remove-label: + # Only run on PR comments with '/ready' from the PR author + if: >- + github.repository == 'dotnet/SqlClient' && + github.event.issue.pull_request != null && + github.event.comment.user.login == github.event.issue.user.login && + startsWith(github.event.comment.body, '/ready') + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Remove 'Author attention needed' label + uses: actions/github-script@v9 + with: + script: | + const labelName = 'Author attention needed'; + const issue_number = context.issue.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + // Check if the label exists on the PR + const labels = await github.paginate(github.rest.issues.listLabelsOnIssue, { + owner, + repo, + issue_number, + per_page: 100, + }); + + const hasLabel = labels.some(label => label.name === labelName); + + if (!hasLabel) { + core.info(`PR #${issue_number} does not have the '${labelName}' label. No action taken.`); + return; + } + + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number, + name: labelName, + }); + core.info(`Removed '${labelName}' label from PR #${issue_number}`); + + // Re-request reviews from existing reviewers (paginate to include all reviews) + const reviews = await github.paginate(github.rest.pulls.listReviews, { + owner, + repo, + pull_number: issue_number, + per_page: 100, + }); + + // Collect unique reviewers (exclude the PR author) + const author = context.payload.issue.user.login; + const reviewers = [...new Set( + reviews + .filter(r => r.user?.type === 'User') + .map(r => r.user?.login) + .filter(login => login && login !== author) + )]; + + if (reviewers.length > 0) { + try { + await github.rest.pulls.requestReviewers({ + owner, + repo, + pull_number: issue_number, + reviewers: reviewers.slice(0, 15), + }); + core.info(`Re-requested reviews from: ${reviewers.join(', ')}`); + } catch (err) { + core.warning(`Failed to re-request reviewers: ${err.message}`); + } + } else { + core.info('No previous reviewers to re-request.'); + }