Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create add-issue-labels-to-pr.yml #1740

Merged
merged 9 commits into from
Jun 16, 2021
139 changes: 139 additions & 0 deletions .github/workflows/add-issue-labels-to-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Name that appears on the workflow
name: Add Linked Issue Labels to Pull Request
on:
pull_request:
types: [opened, edited]
jobs:
# Adds linked issue labels to pull request
# Step1: Reads pull request comment and return the linked issue
# Step2: Perform a GET request to retrieve labels from linked issue
# Step3: Perform a PUT request to apply labels to original pull request
# Note: Step1 uses RegEx to extract linked issues. This is not the best choice, but is required as GitHub does not include linked issues in the context. If this changes in the future, please revise Step1 ASAP for a more robust code.
# Note2: Below you will see ${{ github }} and the github variable used. The former is a context from GitHub actions and the latter is an object argument of the actions/github-script@v4 workflow. These two are not the same and should not be treated as such!
Add-Linked-Issue-Labels-to-Pull-Request:
runs-on: ubuntu-latest
steps:
- name: Retrieve Linked Issue From Comment
# https://github.com/actions/github-script
uses: actions/github-script@v4
# Escapes user input for injection attacks
env:
BODY: ${{ github.event.pull_request.body }}
id: issue-number
with:
result-encoding: string
script: |
// Retrieve comments
const { BODY } = process.env

// Create RegEx for capturing KEYWORD #ISSUE-NUMBER syntax (i.e. resolves #1234)
const KEYWORDS = ['close', 'closes', 'closed', 'fix', 'fixes', 'fixed', 'resolve', 'resolves', 'resolved']
let reArr = []
for (const word of KEYWORDS) {
reArr.push(`[\\n|\\s|^]${word} #\\d*\\s|^${word} #\\d*\\s|\\s${word} #\\d*$|^${word} #\\d*$`)
akibrhast marked this conversation as resolved.
Show resolved Hide resolved
}

// Receive and unpack matches into an Array of Array objs
let re = new RegExp(reArr.join('|'), 'gi')
let match = BODY.matchAll(re)
match = [...match]

// If only one match is found, return the issue number. Else return false. Also console.log results.
if (match.length == 1) {
const linkedIssue = match[0][0]
const issueNumber = match[0][0].match(/\d+/)
console.log(`Issue number found for PR #${context.payload.number}. Issue #${issueNumber}`)
return issueNumber[0]
} else {
console.log('Make sure there is only one issue!')
return false
}


# https://docs.github.com/en/rest/reference/issues#list-labels-for-an-issue
- name: Get Labels from Linked Issue
uses: actions/github-script@v4
id: linked-labels
with:
script: |
// Retrieve issue number from previous step.
const issueNum = ${{ steps.issue-number.outputs.result }}
if (!issueNum) {
return false
}

// GET request to retrieve data from results of request
// https://octokit.github.io/rest.js/v18#issues-list-labels-on-issue
let data;
try {
const results = await github.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNum,
});
data = results.data
}
catch(err) {
console.log('Error with GET Request to get labels')
console.log(err)
return false
}

// Gather all label names into an array of strings and return the array
let labelNameArray = []
for (const label of data) {
labelNameArray.push(label.name)
}
console.log(`Labels found on Issue #${issueNum}: ${labelNameArray.join(', ')}`)
return labelNameArray


# https://docs.github.com/en/rest/reference/issues#set-labels-for-an-issue
- name: Put Labels to Pull Request
uses: actions/github-script@v4
id: final-result
with:
github-token: ${{ secrets.GH_BOT_TOKEN_1 }}
script: |
// Retrieve labels from previous step
const arrayOfLabels = ${{ steps.linked-labels.outputs.result }}
if (!arrayOfLabels) {
return false
}

// PUT request to apply labels to pull request
// https://octokit.github.io/rest.js/v18#issues-add-labels
let results;
try {
results = await github.issues.setLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ github.event.number }},
labels: arrayOfLabels,
})
}
catch(err) {
console.log('Error with PUT Request to edit labels')
console.log(err)
return false
}

// Log result of script
console.log(results)
if (results.status == 200) {
return true
} else {
return false
}


# For use if there are follow-up actions following script success or failure.
- name: Return Failure
if: steps.final-result.outputs.result == 'false'
run: |
echo "Please expand above outputs for errors."
exit 1
- name: Return Success
run: |
echo "${{ steps.final-result.outputs.result }}"
echo "Success"