Skip to content

Commit

Permalink
Actions: New PR labeling and issue link workflows (#1149)
Browse files Browse the repository at this point in the history
* Actions: New PR labeling and issue link workflows

* Update issue/pr trigger workflows, remove dependabot workflow
  • Loading branch information
kyleecodes authored Oct 4, 2024
1 parent 5ba8064 commit 22e3fae
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 50 deletions.
16 changes: 0 additions & 16 deletions .github/workflows/community-first-pr-comment.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/community-issue-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/community-pr-check-issue.yml
Original file line number Diff line number Diff line change
@@ -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})
30 changes: 30 additions & 0 deletions .github/workflows/community-pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -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})
8 changes: 4 additions & 4 deletions .github/workflows/community-stale-management.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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: ''
28 changes: 0 additions & 28 deletions .github/workflows/dependabot-open-issues.yml

This file was deleted.

51 changes: 51 additions & 0 deletions scripts/github-actions/checkPRLinkedIssue.js
Original file line number Diff line number Diff line change
@@ -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;
109 changes: 109 additions & 0 deletions scripts/github-actions/prLabeling.js
Original file line number Diff line number Diff line change
@@ -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}`);
}
};
20 changes: 20 additions & 0 deletions scripts/github-actions/utils/postGHComment.js
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 22e3fae

Please sign in to comment.