From db5f2e1edee666a4b862a3bde6c8882708b14eae Mon Sep 17 00:00:00 2001 From: Colin Lacy Date: Tue, 16 Dec 2025 14:22:26 -0500 Subject: [PATCH] Adds option to only show latest patch versions Signed-off-by: Colin Lacy --- __tests__/main.test.js | 21 +++++++++++++++++---- action.yml | 4 ++++ src/go-versions.js | 28 +++++++++++++++++++++++++++- src/main.js | 9 ++++++++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/__tests__/main.test.js b/__tests__/main.test.js index bb5d110..e62dec0 100644 --- a/__tests__/main.test.js +++ b/__tests__/main.test.js @@ -28,13 +28,13 @@ test('test latest version', () => { test('test version matrix', () => { const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) - const m = matrix('1.16', false, false, t) + const m = matrix('1.16', false, false, false, t) expect(m).toEqual(['1.16', '1.17', '1.18']) }) test('test unstable version matrix', () => { const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) - const m = matrix('1.16', true, false, t) + const m = matrix('1.16', true, false, false, t) expect(m).toEqual([ '1.16beta1', '1.16rc1', @@ -52,7 +52,7 @@ test('test unstable version matrix', () => { test('test patch level version matrix', () => { const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) - const m = matrix('1.16', false, true, t) + const m = matrix('1.16', false, true, false, t) expect(m).toEqual([ '1.16', '1.16.1', @@ -85,7 +85,7 @@ test('test patch level version matrix', () => { test('test patch level, unstable version matrix', () => { const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) - const m = matrix('1.16', true, true, t) + const m = matrix('1.16', true, true, false, t) expect(m).toEqual([ '1.16beta1', '1.16rc1', @@ -123,3 +123,16 @@ test('test patch level, unstable version matrix', () => { '1.18' ]) }) + +test('test patch level with latest patches only', () => { + const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) + const m = matrix('1.16', false, true, true, t) + expect(m).toEqual(['1.16.15', '1.17.8', '1.18']) +}) + +test('test patch level with latest patches only and unstable throws error', () => { + const t = JSON.parse(fs.readFileSync('__tests__/testdata/dl.json', 'utf8')) + expect(() => { + matrix('1.16', true, true, true, t) + }).toThrow('The options "unstable" and "latest-patches-only" cannot be used together') +}) diff --git a/action.yml b/action.yml index a1c4cd8..2b054b4 100644 --- a/action.yml +++ b/action.yml @@ -22,6 +22,10 @@ inputs: description: Include the patch levels on the versions (default is major.minor) required: false default: 'false' + latest-patches-only: + description: When patch-level is true, only include the latest patch version of each major.minor version in the matrix. Does nothing if patch-level is false. Cannot be used with unstable. + required: false + default: 'false' outputs: go-mod-version: description: The Go version specified by go.mod diff --git a/src/go-versions.js b/src/go-versions.js index 6e98369..9642341 100644 --- a/src/go-versions.js +++ b/src/go-versions.js @@ -41,11 +41,16 @@ const getVersions = async withUnsupported => { return result } -const matrix = (min, withUnstable, withPatchLevel, tags) => { +const matrix = (min, withUnstable, withPatchLevel, withLatestPatches, tags) => { const minClean = semverCoerce(min) if (minClean === null) { throw new Error(`Minimal version isn't quite right: ${min}`) } + if (withUnstable && withLatestPatches) { + throw new Error( + 'The options "unstable" and "latest-patches-only" cannot be used together' + ) + } if (!withUnstable) { tags = tags.filter(tag => tag.stable === true) } @@ -63,6 +68,27 @@ const matrix = (min, withUnstable, withPatchLevel, tags) => { const parts = version.split('.') return `${parts[0]}.${parts[1]}` }) + } else if (withLatestPatches) { + // Group by major.minor and keep only the latest patch version + const grouped = {} + versions.forEach(version => { + const parts = version.split('.') + const majorMinor = `${parts[0]}.${parts[1]}` + if (!grouped[majorMinor]) { + grouped[majorMinor] = [] + } + grouped[majorMinor].push(version) + }) + versions = Object.values(grouped).map(group => { + return group.reduce((acc, val) => { + const a = semverCoerce(acc) + const v = semverCoerce(val) + if (v !== null && a !== null && semverGte(v, a)) { + return val + } + return acc + }) + }) } versions = [...new Set(versions)] return versions.reverse() diff --git a/src/main.js b/src/main.js index 27293f2..65a5429 100644 --- a/src/main.js +++ b/src/main.js @@ -21,11 +21,18 @@ async function run() { const withUnsupported = core.getBooleanInput('unsupported') const withUnstable = core.getBooleanInput('unstable') const withPatchLevel = core.getBooleanInput('patch-level') + const withLatestPatches = core.getBooleanInput('latest-patches-only') const content = gomod(`${workingDirectory}/go.mod`) const name = modulename(content) const goModVersion = getGoModVersion(content) const versions = await getVersions(withUnsupported) - const mat = matrix(goModVersion, withUnstable, withPatchLevel, versions) + const mat = matrix( + goModVersion, + withUnstable, + withPatchLevel, + withLatestPatches, + versions + ) const lat = latest(mat) const min = minimal(mat)