From a47998ce5dddc9070550cb0b4b96326ee7a4f0e9 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Tue, 5 Dec 2023 23:32:46 -0800 Subject: [PATCH 1/2] feat(hex): Add support for update-lockfile strategy --- lib/modules/manager/mix/__fixtures__/mix.exs | 6 ++-- lib/modules/manager/mix/extract.spec.ts | 12 +++---- lib/modules/manager/mix/extract.ts | 37 ++++++++++++++----- lib/modules/versioning/hex/index.spec.ts | 38 ++++++++++---------- lib/modules/versioning/hex/index.ts | 1 + lib/util/pretty-time.spec.ts | 2 +- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/lib/modules/manager/mix/__fixtures__/mix.exs b/lib/modules/manager/mix/__fixtures__/mix.exs index 78a1cd2cb3804a..a6c88af2983af4 100644 --- a/lib/modules/manager/mix/__fixtures__/mix.exs +++ b/lib/modules/manager/mix/__fixtures__/mix.exs @@ -20,7 +20,7 @@ defmodule MyProject.MixProject do # {:broadway_dashboard, "~> 0.2.2"}, # {:broadway_dashboard, "~> 0.2.2"}, {:postgrex, "~> 0.8.1"}, # {:broadway_dashboard, "~> 0.2.2"}, - {:ecto, ">2.1.0 or <=3.0.0"}, + {:foo_bar, ">2.1.0 or <=3.0.0"}, {:cowboy, github: "ninenines/cowboy", tag: "v0.4.1"}, {:phoenix, git: "https://github.com/phoenixframework/phoenix.git", branch: "main"}, {:ecto, github: "elixir-ecto/ecto", ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"}, @@ -28,10 +28,10 @@ defmodule MyProject.MixProject do {:also_secret, "~> 1.0", only: [:dev, :test], organization: "acme", runtime: false}, {:ex_doc, ">2.1.0 and <=3.0.0"}, {:jason, ">= 1.0.0"}, - {:jason, "~> 1.0", + {:mason, "~> 1.0", optional: true}, {:hammer_backend_redis, "~> 6.1"}, - {:phoenix, "== 1.6.14"}, + {:public, "== 1.6.14"}, ] end end diff --git a/lib/modules/manager/mix/extract.spec.ts b/lib/modules/manager/mix/extract.spec.ts index 5a7e6ed1d35a70..1933576e219dc7 100644 --- a/lib/modules/manager/mix/extract.spec.ts +++ b/lib/modules/manager/mix/extract.spec.ts @@ -25,8 +25,8 @@ describe('modules/manager/mix/extract', () => { { currentValue: '>2.1.0 or <=3.0.0', datasource: 'hex', - depName: 'ecto', - packageName: 'ecto', + depName: 'foo_bar', + packageName: 'foo_bar', }, { currentDigest: undefined, @@ -76,8 +76,8 @@ describe('modules/manager/mix/extract', () => { { currentValue: '~> 1.0', datasource: 'hex', - depName: 'jason', - packageName: 'jason', + depName: 'mason', + packageName: 'mason', }, { currentValue: '~> 6.1', @@ -89,8 +89,8 @@ describe('modules/manager/mix/extract', () => { currentValue: '== 1.6.14', currentVersion: '1.6.14', datasource: 'hex', - depName: 'phoenix', - packageName: 'phoenix', + depName: 'public', + packageName: 'public', }, ]); }); diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index 25389f4ed9b1d7..ebce5941fd6297 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -1,5 +1,5 @@ import { logger } from '../../../logger'; -import { findLocalSiblingOrParent, localPathExists } from '../../../util/fs'; +import { findLocalSiblingOrParent, readLocalFile } from '../../../util/fs'; import { newlineRegex, regEx } from '../../../util/regex'; import { GitTagsDatasource } from '../../datasource/git-tags'; import { GithubTagsDatasource } from '../../datasource/github-tags'; @@ -16,13 +16,16 @@ const refRegexp = regEx(/ref:\s*"(?[^"]+)"/); const branchOrTagRegexp = regEx(/(?:branch|tag):\s*"(?[^"]+)"/); const organizationRegexp = regEx(/organization:\s*"(?[^"]+)"/); const commentMatchRegExp = regEx(/#.*$/); +const lockedVersionRegExp = regEx( + /^\s+"(?\w+)".*?"(?\d+\.\d+\.\d+)"/, +); export async function extractPackageFile( content: string, packageFile: string, ): Promise { logger.trace(`mix.extractPackageFile(${packageFile})`); - const deps: PackageDependency[] = []; + const deps = new Map(); const contentArr = content .split(newlineRegex) .map((line) => line.replace(commentMatchRegExp, '')); @@ -64,17 +67,35 @@ export async function extractPackageFile( } } - deps.push(dep); + deps.set(app, dep); + logger.info(`setting ${app} to ${JSON.stringify(dep)}`); depMatchGroups = depMatchRegExp.exec(depBuffer)?.groups; } } } - const res: PackageFileContent = { deps }; const lockFileName = (await findLocalSiblingOrParent(packageFile, 'mix.lock')) ?? 'mix.lock'; - // istanbul ignore if - if (await localPathExists(lockFileName)) { - res.lockFiles = [lockFileName]; + const lockFileContent = await readLocalFile(lockFileName); + + if (lockFileContent) { + const lockedVersions = lockFileContent + .toString() + .split(newlineRegex) + .slice(1, -1) + .reduce>((lockedVersions, line) => { + const groups = lockedVersionRegExp.exec(line)?.groups; + if (groups?.app && groups?.lockedVersion) { + lockedVersions.set(groups.app, groups.lockedVersion); + } + return lockedVersions; + }, new Map()); + for (const [app, dep] of deps.entries()) { + dep.lockedVersion = lockedVersions.get(app); + logger.debug(`Found ${dep.lockedVersion} for ${app}`); + } } - return res; + return { + deps: Array.from(deps.values()), + lockFiles: lockFileContent ? [lockFileName] : undefined, + }; } diff --git a/lib/modules/versioning/hex/index.spec.ts b/lib/modules/versioning/hex/index.spec.ts index 6ec94685bf8db5..11a70b073c0033 100644 --- a/lib/modules/versioning/hex/index.spec.ts +++ b/lib/modules/versioning/hex/index.spec.ts @@ -63,24 +63,26 @@ describe('modules/versioning/hex/index', () => { ); it.each` - currentValue | rangeStrategy | currentVersion | newVersion | expected - ${'== 1.2.3'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} - ${'== 3.6.1'} | ${'bump'} | ${'3.6.1'} | ${'3.6.2'} | ${'== 3.6.2'} - ${'== 3.6.1'} | ${'replace'} | ${'3.6.1'} | ${'3.6.2'} | ${'== 3.6.2'} - ${'~> 1.2'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0'} - ${'~> 1.2'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} - ${'~> 1.2'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0'} - ${'~> 1.2'} | ${'bump'} | ${'1.2.3'} | ${'1.3.1'} | ${'~> 1.3'} - ${'~> 1.2.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.0'} - ${'~> 1.2.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} - ${'~> 1.2.0'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.7'} - ${'>= 1.0.0 and <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 and <= 2.0.7'} - ${'>= 1.0.0 and <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'} - ${'>= 1.0.0 and <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} - ${'>= 1.0.0 or <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 or <= 2.0.0'} - ${'>= 1.0.0 or <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'} - ${'>= 1.0.0 or <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} - ${'~> 0.4'} | ${'replace'} | ${'0.4.2'} | ${'0.6.0'} | ${'~> 0.6'} + currentValue | rangeStrategy | currentVersion | newVersion | expected + ${'== 1.2.3'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} + ${'== 3.6.1'} | ${'bump'} | ${'3.6.1'} | ${'3.6.2'} | ${'== 3.6.2'} + ${'== 3.6.1'} | ${'replace'} | ${'3.6.1'} | ${'3.6.2'} | ${'== 3.6.2'} + ${'~> 1.2'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0'} + ${'~> 1.2'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} + ${'~> 1.2'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0'} + ${'~> 1.2'} | ${'bump'} | ${'1.2.3'} | ${'1.3.1'} | ${'~> 1.3'} + ${'~> 1.1'} | ${'update-lockfile'} | ${'1.2.0'} | ${'1.3.0'} | ${'~> 1.1'} + ${'~> 1.1'} | ${'update-lockfile'} | ${'1.2.0'} | ${'2.0.0'} | ${'~> 2.0'} + ${'~> 1.2.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.0'} + ${'~> 1.2.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} + ${'~> 1.2.0'} | ${'bump'} | ${'1.2.3'} | ${'2.0.7'} | ${'~> 2.0.7'} + ${'>= 1.0.0 and <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 and <= 2.0.7'} + ${'>= 1.0.0 and <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'} + ${'>= 1.0.0 and <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} + ${'>= 1.0.0 or <= 2.0.0'} | ${'widen'} | ${'1.2.3'} | ${'2.0.7'} | ${'>= 1.0.0 or <= 2.0.0'} + ${'>= 1.0.0 or <= 2.0.0'} | ${'replace'} | ${'1.2.3'} | ${'2.0.7'} | ${'<= 2.0.7'} + ${'>= 1.0.0 or <= 2.0.0'} | ${'pin'} | ${'1.2.3'} | ${'2.0.7'} | ${'== 2.0.7'} + ${'~> 0.4'} | ${'replace'} | ${'0.4.2'} | ${'0.6.0'} | ${'~> 0.6'} `( 'getNewValue("$currentValue", "$rangeStrategy", "$currentVersion", "$newVersion") === "$expected"', ({ currentValue, rangeStrategy, currentVersion, newVersion, expected }) => { diff --git a/lib/modules/versioning/hex/index.ts b/lib/modules/versioning/hex/index.ts index b84ff6189fb344..f82d9f9b1b034b 100644 --- a/lib/modules/versioning/hex/index.ts +++ b/lib/modules/versioning/hex/index.ts @@ -12,6 +12,7 @@ export const supportedRangeStrategies: RangeStrategy[] = [ 'widen', 'pin', 'replace', + 'update-lockfile', ]; function hex2npm(input: string): string { diff --git a/lib/util/pretty-time.spec.ts b/lib/util/pretty-time.spec.ts index 693e73c4fa8e6f..4a1017f1c10375 100644 --- a/lib/util/pretty-time.spec.ts +++ b/lib/util/pretty-time.spec.ts @@ -47,7 +47,7 @@ describe('util/pretty-time', () => { }); describe('satisfiesDateRange()', () => { - const t0 = DateTime.fromISO('2023-07-07T12:00:00'); + const t0 = DateTime.fromISO('2023-07-07T12:00:00Z'); beforeAll(() => { jest.useFakeTimers(); From 64dae85b2080f679e10426c2a3661a44d06dd29b Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Tue, 11 Jun 2024 09:32:47 -0700 Subject: [PATCH 2/2] revert unrelated test change --- lib/util/pretty-time.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/pretty-time.spec.ts b/lib/util/pretty-time.spec.ts index 4a1017f1c10375..693e73c4fa8e6f 100644 --- a/lib/util/pretty-time.spec.ts +++ b/lib/util/pretty-time.spec.ts @@ -47,7 +47,7 @@ describe('util/pretty-time', () => { }); describe('satisfiesDateRange()', () => { - const t0 = DateTime.fromISO('2023-07-07T12:00:00Z'); + const t0 = DateTime.fromISO('2023-07-07T12:00:00'); beforeAll(() => { jest.useFakeTimers();