Skip to content

Commit 590dd10

Browse files
Fix version numbers with no . not matching open tickets, resulting in duplicates
1 parent 6438f90 commit 590dd10

3 files changed

Lines changed: 46 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
### Fixed
1212

13+
- Fix version numbers without `.` failing to match open tickets, resulting in duplicates
14+
1315
### Removed
1416

1517
## 0.2.1 - 2026-05-07

src/core/utils/versionUtils.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,22 @@ describe('extractLatestVersionFromTitle', () => {
169169
).toBe('2.0.0-beta.1');
170170
});
171171

172+
it('extracts calver version from FYI format', () => {
173+
expect(
174+
extractLatestVersionFromTitle(
175+
'[Dependicus] [pypi] FYI: sudachidict-core 20260428 is available (currently on 20241021)',
176+
),
177+
).toBe('20260428');
178+
});
179+
180+
it('extracts calver version from "to X" format', () => {
181+
expect(
182+
extractLatestVersionFromTitle(
183+
'[Dependicus] [pypi] Update sudachidict-core from 20241021 to 20260428',
184+
),
185+
).toBe('20260428');
186+
});
187+
172188
it('returns undefined for old format without version', () => {
173189
expect(extractLatestVersionFromTitle('[Dependicus] Update react')).toBeUndefined();
174190
});
@@ -235,6 +251,22 @@ describe('extractDependencyNameFromTitle', () => {
235251
).toBe('npm::@linear/sdk');
236252
});
237253

254+
it('extracts name from FYI title with calver version', () => {
255+
expect(
256+
extractDependencyNameFromTitle(
257+
'[Dependicus] [pypi] FYI: sudachidict-core 20260428 is available (currently on 20241021)',
258+
),
259+
).toBe('pypi::sudachidict-core');
260+
});
261+
262+
it('extracts name from FYI title with calver version (no ecosystem tag)', () => {
263+
expect(
264+
extractDependencyNameFromTitle(
265+
'[Dependicus] FYI: sudachidict-core 20260428 is available (currently on 20241021)',
266+
),
267+
).toBe('sudachidict-core');
268+
});
269+
238270
it('returns undefined for non-Dependicus titles', () => {
239271
expect(extractDependencyNameFromTitle('Update react to 19.0.0')).toBeUndefined();
240272
expect(extractDependencyNameFromTitle('Fix bug in react')).toBeUndefined();

src/core/utils/versionUtils.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,16 @@ export function extractLatestVersionFromTitle(title: string): string | undefined
105105
return latestMatch[1];
106106
}
107107

108-
// Try FYI format: "FYI: package X.Y.Z is available"
109-
const fyiMatch = title.match(/FYI:\s+\S+\s+(\d+\.\d+\.\d+(?:-[\w.]+)?)\s+is available/);
108+
// Try FYI format: "FYI: package <version> is available"
109+
// Anchor on "is available" to be version-format-agnostic (handles semver, calver, etc.)
110+
const fyiMatch = title.match(/FYI:\s+\S+\s+(\S+)\s+is available/);
110111
if (fyiMatch) {
111112
return fyiMatch[1];
112113
}
113114

114-
// Try format "to X.Y.Z" (when min === latest)
115-
const toMatch = title.match(/to\s+(\d+\.\d+\.\d+(?:-[\w.]+)?)\s*$/);
115+
// Try format "to <version>" (when min === latest)
116+
// Anchor on end-of-string to be version-format-agnostic
117+
const toMatch = title.match(/to\s+(\S+)\s*$/);
116118
if (toMatch) {
117119
return toMatch[1];
118120
}
@@ -133,8 +135,11 @@ export function extractDependencyNameFromTitle(title: string): string | undefine
133135
return `${ecoUpdateMatch[1]}::${ecoUpdateMatch[2]}`;
134136
}
135137

136-
// Try new FYI format with ecosystem tag: "[Dependicus] [npm] FYI: X Y.Z is available"
137-
const ecoFyiMatch = title.match(/^\[Dependicus\]\s+\[(\w+)\]\s+FYI:\s+(.+?)\s+\d+\.\d+/);
138+
// Try new FYI format with ecosystem tag: "[Dependicus] [eco] FYI: X <version> is available"
139+
// Anchor on "is available" to be version-format-agnostic (handles semver, calver, etc.)
140+
const ecoFyiMatch = title.match(
141+
/^\[Dependicus\]\s+\[(\w+)\]\s+FYI:\s+(.+?)\s+\S+\s+is available/,
142+
);
138143
if (ecoFyiMatch) {
139144
return `${ecoFyiMatch[1]}::${ecoFyiMatch[2]}`;
140145
}
@@ -146,7 +151,7 @@ export function extractDependencyNameFromTitle(title: string): string | undefine
146151
}
147152

148153
// Backward compat: FYI format (no ecosystem tag)
149-
const fyiMatch = title.match(/^\[Dependicus\]\s+FYI:\s+(.+?)\s+\d+\.\d+/);
154+
const fyiMatch = title.match(/^\[Dependicus\]\s+FYI:\s+(.+?)\s+\S+\s+is available/);
150155
if (fyiMatch) {
151156
return fyiMatch[1];
152157
}

0 commit comments

Comments
 (0)