diff --git a/.github/scripts/pr-draft-nudge.js b/.github/scripts/pr-draft-nudge.js new file mode 100644 index 0000000..7b5c0c8 --- /dev/null +++ b/.github/scripts/pr-draft-nudge.js @@ -0,0 +1,60 @@ +module.exports = async ({ github, context, core }) => { + try { + if (process.env.PR_DRAFT_NUDGE_COMMENT_DISABLE === "true") { + core.info("PR draft nudge comment is disabled for this repository."); + return; + } + + const pr = context.payload.pull_request; + + if (!pr) { + core.info("This action is only applicable to pull requests."); + return; + } + + // We only want to comment on PRs that are opened ready for review with reviewers. + if ( + context.payload.action !== "opened" || + pr.draft || + !pr.requested_reviewers || + pr.requested_reviewers.length === 0 + ) { + core.info( + 'PR is a draft, has no reviewers, or this is not an "opened" event. Skipping.' + ); + return; + } + + const prCreator = pr.user.login; + const commentIdentifier = ""; + const commentBody = `:wave: @${prCreator}, thanks for creating this pull request!\n\nTo help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.\n\nOnce you're ready, you can mark it as "Ready for review" to request feedback. Thanks!\n\n${commentIdentifier}`; + + // Check if a comment with the identifier already exists + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + }); + + const existingComment = comments.find((comment) => + comment.body.includes(commentIdentifier) + ); + + if (existingComment) { + core.info("A PR draft nudge comment already exists on this PR."); + return; + } + + // Create the comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + body: commentBody, + }); + + core.info("Successfully posted PR draft nudge comment."); + } catch (error) { + core.setFailed(`Action failed with error: ${error.message}`); + } +}; diff --git a/.github/workflows/dependency-review-vulnerability-license.yml b/.github/workflows/dependency-review-vulnerability-license.yml index 4feb9c4..bab32cf 100644 --- a/.github/workflows/dependency-review-vulnerability-license.yml +++ b/.github/workflows/dependency-review-vulnerability-license.yml @@ -25,6 +25,7 @@ jobs: name: License and Vulnerabilities permissions: contents: read + pull-requests: write runs-on: ubuntu-latest # Skip on merge group events if: ${{ github.event_name == 'pull_request' }} diff --git a/.github/workflows/pr-draft-nudge.yml b/.github/workflows/pr-draft-nudge.yml new file mode 100644 index 0000000..a6061c7 --- /dev/null +++ b/.github/workflows/pr-draft-nudge.yml @@ -0,0 +1,36 @@ +### +# This workflow nudges users to mark their pull requests as draft if they are not ready for review. +# +# To disable the comment, set the `PR_DRAFT_NUDGE_COMMENT_DISABLE` variable in the repository settings to `true`. +# The default value is `false`, which means the comment will be posted. +# To set the variable, you can use the GitHub CLI: +# gh variable set PR_DRAFT_NUDGE_COMMENT_DISABLE --body "true" +### + +name: PR Draft Nudge + +on: + pull_request: + types: [opened] + +permissions: {} + +jobs: + pr-draft-nudge: + name: PR Draft Nudge + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v4 + + - name: Run + uses: actions/github-script@v7 + env: + PR_DRAFT_NUDGE_COMMENT_DISABLE: ${{ vars.PR_DRAFT_NUDGE_COMMENT_DISABLE || 'false' }} + with: + script: | + const script = require('./.github/scripts/pr-draft-nudge.js'); + await script({ github, context, core });