Skip to content

Commit

Permalink
Incorporate feedback
Browse files Browse the repository at this point in the history
* Grab most recent PR labels
* Use octokit.rest.issues.addLabels() with a diff of labels
* Squash project labels into bigProjectLabel if too many
* Use template literals
* Handle more edge cases
  • Loading branch information
tbradsha committed Dec 13, 2024
1 parent 2893b33 commit 9661caa
Showing 1 changed file with 60 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { getInput } = require( '@actions/core' );
const debug = require( '../../utils/debug' );
const getFiles = require( '../../utils/get-files' );
const getLabels = require( '../../utils/labels/get-labels' );

/* global GitHub, WebhookPayloadPullRequest */

Expand Down Expand Up @@ -51,17 +52,16 @@ function cleanName( name ) {
/**
* Build a list of labels to add to the pull request, based off our file list.
*
* @param {GitHub} octokit - Initialized Octokit REST client.
* @param {string} owner - Repository owner.
* @param {string} repo - Repository name.
* @param {string} number - PR number.
* @param {boolean} isDraft - Whether the pull request is a draft.
* @param {boolean} isRevert - Whether the pull request is a revert.
* @param {string[]} curLabels - Current labels on the pull request.
* @param {GitHub} octokit - Initialized Octokit REST client.
* @param {string} owner - Repository owner.
* @param {string} repo - Repository name.
* @param {string} number - PR number.
* @param {boolean} isDraft - Whether the pull request is a draft.
* @param {boolean} isRevert - Whether the pull request is a revert.
* @return {Promise<Array>} Promise resolving to an array of keywords we'll search for.
*/
async function getLabelsToAdd( octokit, owner, repo, number, isDraft, isRevert, curLabels ) {
const keywords = new Set( curLabels );
async function getFileDerivedLabels( octokit, owner, repo, number, isDraft, isRevert ) {
const keywords = new Set();

// Get next valid milestone.
const files = await getFiles( octokit, owner, repo, number );
Expand Down Expand Up @@ -331,47 +331,79 @@ async function addLabels( payload, octokit ) {
const { owner, name } = repository;
const { draft, title } = pull_request;

// GitHub allows 100 labels on a PR.
// Limit to less than that to allow a buffer for future manual labels.
const maxLabels = 90;
const bigProjectLabel = '[Project] All the things!';

// Get labels to add to the PR.
const isDraft = !! ( pull_request && draft );

// If the PR title includes the word "revert", mark it as such.
const isRevert = title.toLowerCase().includes( 'revert' );

const currentLabels = payload.pull_request.labels.map( l => l.name );
let labelsToAdd = await getLabelsToAdd(
const fileDerivedLabels = await getFileDerivedLabels(
octokit,
owner.login,
name,
number,
isDraft,
isRevert,
currentLabels
isRevert
);

// Grab current labels on the PR.
// We can't rely on payload, as it could be outdated by the time this runs.
const currentLabels = await getLabels( octokit, owner.login, name, number );

// This is an array of labels that GitHub doesn't already have.
let labelsToAdd = fileDerivedLabels.filter( label => ! currentLabels.includes( label ) );

// Nothing new was added, so abort.
if ( labelsToAdd.length === currentLabels.length ) {
if ( labelsToAdd.length === 0 ) {
debug( 'add-labels: No new labels to add to that PR. Aborting.' );
return;
}

// GitHub allows 100 labels on a PR. Limit to less than that to allow for additional labels elsewhere.
const maxLabels = 90;
const bigLabel = 'All the things (>' + maxLabels + ' labels)';
if ( labelsToAdd.length > maxLabels ) {
debug(
'add-labels: GitHub only allows 100 labels on a PR, so limiting to the first ' +
maxLabels +
'.'
);
labelsToAdd.splice( maxLabels );
labelsToAdd.push( bigLabel );
} else if ( labelsToAdd.includes( bigLabel ) ) {
labelsToAdd = labelsToAdd.filter( label => label !== bigLabel );
// Determine how many labels can safely be added.
let maxLabelsToAdd = Math.max( 0, maxLabels - currentLabels.length );

// Overkill, but let's prevent this label from counting toward the max.
const hasBigProjectLabel = currentLabels.includes( bigProjectLabel );
if ( hasBigProjectLabel ) {
maxLabelsToAdd++;
}

// If there are too many labels, we need to reduce the label count to keep GitHub happy.
if ( labelsToAdd.length > maxLabelsToAdd ) {
debug( `add-labels: Too many labels! Grouping project labels into '${ bigProjectLabel }'.` );

// Filter out project-type labels in deference to bigProjectLabel.
// In theory we could also remove any existing project-type labels here, but for now
// let's not as that would prevent manually adding specific project labels.
const projectLabelRegex = /^(\[Action\]|\[Package\]|\[Plugin\]|\[JS Package\])/;
labelsToAdd = labelsToAdd.filter( label => ! projectLabelRegex.test( label ) );

if ( ! hasBigProjectLabel ) {
// Add to the beginning of the labels array in case the array gets truncated later on.
labelsToAdd.unshift( bigProjectLabel );
}
} else if ( hasBigProjectLabel ) {
await octokit.rest.issues.removeLabel( {
owner: owner.login,
repo: name,
issue_number: number,
name: bigProjectLabel,
} );
}
// In the rare chance there would still be too many labels...
if ( labelsToAdd.length > maxLabelsToAdd ) {
debug( `add-labels: Limiting to the first ${ maxLabels }.` );
labelsToAdd.splice( maxLabelsToAdd );
}

debug( `add-labels: Adding labels ${ labelsToAdd } to PR #${ number }` );

await octokit.rest.issues.setLabels( {
await octokit.rest.issues.addLabels( {
owner: owner.login,
repo: name,
issue_number: number,
Expand Down

0 comments on commit 9661caa

Please sign in to comment.