1
0
mirror of synced 2025-12-19 18:10:59 -05:00

Add actions label maker (#51133)

Co-authored-by: Grace Park <gracepark@github.com>
Co-authored-by: Evan Bonsignori <ebonsignori@github.com>
This commit is contained in:
Robert Sese
2024-06-13 16:29:27 -05:00
committed by GitHub
parent 712ce0eb8f
commit df6cb10c4b
3 changed files with 257 additions and 0 deletions

33
.github/actions/labeler/action.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Labeler
description: Adds labels to an Issue or PR
inputs:
token:
description: defaults to GITHUB_TOKEN, otherwise can use a PAT
required: false
default: ${{ github.token }}
addLabels:
description: array of labels to apply
required: false
removeLabels:
description: array of labels to remove
required: false
ignoreIfAssigned:
description: don't apply labels if there are assignees
required: false
ignoreIfLabeled:
description: don't apply labels if there are already labels added
required: false
runs:
using: 'composite'
steps:
- name: Add label to an issue or pr
run: node .github/actions/labeler/labeler.js
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.token }}
ADD_LABELS: ${{ inputs.addLabels }}
REMOVE_LABELS: ${{ inputs.removeLabels }}
IGNORE_IF_ASSIGNED: ${{ inputs.ignoreIfAssigned }}
IGNORE_IF_LABELED: ${{ inputs.ignoreIfLabeled }}

160
.github/actions/labeler/labeler.js vendored Normal file
View File

@@ -0,0 +1,160 @@
/* See function main in this file for documentation */
import coreLib from '@actions/core'
import github from '#src/workflows/github.js'
import { getActionContext } from '#src/workflows/action-context.js'
import { boolEnvVar } from '#src/workflows/get-env-inputs.js'
// When this file is invoked directly from action as opposed to being imported
if (import.meta.url.endsWith(process.argv[1])) {
if (!process.env.GITHUB_TOKEN) {
throw new Error('You must set the GITHUB_TOKEN environment variable.')
}
const { ADD_LABELS, REMOVE_LABELS } = process.env
const octokit = github()
const opts = {
addLabels: ADD_LABELS,
removeLabels: REMOVE_LABELS,
ignoreIfAssigned: boolEnvVar('IGNORE_IF_ASSIGNED'),
ignoreIfLabeled: boolEnvVar('IGNORE_IF_LABELED'),
}
// labels come in comma separated from actions
let addLabels
if (opts.addLabels) {
addLabels = [...opts.addLabels.split(',')]
opts.addLabels = addLabels.map((l) => l.trim())
} else {
opts.addLabels = []
}
let removeLabels
if (opts.removeLabels) {
removeLabels = [...opts.removeLabels.split(',')]
opts.removeLabels = removeLabels.map((l) => l.trim())
} else {
opts.removeLabels = []
}
const actionContext = getActionContext()
const { owner, repo } = actionContext
let issueOrPrNumber = actionContext?.pull_request?.number
if (!issueOrPrNumber) {
issueOrPrNumber = actionContext?.issue?.number
}
opts.issue_number = issueOrPrNumber
opts.owner = owner
opts.repo = repo
main(coreLib, octokit, opts, {})
}
/*
* Applies labels to an issue or pull request.
*
* opts:
* issue_number {number} id of the issue or pull request to label
* owner {string} owner of the repository
* repo {string} repository name
* addLabels {Array<string>} array of labels to apply
* removeLabels {Array<string>} array of labels to remove
* ignoreIfAssigned {boolean} don't apply labels if there are assignees
* ignoreIfLabeled {boolean} don't apply labels if there are already labels added
*/
export default async function main(core, octokit, opts = {}) {
if (opts.addLabels?.length === 0 && opts.removeLabels?.length === 0) {
core.info('No labels to add or remove specified, nothing to do.')
return
}
if (opts.ignoreIfAssigned || opts.ignoreIfLabeled) {
try {
const { data } = await octokit.issues.get({
issue_number: opts.issue_number,
owner: opts.owner,
repo: opts.repo,
})
if (opts.ignoreIfAssigned) {
if (data.assignees.length > 0) {
core.info(
`ignore-if-assigned is true: not applying labels since there's ${data.assignees.length} assignees`,
)
return 0
}
}
if (opts.ignoreIfLabeled) {
if (data.labels.length > 0) {
core.info(
`ignore-if-labeled is true: not applying labels since there's ${data.labels.length} labels applied`,
)
return 0
}
}
} catch (err) {
throw new Error(`Error getting issue: ${err}`)
}
}
if (opts.removeLabels?.length > 0) {
// removing a label fails if the label isn't already applied
let appliedLabels = []
try {
const { data } = await octokit.issues.get({
issue_number: opts.issue_number,
owner: opts.owner,
repo: opts.repo,
})
appliedLabels = data.labels.map((l) => l.name)
} catch (err) {
throw new Error(`Error getting issue: ${err}`)
}
opts.removeLabels = opts.removeLabels.filter((l) => appliedLabels.includes(l))
await Promise.all(
opts.removeLabels.map(async (label) => {
try {
await octokit.issues.removeLabel({
issue_number: opts.issue_number,
owner: opts.owner,
repo: opts.repo,
name: label,
})
} catch (err) {
throw new Error(`Error removing label: ${err}`)
}
}),
)
if (opts.removeLabels.length > 0) {
core.info(`Removed labels: ${opts.removeLabels.join(', ')}`)
}
}
if (opts.addLabels?.length > 0) {
try {
await octokit.issues.addLabels({
issue_number: opts.issue_number,
owner: opts.owner,
repo: opts.repo,
labels: opts.addLabels,
})
core.info(`Added labels: ${opts.addLabels.join(', ')}`)
} catch (err) {
throw new Error(`Error adding label: ${err}`)
}
}
}

64
src/workflows/labeler.ts Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env node
// [start-readme]
//
// This script adds labels to issues or pull requests.
//
// [end-readme]
import { program } from 'commander'
import label from '../../.github/actions/labeler/labeler.js'
import { getCoreInject } from '@/links/scripts/action-injections'
import github from '@/workflows/github.js'
program
.description('Add labels to an issue or PR.')
.option('--id <ID>', 'Id of the issue or PR to label')
.option('--add-labels <LABELS>', 'Labels to add, comma separated if more than one')
.option('--remove-labels <LABELS>', 'Labels to remove, comma separated if more than one')
.option('--repo <REPOSITORY>', 'Which repository to apply labels to in owner/repo format')
.option('--ignore-if-assigned', "Don't apply labels if there are assignees")
.option('--ignore-if-labeled', "Don't apply labels if there are already labels applied")
.parse(process.argv)
const opts = program.opts()
const octokit = github()
let addLabels = []
if (opts.addLabels) {
addLabels = [...opts.addLabels.split(',')]
addLabels = addLabels.map((l) => l.trim())
}
let removeLabels = []
if (opts.removeLabels) {
removeLabels = [...opts.removeLabels.split(',')]
removeLabels = removeLabels.map((l) => l.trim())
}
if (!process.env.GITHUB_TOKEN) {
throw new Error('You must set the GITHUB_TOKEN environment variable.')
}
if (!opts.repo) {
throw new Error('You must provide the repository that contains the issue with the --repo flag.')
}
if (!opts.id) {
throw new Error(
'You must provide the number of the issue where the labels will be applied with the --id flag',
)
}
const [owner, repo] = opts.repo.split('/')
const issueNumber = opts.id
label(getCoreInject(opts.debug), octokit, {
addLabels,
removeLabels,
repo,
owner,
issue_number: issueNumber,
ignoreIfAssigned: opts.ignoreIfAssigned,
ignoreIfLabeled: opts.ignoreIfLabeled,
})