From bcb4e693ecf4de5104c1df7adedfd7f8828920f0 Mon Sep 17 00:00:00 2001 From: Marek Augustynowicz Date: Thu, 9 Jul 2026 14:30:43 +0200 Subject: [PATCH 1/4] fix(jira-integration): Match angle-bracket-wrapped Jira URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support the Markdown autolink form () in “Closes …” lists, for every item in the list including the first one. Brackets are optional on either side; issue keys are still extracted only via the strict key pattern, so nothing new can reach the JQL queries. Co-Authored-By: Claude Fable 5 Reviewed-by: Claude Fable 5 Reviewed-by: CodeRabbit 0.6.5 Reviewed-by: CodeRabbit <136622811+coderabbitai[bot]@users.noreply.github.com> Reviewed-by: Codex gpt-5.5 Reviewed-by: Gemini gemini-2.5-pro --- jira-integration/dist/index.mjs | 2 +- jira-integration/index.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jira-integration/dist/index.mjs b/jira-integration/dist/index.mjs index afb1f6c..a919567 100644 --- a/jira-integration/dist/index.mjs +++ b/jira-integration/dist/index.mjs @@ -36254,7 +36254,7 @@ function extractResolvedIssueKeys(prBody, comments) { // jira keys as extracted keys will be used in JQL queries. const issueKeyRegExp = '[A-Z][A-Z0-9]+-[0-9]+' const urlRegExp = `${jiraApiBaseUrl.origin}/browse/(${issueKeyRegExp})` - const closesRegExp = `${keywordsRegExp}${urlRegExp}(?:\\s*,\\s*${urlRegExp})*` + const closesRegExp = `${keywordsRegExp}?(?:\\s*,\\s*?)*` // Find all “Closes URL, URL…” const matches = text.match(new RegExp(closesRegExp, 'gi')) || [] diff --git a/jira-integration/index.mjs b/jira-integration/index.mjs index eec29c8..485664b 100644 --- a/jira-integration/index.mjs +++ b/jira-integration/index.mjs @@ -178,7 +178,7 @@ function extractResolvedIssueKeys(prBody, comments) { // jira keys as extracted keys will be used in JQL queries. const issueKeyRegExp = '[A-Z][A-Z0-9]+-[0-9]+' const urlRegExp = `${jiraApiBaseUrl.origin}/browse/(${issueKeyRegExp})` - const closesRegExp = `${keywordsRegExp}${urlRegExp}(?:\\s*,\\s*${urlRegExp})*` + const closesRegExp = `${keywordsRegExp}?(?:\\s*,\\s*?)*` // Find all “Closes URL, URL…” const matches = text.match(new RegExp(closesRegExp, 'gi')) || [] From 4865cf493105e64e99bc495f612d60042cf2b0fe Mon Sep 17 00:00:00 2001 From: Marek Augustynowicz Date: Thu, 9 Jul 2026 14:31:23 +0200 Subject: [PATCH 2/4] fix(jira-integration): Avoid crash on case-variant Jira URLs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The “Closes …” list is matched case-insensitively, but the per-match URL extraction was case-sensitive, so e.g. an uppercase host or a lowercase issue key made it return null and the action crashed on null.map(). Use the i flag in both extraction steps as well. Co-Authored-By: Claude Fable 5 Reviewed-by: Claude Fable 5 Reviewed-by: CodeRabbit 0.6.5 Reviewed-by: CodeRabbit <136622811+coderabbitai[bot]@users.noreply.github.com> Reviewed-by: Codex gpt-5.5 Reviewed-by: Gemini gemini-2.5-pro --- jira-integration/dist/index.mjs | 6 +++--- jira-integration/index.mjs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jira-integration/dist/index.mjs b/jira-integration/dist/index.mjs index a919567..0c1f9a5 100644 --- a/jira-integration/dist/index.mjs +++ b/jira-integration/dist/index.mjs @@ -36263,10 +36263,10 @@ function extractResolvedIssueKeys(prBody, comments) { new Set( matches.flatMap((match) => { // Find URLs - const urlMatches = match.match(new RegExp(urlRegExp, 'g')) + const urlMatches = match.match(new RegExp(urlRegExp, 'gi')) // Find issueId in the URL (only capture group in urlRegExp) - const issueKeys = urlMatches.map( - (url) => url.match(new RegExp(urlRegExp))[1] + const issueKeys = urlMatches.map((url) => + url.match(new RegExp(urlRegExp, 'i'))[1].toUpperCase() ) return issueKeys }) diff --git a/jira-integration/index.mjs b/jira-integration/index.mjs index 485664b..821f3e3 100644 --- a/jira-integration/index.mjs +++ b/jira-integration/index.mjs @@ -187,10 +187,10 @@ function extractResolvedIssueKeys(prBody, comments) { new Set( matches.flatMap((match) => { // Find URLs - const urlMatches = match.match(new RegExp(urlRegExp, 'g')) + const urlMatches = match.match(new RegExp(urlRegExp, 'gi')) // Find issueId in the URL (only capture group in urlRegExp) - const issueKeys = urlMatches.map( - (url) => url.match(new RegExp(urlRegExp))[1] + const issueKeys = urlMatches.map((url) => + url.match(new RegExp(urlRegExp, 'i'))[1].toUpperCase() ) return issueKeys }) From 82ff77a5737e64153f8943be977f7ea714c7b0ab Mon Sep 17 00:00:00 2001 From: Marek Augustynowicz Date: Thu, 9 Jul 2026 14:32:05 +0200 Subject: [PATCH 3/4] fix(jira-integration): Escape Jira origin in URL regexp Unescaped dots in the configured origin acted as wildcards, so look-alike hosts could match. RegExp.escape() is built in since Node 24, which this action already runs on. Co-Authored-By: Claude Fable 5 Reviewed-by: Claude Fable 5 Reviewed-by: CodeRabbit 0.6.5 Reviewed-by: CodeRabbit <136622811+coderabbitai[bot]@users.noreply.github.com> Reviewed-by: Codex gpt-5.5 Reviewed-by: Gemini gemini-2.5-pro --- jira-integration/dist/index.mjs | 2 +- jira-integration/index.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jira-integration/dist/index.mjs b/jira-integration/dist/index.mjs index 0c1f9a5..dd01715 100644 --- a/jira-integration/dist/index.mjs +++ b/jira-integration/dist/index.mjs @@ -36253,7 +36253,7 @@ function extractResolvedIssueKeys(prBody, comments) { // It’s extremely important for this regexp to match only simple // jira keys as extracted keys will be used in JQL queries. const issueKeyRegExp = '[A-Z][A-Z0-9]+-[0-9]+' - const urlRegExp = `${jiraApiBaseUrl.origin}/browse/(${issueKeyRegExp})` + const urlRegExp = `${RegExp.escape(jiraApiBaseUrl.origin)}/browse/(${issueKeyRegExp})` const closesRegExp = `${keywordsRegExp}?(?:\\s*,\\s*?)*` // Find all “Closes URL, URL…” diff --git a/jira-integration/index.mjs b/jira-integration/index.mjs index 821f3e3..c7cfe9e 100644 --- a/jira-integration/index.mjs +++ b/jira-integration/index.mjs @@ -177,7 +177,7 @@ function extractResolvedIssueKeys(prBody, comments) { // It’s extremely important for this regexp to match only simple // jira keys as extracted keys will be used in JQL queries. const issueKeyRegExp = '[A-Z][A-Z0-9]+-[0-9]+' - const urlRegExp = `${jiraApiBaseUrl.origin}/browse/(${issueKeyRegExp})` + const urlRegExp = `${RegExp.escape(jiraApiBaseUrl.origin)}/browse/(${issueKeyRegExp})` const closesRegExp = `${keywordsRegExp}?(?:\\s*,\\s*?)*` // Find all “Closes URL, URL…” From e4ff7009fa7f478a62ee4197b85ad7d36fa93ff0 Mon Sep 17 00:00:00 2001 From: Marek Augustynowicz Date: Wed, 15 Jul 2026 13:31:28 +0200 Subject: [PATCH 4/4] chore: Move .nvmrc to repo root, bump to Node 24 jira-integration now uses RegExp.escape, which needs Node 24. The action already runs on node24 (action.yaml), but the pinned .nvmrc kept local runs on Node 20, where the documented debugging flow (node index.mjs) would throw. One repo-root .nvmrc keeps all workspaces on the same version. Co-Authored-By: Claude Fable 5 Reviewed-by: Codex gpt-5.5 Reviewed-by: Gemini gemini-2.5-pro --- .nvmrc | 1 + jira-integration/.nvmrc | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .nvmrc delete mode 100644 jira-integration/.nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..5bcf9c6 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v24.18.0 diff --git a/jira-integration/.nvmrc b/jira-integration/.nvmrc deleted file mode 100644 index 016e34b..0000000 --- a/jira-integration/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v20.17.0