From 5ba8064d871be06025d142a97ef2e467f29c8107 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:54:27 +0200 Subject: [PATCH 1/2] build(deps): bump rollup from 2.79.1 to 2.79.2 (#1150) Bumps [rollup](https://github.com/rollup/rollup) from 2.79.1 to 2.79.2. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.79.1...v2.79.2) --- updated-dependencies: - dependency-name: rollup dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 11f52464..e65cbfb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8287,9 +8287,9 @@ rollup-plugin-terser@^7.0.0: terser "^5.0.0" rollup@^2.43.1: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + version "2.79.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.2.tgz#f150e4a5db4b121a21a747d762f701e5e9f49090" + integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ== optionalDependencies: fsevents "~2.3.2" From 22e3fae27e690c50ae3a3e02f83be4301b795632 Mon Sep 17 00:00:00 2001 From: Kylee Fields <43586156+kyleecodes@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:44:21 -0400 Subject: [PATCH 2/2] Actions: New PR labeling and issue link workflows (#1149) * Actions: New PR labeling and issue link workflows * Update issue/pr trigger workflows, remove dependabot workflow --- .../workflows/community-first-pr-comment.yml | 16 --- .github/workflows/community-issue-comment.yml | 4 +- .../workflows/community-pr-check-issue.yml | 22 ++++ .github/workflows/community-pr-labeler.yml | 30 +++++ .../workflows/community-stale-management.yml | 8 +- .github/workflows/dependabot-open-issues.yml | 28 ----- scripts/github-actions/checkPRLinkedIssue.js | 51 ++++++++ scripts/github-actions/prLabeling.js | 109 ++++++++++++++++++ scripts/github-actions/utils/postGHComment.js | 20 ++++ 9 files changed, 238 insertions(+), 50 deletions(-) delete mode 100644 .github/workflows/community-first-pr-comment.yml create mode 100644 .github/workflows/community-pr-check-issue.yml create mode 100644 .github/workflows/community-pr-labeler.yml delete mode 100644 .github/workflows/dependabot-open-issues.yml create mode 100644 scripts/github-actions/checkPRLinkedIssue.js create mode 100644 scripts/github-actions/prLabeling.js create mode 100644 scripts/github-actions/utils/postGHComment.js diff --git a/.github/workflows/community-first-pr-comment.yml b/.github/workflows/community-first-pr-comment.yml deleted file mode 100644 index e476f533..00000000 --- a/.github/workflows/community-first-pr-comment.yml +++ /dev/null @@ -1,16 +0,0 @@ -# This workflow comments on PRs opened by first time contributors. -# Reminds first timer contributors to associate their PR with an issue and follow the guidelines. -# See for more info: https://github.com/actions/first-interaction - -name: First Interaction PR Comment - -on: [pull_request] - -jobs: - greeting: - runs-on: ubuntu-latest - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: 'First time contributors to Chayn: Please make sure that this PR is linked to an issue you are assigned! We will not merge contributor PRs without a linked assigned issue. Please ask to be assigned an existing issue or create your own before opening a PR. Read our Contributing Guidelines in the CONTRIBUTING.md file for more details. Thank you for your contribution!' diff --git a/.github/workflows/community-issue-comment.yml b/.github/workflows/community-issue-comment.yml index 139e0f24..7a69bbd0 100644 --- a/.github/workflows/community-issue-comment.yml +++ b/.github/workflows/community-issue-comment.yml @@ -27,12 +27,12 @@ jobs: repo: context.repo.repo, issue_number: context.payload.issue.number, body: `Thank you @${context.payload.issue.assignee.login} you have been assigned this issue! - **Please follow the directions in our [Contributing Guide](https://github.com/chaynHQ/.github/blob/main/docs/CONTRIBUTING.md). We look forward to reviewing your pull request shortly ✨** + **Please follow the directions in our [Contributing Guide](https://github.com/chaynHQ/.github/blob/main/docs/CONTRIBUTING.md). We look forward to reviewing your pull request. ✨** --- Support Chayn's mission? ⭐ Please star this repo to help us find more contributors like you! - Learn more about Chayn [here](https://linktr.ee/chayn) and [explore our projects](https://org.chayn.co/projects). 🌸` + Learn more about Chayn and our impact [here](https://github.com/chaynHQ/.github/blob/main/profile/README.md). 🌸` }) # When issues are labeled as stale, a comment is posted. diff --git a/.github/workflows/community-pr-check-issue.yml b/.github/workflows/community-pr-check-issue.yml new file mode 100644 index 00000000..9f486176 --- /dev/null +++ b/.github/workflows/community-pr-check-issue.yml @@ -0,0 +1,22 @@ +name: Check Linked Issue on PR +on: + pull_request: + types: [opened, edited] + branches: + - "develop" + +jobs: + Check-For-Linked-Issue: + runs-on: ubuntu-latest + if: ${{ github.event.action == 'opened' || github.event.action == 'edited' }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check for keyword and issue number + id: check-for-keyword + uses: actions/github-script@v7 + with: + script: | + const script = require('./scripts/github-actions/checkPRLinkedIssue.js') + script({g: github, c: context}) diff --git a/.github/workflows/community-pr-labeler.yml b/.github/workflows/community-pr-labeler.yml new file mode 100644 index 00000000..3ef4cb63 --- /dev/null +++ b/.github/workflows/community-pr-labeler.yml @@ -0,0 +1,30 @@ +name: Auto-label PR from Linked Issue and Review Status + +on: + pull_request: + types: [opened, edited, synchronize] + pull_request_review: + types: [submitted, edited, dismissed] + +jobs: + auto-label: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm install @actions/github @actions/core + + - name: Run PR labeling script + uses: actions/github-script@v7 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const script = require('./scripts/github-actions/prLabeling.js') + await script({github, context, core}) diff --git a/.github/workflows/community-stale-management.yml b/.github/workflows/community-stale-management.yml index ee049d76..4ee44148 100644 --- a/.github/workflows/community-stale-management.yml +++ b/.github/workflows/community-stale-management.yml @@ -27,7 +27,6 @@ jobs: days-before-stale: 30 # disables closing issues days-before-issue-close: -1 - # close pr after 1 week no updates after stale warning days-before-pr-close: 7 # only scan assigned issues include-only-assigned: true @@ -39,6 +38,7 @@ jobs: exempt-pr-labels: dependencies # disable counting irrelevant activity (branch updates) towards day counter on prs. ignore-pr-updates: true - stale-pr-message: 'As per Chayn policy, after 30 days of inactivity, we will close this PR.' - close-pr-message: 'This PR has been closed due to inactivity.' - stale-issue-message: 'As per Chayn policy, after 30 days of inactivity, we will be unassigning this issue. Please comment to stay assigned.' + # messages skipped, instead handled by issue-comment.yml + stale-pr-message: '' + close-pr-message: '' + stale-issue-message: '' diff --git a/.github/workflows/dependabot-open-issues.yml b/.github/workflows/dependabot-open-issues.yml deleted file mode 100644 index ff0b82e7..00000000 --- a/.github/workflows/dependabot-open-issues.yml +++ /dev/null @@ -1,28 +0,0 @@ -# This workflow opens issues for pull requests opened by dependabot. -# See for more info: https://github.com/actions-cool/issues-helper - -name: Open Dependabot Issues # from pull requests - -on: - pull_request: - types: [opened] - branches: [develop] - -jobs: - create-issue: - runs-on: ubuntu-latest - permissions: - issues: write - if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }} - steps: - - name: Create issue - uses: actions-cool/issues-helper@v3 - with: - actions: 'create-issue' - token: ${{ secrets.GITHUB_TOKEN }} - title: ${{ github.event.pull_request.title }} - body: | - ### Dependabot opened a pull request to update a dependency. Please review it: ${{ github.event.pull_request.html_url }} - - [ ] Comment on this issue tagging Chayn staff (@kyleecodes) to be assigned this issue. - - [ ] Follow directions in the Chayn Dependency Upgrade Guide here: https://chayn.notion.site/Chayn-Tech-Contributor-Wiki-5356c7118c134863a2e092e9df6cbc34?pvs=4 - labels: 'dependencies' diff --git a/scripts/github-actions/checkPRLinkedIssue.js b/scripts/github-actions/checkPRLinkedIssue.js new file mode 100644 index 00000000..961bd90f --- /dev/null +++ b/scripts/github-actions/checkPRLinkedIssue.js @@ -0,0 +1,51 @@ +const postIssueComment = require('./utils/postGHComment'); + +async function main({ g, c }) { + const github = g; + const context = c; + + // Retrieve body of context.payload and search for GitHub keywords followed by + // '#' + number. Exclude any matches that are in a comment within the PR body + const prBody = context.payload.pull_request.body; + const prNumber = context.payload.pull_request.number; + const prOwner = context.payload.pull_request.user.login; + const exemptPrOwners = ['kyleecodes', 'swetha-charles', 'eleanorreem', 'annarhughes', 'tarebyte', 'dependabot[bot]', 'dependabot', 'github-actions[bot]', 'github-actions']; + const regex = + /(?!<!--)(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s*#(\d+)(?![^<]*-->)/gi; + const match = prBody.match(regex); + + let prComment; + + // if no issue linked in description and PR not owned by staff + if (!match && !exemptPrOwners.includes(prOwner)) { + console.log('PR does not have a properly linked issue.'); + prComment = `@${prOwner}, this Pull Request is not linked to a valid issue. Above, on the first line of your PR, please link the number of the issue that you worked on using the format of 'Resolves #' + issue number, for example: **_Fixes #9876_**\n\nNote: Do **_not_** use the number of this PR or URL for issue. Chayn staff may disregard this. A linked issue is required for automated PR labeling.`; + } else { + console.log(match[0]); + const [keyword, linkNumber] = match[0].replaceAll('#', '').split(' '); + console.log(`Found a keyword: \'${keyword}\'. Checking for legitimate linked issue...`); + + // Check if the linked issue exists in repo + // Issue get request: https://octokit.github.io/rest.js/v20#issues-get + try { + await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: linkNumber, + }); + console.log( + `Found an issue: \'#${linkNumber}\' in repo. Reference is a legitimate linked issue.`, + ); + } catch (error) { + console.log(`Couldn\'t find issue: \'#${linkNumber}\' in repo. Posting comment...`); + prComment = `@${prOwner}, the issue number referenced above as "**${keyword} #${linkNumber}**" is not found. Please replace with a valid issue number.`; + } + } + + // Post comment to PR + if (prComment) { + postIssueComment(prNumber, prComment, github, context); + } +} + +module.exports = main; diff --git a/scripts/github-actions/prLabeling.js b/scripts/github-actions/prLabeling.js new file mode 100644 index 00000000..068b782d --- /dev/null +++ b/scripts/github-actions/prLabeling.js @@ -0,0 +1,109 @@ +module.exports = async ({ github, context, core }) => { + const pr = context.payload.pull_request; + const bodyText = pr.body; + // regex to search for issue linked in description + const issuePattern = /(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s+#(\d+)/i; + const match = bodyText.match(issuePattern); + + // reset labels + async function removeAllLabels() { + const currentLabels = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + }); + + for (const label of currentLabels.data) { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + name: label.name, + }); + } + } + + if (!match) { + console.log('No linked issue found in the pull request description.'); + await removeAllLabels(); + return; + } + + // label PR with linked issue labels + const issueNumber = match[2]; + console.log(`Linked issue found: #${issueNumber}`); + + try { + const issue = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + }); + + const issueLabels = issue.data.labels.map((label) => label.name); + + // Remove all existing labels + await removeAllLabels(); + + if (issueLabels.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: issueLabels, + }); + console.log(`Added labels to PR: ${issueLabels.join(', ')}`); + } else { + console.log('No labels found on the linked issue.'); + } + + // Update review status label + const reviews = await github.rest.pulls.listReviews({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + }); + + let reviewStatus = { name: 'needs review', color: 'b60205' }; + if (reviews.data.length > 0) { + const latestReview = reviews.data[reviews.data.length - 1]; + switch (latestReview.state) { + case 'APPROVED': + reviewStatus = { name: 'review approved', color: '0E8A16' }; + break; + case 'CHANGES_REQUESTED': + reviewStatus = { name: 'changes requested', color: 'FBCA04' }; + break; + case 'COMMENTED': + reviewStatus = { name: 'review in progress', color: 'FBCA04' }; + break; + } + } + await github.rest.issues + .createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: reviewStatus.name, + color: reviewStatus.color, + }) + .catch((error) => { + if (error.status !== 422) { + // 422 means label already exists + throw error; + } + }); + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: [reviewStatus.name], + }); + console.log( + `Updated review status label: ${reviewStatus.name} with color: ${reviewStatus.color}`, + ); + } catch (error) { + console.error(`Error processing PR: ${error}`); + core.setFailed(`Error processing PR: ${error.message}`); + } +}; diff --git a/scripts/github-actions/utils/postGHComment.js b/scripts/github-actions/utils/postGHComment.js new file mode 100644 index 00000000..dbadb45c --- /dev/null +++ b/scripts/github-actions/utils/postGHComment.js @@ -0,0 +1,20 @@ +/** + * Posts a comment on GitHub issues and pull requests + * TODO: reduce repetition and use in other workflow scripts. + * @param {Number} issueNum - the issue number where the comment should be posted + * @param {String} comment - the comment to be posted + */ +async function postComment(issueNum, comment, github, context) { + try { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNum, + body: comment, + }); + } catch (err) { + throw new Error(err); + } +} + +module.exports = postComment;