From d42c910cc5f25887ad926e87c987c9e6c1686a9b Mon Sep 17 00:00:00 2001 From: psavelis Date: Tue, 11 Nov 2025 13:59:39 -0300 Subject: [PATCH] feat: support multiple issues --- dist/index.js | 61 +++++++++++++++++++++--------------------- src/main.ts | 74 ++++++++++++++++++++++++++++----------------------- 2 files changed, 71 insertions(+), 64 deletions(-) diff --git a/dist/index.js b/dist/index.js index 50be49a..a8ee774 100644 --- a/dist/index.js +++ b/dist/index.js @@ -91,12 +91,7 @@ const github_1 = __nccwpck_require__(2819); const getTeams_1 = __importDefault(__nccwpck_require__(2430)); const getIssueByTeamAndNumber_1 = __importDefault(__nccwpck_require__(4615)); const addLabels_1 = __importDefault(__nccwpck_require__(38)); -const getIdsFromInput = (input) => { - if (!input.trim()) { - return []; - } - return input.split(",").map((id) => id.trim()); -}; +const getIdsFromInput = (input) => input.trim() ? input.split(",").map((id) => id.trim()) : []; const main = async () => { try { const prTitle = github_1.context?.payload?.pull_request?.title; @@ -111,12 +106,8 @@ const main = async () => { (0, core_1.setFailed)(`Could not load PR branch`); return; } - const prBody = github_1.context?.payload?.pull_request?.body; + const prBody = github_1.context?.payload?.pull_request?.body ?? ""; (0, core_1.debug)(`PR Body: ${prBody}`); - if (prBranch === undefined) { - (0, core_1.setFailed)(`Could not load PR body`); - return; - } const apiKey = (0, core_1.getInput)("linear-api-key", { required: true }); const linearClient = new sdk_1.LinearClient({ apiKey }); const teams = await (0, getTeams_1.default)(linearClient); @@ -125,33 +116,43 @@ const main = async () => { return; } const labelIds = getIdsFromInput((0, core_1.getInput)("linear-issue-label-ids")); + const haystack = prBranch + " " + prTitle + " " + prBody; + const foundIssues = []; + const processedIssueIds = new Set(); for (const team of teams) { - // TODO: Iterate over multiple matches and not just first match const regexString = `${team.key}-(?\\d+)`; const regex = new RegExp(regexString, "gim"); - const haystack = prBranch + " " + prTitle + " " + prBody; (0, core_1.debug)(`Checking PR for indentifier "${regexString}" in "${haystack}"`); - const check = regex.exec(haystack); - const issueNumber = check?.groups?.issueNumber; - if (issueNumber) { - (0, core_1.debug)(`Found issue number: ${issueNumber}`); - const issue = await (0, getIssueByTeamAndNumber_1.default)(linearClient, team, Number(issueNumber)); - if (issue) { - (0, addLabels_1.default)(linearClient, issue, labelIds); - (0, core_1.setOutput)("linear-team-id", team.id); - (0, core_1.setOutput)("linear-team-key", team.key); - (0, core_1.setOutput)("linear-issue-id", issue.id); - (0, core_1.setOutput)("linear-issue-number", issue.number); - (0, core_1.setOutput)("linear-issue-identifier", issue.identifier); - (0, core_1.setOutput)("linear-issue-url", issue.url); - (0, core_1.setOutput)("linear-issue-title", issue.title); - (0, core_1.setOutput)("linear-issue-description", issue.description); - return; + const matches = [...haystack.matchAll(regex)]; + for (const match of matches) { + const issueNumber = match.groups?.issueNumber; + if (issueNumber) { + (0, core_1.debug)(`Found issue number: ${issueNumber}`); + const issue = await (0, getIssueByTeamAndNumber_1.default)(linearClient, team, Number(issueNumber)); + if (issue && !processedIssueIds.has(issue.id)) { + processedIssueIds.add(issue.id); + await (0, addLabels_1.default)(linearClient, issue, labelIds); + foundIssues.push(issue); + } } } } + if (foundIssues.length > 0) { + const firstIssue = foundIssues[0]; + const firstTeam = teams.find((t) => firstIssue.identifier.startsWith(t.key)); + if (firstTeam) { + (0, core_1.setOutput)("linear-team-id", firstTeam.id); + (0, core_1.setOutput)("linear-team-key", firstTeam.key); + } + (0, core_1.setOutput)("linear-issue-id", firstIssue.id); + (0, core_1.setOutput)("linear-issue-number", firstIssue.number); + (0, core_1.setOutput)("linear-issue-identifier", firstIssue.identifier); + (0, core_1.setOutput)("linear-issue-url", firstIssue.url); + (0, core_1.setOutput)("linear-issue-title", firstIssue.title); + (0, core_1.setOutput)("linear-issue-description", firstIssue.description); + return; + } (0, core_1.setFailed)(`Failed to find Linear issue identifier in PR branch, title, or body.`); - return; } catch (error) { (0, core_1.setFailed)(`${error?.message ?? error}`); diff --git a/src/main.ts b/src/main.ts index 720edff..d651839 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,12 +5,8 @@ import getTeams from "./getTeams"; import getIssueByTeamAndNumber from "./getIssueByTeamAndNumber"; import addLabels from "./addLabels"; -const getIdsFromInput = (input: string): string[] => { - if (!input.trim()) { - return []; - } - return input.split(",").map((id) => id.trim()); -}; +const getIdsFromInput = (input: string): string[] => + input.trim() ? input.split(",").map((id) => id.trim()) : []; const main = async () => { try { @@ -28,12 +24,8 @@ const main = async () => { return; } - const prBody = context?.payload?.pull_request?.body; + const prBody = context?.payload?.pull_request?.body ?? ""; debug(`PR Body: ${prBody}`); - if (prBranch === undefined) { - setFailed(`Could not load PR body`); - return; - } const apiKey = getInput("linear-api-key", { required: true }); const linearClient = new LinearClient({ apiKey }); @@ -44,41 +36,55 @@ const main = async () => { } const labelIds = getIdsFromInput(getInput("linear-issue-label-ids")); + const haystack = prBranch + " " + prTitle + " " + prBody; + const foundIssues = []; + const processedIssueIds = new Set(); + for (const team of teams) { - // TODO: Iterate over multiple matches and not just first match const regexString = `${team.key}-(?\\d+)`; const regex = new RegExp(regexString, "gim"); - const haystack = prBranch + " " + prTitle + " " + prBody; debug(`Checking PR for indentifier "${regexString}" in "${haystack}"`); - const check = regex.exec(haystack); - const issueNumber = check?.groups?.issueNumber; - if (issueNumber) { - debug(`Found issue number: ${issueNumber}`); - const issue = await getIssueByTeamAndNumber( - linearClient, - team, - Number(issueNumber), - ); - if (issue) { - addLabels(linearClient, issue, labelIds); - setOutput("linear-team-id", team.id); - setOutput("linear-team-key", team.key); - setOutput("linear-issue-id", issue.id); - setOutput("linear-issue-number", issue.number); - setOutput("linear-issue-identifier", issue.identifier); - setOutput("linear-issue-url", issue.url); - setOutput("linear-issue-title", issue.title); - setOutput("linear-issue-description", issue.description); - return; + const matches = [...haystack.matchAll(regex)]; + for (const match of matches) { + const issueNumber = match.groups?.issueNumber; + if (issueNumber) { + debug(`Found issue number: ${issueNumber}`); + const issue = await getIssueByTeamAndNumber( + linearClient, + team, + Number(issueNumber), + ); + if (issue && !processedIssueIds.has(issue.id)) { + processedIssueIds.add(issue.id); + await addLabels(linearClient, issue, labelIds); + foundIssues.push(issue); + } } } } + if (foundIssues.length > 0) { + const firstIssue = foundIssues[0]; + const firstTeam = teams.find((t) => + firstIssue.identifier.startsWith(t.key), + ); + if (firstTeam) { + setOutput("linear-team-id", firstTeam.id); + setOutput("linear-team-key", firstTeam.key); + } + setOutput("linear-issue-id", firstIssue.id); + setOutput("linear-issue-number", firstIssue.number); + setOutput("linear-issue-identifier", firstIssue.identifier); + setOutput("linear-issue-url", firstIssue.url); + setOutput("linear-issue-title", firstIssue.title); + setOutput("linear-issue-description", firstIssue.description); + return; + } + setFailed( `Failed to find Linear issue identifier in PR branch, title, or body.`, ); - return; } catch (error) { setFailed(`${(error as any)?.message ?? error}`); }