diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index 8316fedda0..447e559c90 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -5,7 +5,7 @@ on: jobs: labeler: - name: apply labels + name: review permissions: contents: read pull-requests: write @@ -14,17 +14,17 @@ jobs: - uses: actions/checkout@v4 with: submodules: false + + # Label PRs - uses: actions/labeler@v5.0.0 with: dot: true configuration-path: .github/labeler.yaml - pr_branch_check: - name: check branch - runs-on: ubuntu-latest - if: github.repository == 'commaai/openpilot' - steps: - - uses: Vankka/pr-target-branch-action@def32ec9d93514138d6ac0132ee62e120a72aed5 + # Check PR target branch + - name: check branch + uses: Vankka/pr-target-branch-action@def32ec9d93514138d6ac0132ee62e120a72aed5 + if: github.repository == 'commaai/openpilot' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -34,194 +34,20 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" - comment: - runs-on: ubuntu-latest - steps: - - name: comment - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 - if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' - with: - message: | - - Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: - * Convert your PR to a draft unless it's ready to review - * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) - * Before marking as "ready for review", ensure: - * the goal is clearly stated in the description - * all the tests are passing - * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) - * include a route or your device' dongle ID if relevant - comment_tag: run_id - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - check-pr-template: - runs-on: ubuntu-latest - permissions: - contents: read - issues: write - pull-requests: write - actions: read - if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' - steps: - - uses: actions/github-script@v7 - with: - script: | - // Comment to add to the PR if no template has been used - const NO_TEMPLATE_MESSAGE = - "It looks like you didn't use one of the Pull Request templates. Please check [the contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md). \ - Also make sure that you didn't modify any of the checkboxes or headings within the template."; - // body data for future requests - const body_data = { - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }; - - // Utility function to extract all headings - const extractHeadings = (markdown) => { - const headingRegex = /^(#{1,6})\s+(.+)$/gm; - const boldTextRegex = /^(?:\*\*|__)(.+?)(?:\*\*|__)\s*$/gm; - const headings = []; - let headingMatch; - while ((headingMatch = headingRegex.exec(markdown))) { - headings.push(headingMatch[2].trim()); - } - let boldMatch; - while ((boldMatch = boldTextRegex.exec(markdown))) { - headings.push(boldMatch[1].trim()); - } - return headings; - }; - - // Utility function to extract all check box descriptions - const extractCheckBoxTexts = (markdown) => { - const checkboxRegex = /^\s*-\s*\[( |x)\]\s+(.+)$/gm; - const checkboxes = []; - let match; - while ((match = checkboxRegex.exec(markdown))) { - checkboxes.push(match[2].trim()); - } - return checkboxes; - }; - - // Utility function to check if a list is a subset of another list - isSubset = (subset, superset) => { - return subset.every((item) => superset.includes(item)); - }; - - // Utility function to check if a list of checkboxes is a subset of another list of checkboxes - isCheckboxSubset = (templateCheckBoxTexts, prTextCheckBoxTexts) => { - // Check if each template checkbox text is a substring of at least one PR checkbox text - // (user should be allowed to add additional text) - return templateCheckBoxTexts.every((item) => prTextCheckBoxTexts.some((element) => element.includes(item))) - } - - // Get filenames of all currently checked-in PR templates - const template_contents = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: ".github/PULL_REQUEST_TEMPLATE", - }); - var template_filenames = []; - for (const content of template_contents.data) { - template_filenames.push(content.path); - } - console.debug("Received template filenames: " + template_filenames); - // Retrieve templates - var templates = []; - for (const template_filename of template_filenames) { - const template_response = await github.rest.repos.getContent({ - owner: context.repo.owner, - repo: context.repo.repo, - path: template_filename, - }); - // Convert Base64 content back - const decoded_template = atob(template_response.data.content); - const headings = extractHeadings(decoded_template); - const checkboxes = extractCheckBoxTexts(decoded_template); - if (!headings.length && !checkboxes.length) { - console.warn( - "Invalid template! Contains neither headings nor checkboxes, ignoring it: \n" + - decoded_template - ); - } else { - templates.push({ headings: headings, checkboxes: checkboxes }); - } - } - // Retrieve the PR Body - const pull_request = await github.rest.issues.get({ - ...body_data, - }); - const pull_request_text = pull_request.data.body; - console.debug("Received Pull Request body: \n" + pull_request_text); - - /* Check if the PR Body matches one of the templates - A template is defined by all headings and checkboxes it contains - We extract all Headings and Checkboxes from the PR text and check if any of the templates is a subset of that - */ - const pr_headings = extractHeadings(pull_request_text); - const pr_checkboxes = extractCheckBoxTexts(pull_request_text); - console.debug("Found Headings in PR body:\n" + pr_headings); - console.debug("Found Checkboxes in PR body:\n" + pr_checkboxes); - var template_found = false; - // Iterate over each template to check if it applies - for (const template of templates) { - console.log( - "Checking for headings: [" + - template.headings + - "] and checkboxes: [" + - template.checkboxes + "]" - ); - if ( - isCheckboxSubset(template.checkboxes, pr_checkboxes) && - isSubset(template.headings, pr_headings) - ) { - console.debug("Found matching template!"); - template_found = true; - } - } - - // List comments from previous runs - var existing_comments = []; - const comments = await github.rest.issues.listComments({ - ...body_data, - }); - for (const comment of comments.data) { - if (comment.body === NO_TEMPLATE_MESSAGE) { - existing_comments.push(comment); - } - } - - // Add a comment to the PR that it is not using a the template (but only if this comment does not exist already) - if (!template_found) { - var comment_already_sent = false; - - // Add an 'in-bot-review' label since this PR doesn't have the template - github.rest.issues.addLabels({ - ...body_data, - labels: ["in-bot-review"], - }); - - if (existing_comments.length < 1) { - github.rest.issues.createComment({ - ...body_data, - body: NO_TEMPLATE_MESSAGE, - }); - } - } else { - // If template has been found, delete any old comment about missing template - for (const existing_comment of existing_comments) { - github.rest.issues.deleteComment({ - ...body_data, - comment_id: existing_comment.id, - }); - } - // Remove the 'in-bot-review' label after the review is done and the PR has passed - github.rest.issues.removeLabel({ - ...body_data, - name: "in-bot-review", - }).catch((error) => { - console.log("Label 'in-bot-review' not found, ignoring"); - }); - } - + # Welcome comment + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + with: + message: | + + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + comment_tag: run_id + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}