From a47998ce5dddc9070550cb0b4b96326ee7a4f0e9 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Tue, 5 Dec 2023 23:32:46 -0800 Subject: [PATCH 1/8] 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 ffe21e14d357dec863787ec85f78fe7ac86089b1 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Wed, 13 Mar 2024 15:30:15 -0700 Subject: [PATCH 2/8] chore: remove changes from hex Only make changes to the mix manager in one PR --- lib/modules/versioning/hex/index.spec.ts | 38 +++++++++++------------- lib/modules/versioning/hex/index.ts | 1 - 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/lib/modules/versioning/hex/index.spec.ts b/lib/modules/versioning/hex/index.spec.ts index 11a70b073c0033..6ec94685bf8db5 100644 --- a/lib/modules/versioning/hex/index.spec.ts +++ b/lib/modules/versioning/hex/index.spec.ts @@ -63,26 +63,24 @@ 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.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'} + 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'} `( '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 f82d9f9b1b034b..b84ff6189fb344 100644 --- a/lib/modules/versioning/hex/index.ts +++ b/lib/modules/versioning/hex/index.ts @@ -12,7 +12,6 @@ export const supportedRangeStrategies: RangeStrategy[] = [ 'widen', 'pin', 'replace', - 'update-lockfile', ]; function hex2npm(input: string): string { From b03eee44740e77a97e3283141d323e076e88eb92 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Wed, 13 Mar 2024 16:18:14 -0700 Subject: [PATCH 3/8] test(mix): update tests for code coverage --- lib/modules/manager/mix/__fixtures__/mix.lock | 15 +++ lib/modules/manager/mix/extract.spec.ts | 98 ++++++++++++++++++- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 lib/modules/manager/mix/__fixtures__/mix.lock diff --git a/lib/modules/manager/mix/__fixtures__/mix.lock b/lib/modules/manager/mix/__fixtures__/mix.lock new file mode 100644 index 00000000000000..df0a82ba80b452 --- /dev/null +++ b/lib/modules/manager/mix/__fixtures__/mix.lock @@ -0,0 +1,15 @@ +%{ + "foo_bar": {:hex, :foo_bar, "2.2.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, + "postgrex": {:hex, :postgrex, "0.8.2", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"}, + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "cowboy": {:git, "https://github.com/ninenines/cowboy.git", "81f3a21474155f68fbf494b7026b9678027d303e", [tag: "v0.4.1"]}, + "phoenix": {:git, "https://github.com/phoenixframework/phoenix.git", "61f3a21474155f68fbf494b7026b9678027d303e", [branch: "main]}, + "ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [ref: "795036d997c7503b21fb64d6bf1a89b83c44f2b5"]}, + "secret": {:hex, :secret, "1.5.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "also_secret": {:hex, :also_secret, "1.3.4", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "ex_doc": {:hex, :ex_doc, "2.2.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "jason": {:hex, :jason, "1.0.1", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "mason": {:hex, :mason, "1.1.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "hammer_backend_redis": {:hex, :hammer_backend_redis, "6.1.5", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "public": {:hex, :public, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, +} diff --git a/lib/modules/manager/mix/extract.spec.ts b/lib/modules/manager/mix/extract.spec.ts index 1933576e219dc7..852b8e53c8a55c 100644 --- a/lib/modules/manager/mix/extract.spec.ts +++ b/lib/modules/manager/mix/extract.spec.ts @@ -13,7 +13,7 @@ describe('modules/manager/mix/extract', () => { expect(res?.deps).toBeEmpty(); }); - it('extracts all dependencies', async () => { + it('extracts all dependencies when no lockfile', async () => { const res = await extractPackageFile(Fixtures.get('mix.exs'), 'mix.exs'); expect(res?.deps).toEqual([ { @@ -94,5 +94,101 @@ describe('modules/manager/mix/extract', () => { }, ]); }); + + it('extracts all dependencies and adds the locked version if lockfile present', async () => { + // allows fetching the sibling mix.lock file + GlobalConfig.set({ localDir: 'lib/modules/manager/mix/__fixtures__' }); + const res = await extractPackageFile(Fixtures.get('mix.exs'), 'mix.exs'); + expect(res?.deps).toEqual([ + { + currentValue: '~> 0.8.1', + datasource: 'hex', + depName: 'postgrex', + packageName: 'postgrex', + lockedVersion: '0.8.2', + }, + { + currentValue: '>2.1.0 or <=3.0.0', + datasource: 'hex', + depName: 'foo_bar', + packageName: 'foo_bar', + lockedVersion: '2.2.0', + }, + { + currentDigest: undefined, + currentValue: 'v0.4.1', + datasource: 'github-tags', + depName: 'cowboy', + packageName: 'ninenines/cowboy', + lockedVersion: undefined, + }, + { + currentDigest: undefined, + currentValue: 'main', + datasource: 'git-tags', + depName: 'phoenix', + packageName: 'https://github.com/phoenixframework/phoenix.git', + lockedVersion: undefined, + }, + { + currentDigest: '795036d997c7503b21fb64d6bf1a89b83c44f2b5', + currentValue: undefined, + datasource: 'github-tags', + depName: 'ecto', + packageName: 'elixir-ecto/ecto', + lockedVersion: undefined, + }, + { + currentValue: '~> 1.0', + datasource: 'hex', + depName: 'secret', + packageName: 'secret:acme', + lockedVersion: '1.5.0', + }, + { + currentValue: '~> 1.0', + datasource: 'hex', + depName: 'also_secret', + packageName: 'also_secret:acme', + lockedVersion: '1.3.4', + }, + { + currentValue: '>2.1.0 and <=3.0.0', + datasource: 'hex', + depName: 'ex_doc', + packageName: 'ex_doc', + lockedVersion: '2.2.0', + }, + { + currentValue: '>= 1.0.0', + datasource: 'hex', + depName: 'jason', + packageName: 'jason', + lockedVersion: '1.0.1', + }, + { + currentValue: '~> 1.0', + datasource: 'hex', + depName: 'mason', + packageName: 'mason', + lockedVersion: '1.1.0', + }, + { + currentValue: '~> 6.1', + datasource: 'hex', + depName: 'hammer_backend_redis', + packageName: 'hammer_backend_redis', + lockedVersion: '6.1.5', + }, + { + currentValue: '== 1.6.14', + currentVersion: '1.6.14', + datasource: 'hex', + depName: 'public', + packageName: 'public', + lockedVersion: '1.6.14', + }, + ]); + }); }); }); From 87f563eaff6e995dc4f53da079803e56f6fb0a3c Mon Sep 17 00:00:00 2001 From: Josiah Dahl <105243742+pdm-jd@users.noreply.github.com> Date: Fri, 15 Mar 2024 09:58:59 -0700 Subject: [PATCH 4/8] Apply suggestions from code review Co-authored-by: Michael Kriese --- lib/modules/manager/mix/extract.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index ebce5941fd6297..923790255c75d2 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -68,18 +68,17 @@ export async function extractPackageFile( } deps.set(app, dep); - logger.info(`setting ${app} to ${JSON.stringify(dep)}`); + logger.trace({dep}, `setting ${app}`); depMatchGroups = depMatchRegExp.exec(depBuffer)?.groups; } } } const lockFileName = (await findLocalSiblingOrParent(packageFile, 'mix.lock')) ?? 'mix.lock'; - const lockFileContent = await readLocalFile(lockFileName); + const lockFileContent = await readLocalFile(lockFileName, 'utf8'); if (lockFileContent) { const lockedVersions = lockFileContent - .toString() .split(newlineRegex) .slice(1, -1) .reduce>((lockedVersions, line) => { From b8e5b3e5cc7cf07fd29e3ebf7589c4eab5ea9d1e Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Fri, 15 Mar 2024 10:07:07 -0700 Subject: [PATCH 5/8] Apply feedback from review --- lib/modules/manager/mix/extract.ts | 23 ++++++++++++----------- lib/util/pretty-time.spec.ts | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index 923790255c75d2..72918129165d68 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -68,7 +68,7 @@ export async function extractPackageFile( } deps.set(app, dep); - logger.trace({dep}, `setting ${app}`); + logger.trace({ dep }, `setting ${app}`); depMatchGroups = depMatchRegExp.exec(depBuffer)?.groups; } } @@ -78,16 +78,17 @@ export async function extractPackageFile( const lockFileContent = await readLocalFile(lockFileName, 'utf8'); if (lockFileContent) { - const lockedVersions = lockFileContent - .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()); + const lockFileLines = lockFileContent.split(newlineRegex).slice(1, -1); + + const lockedVersions: Map = new Map(); + + for (const line of lockFileLines) { + const groups = lockedVersionRegExp.exec(line)?.groups; + if (groups?.app && groups?.lockedVersion) { + lockedVersions.set(groups.app, groups.lockedVersion); + } + } + for (const [app, dep] of deps.entries()) { dep.lockedVersion = lockedVersions.get(app); logger.debug(`Found ${dep.lockedVersion} for ${app}`); 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(); From 3bc29e795dcb2cfc4d2a4def653b01ab705a2d21 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Tue, 26 Mar 2024 15:46:43 -0600 Subject: [PATCH 6/8] PR review feedback --- lib/modules/manager/mix/extract.spec.ts | 2 +- lib/modules/manager/mix/extract.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/modules/manager/mix/extract.spec.ts b/lib/modules/manager/mix/extract.spec.ts index 852b8e53c8a55c..da6ffc1fbb14f4 100644 --- a/lib/modules/manager/mix/extract.spec.ts +++ b/lib/modules/manager/mix/extract.spec.ts @@ -10,7 +10,7 @@ describe('modules/manager/mix/extract', () => { describe('extractPackageFile()', () => { it('returns empty for invalid dependency file', async () => { const res = await extractPackageFile('nothing here', 'mix.exs'); - expect(res?.deps).toBeEmpty(); + expect(res).toBeNull(); }); it('extracts all dependencies when no lockfile', async () => { diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index 72918129165d68..b1809d816024b7 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -91,11 +91,15 @@ export async function extractPackageFile( for (const [app, dep] of deps.entries()) { dep.lockedVersion = lockedVersions.get(app); - logger.debug(`Found ${dep.lockedVersion} for ${app}`); + logger.trace(`Found ${dep.lockedVersion} for ${app}`); } } + const depsArray = Array.from(deps.values()); + if (depsArray.length === 0) { + return null; + } return { - deps: Array.from(deps.values()), + deps: depsArray, lockFiles: lockFileContent ? [lockFileName] : undefined, }; } From b8fd6688bd94bf43357bf816470e5f7193ebddc3 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Mon, 8 Apr 2024 15:58:38 -0700 Subject: [PATCH 7/8] apply changes --- lib/modules/manager/mix/extract.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index b1809d816024b7..1cb7d82c2a01df 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -80,7 +80,7 @@ export async function extractPackageFile( if (lockFileContent) { const lockFileLines = lockFileContent.split(newlineRegex).slice(1, -1); - const lockedVersions: Map = new Map(); + const lockedVersions = new Map(); for (const line of lockFileLines) { const groups = lockedVersionRegExp.exec(line)?.groups; @@ -90,8 +90,11 @@ export async function extractPackageFile( } for (const [app, dep] of deps.entries()) { - dep.lockedVersion = lockedVersions.get(app); - logger.trace(`Found ${dep.lockedVersion} for ${app}`); + const lockedVersion = lockedVersions.get(app); + if (lockedVersion) { + dep.lockedVersion = lockedVersion; + logger.trace(`Found ${lockedVersion} for ${app}`); + } } } const depsArray = Array.from(deps.values()); From 1e6aa464db9ca3c15930ddb7cadeaa8aa2e5c106 Mon Sep 17 00:00:00 2001 From: Josiah Dahl Date: Thu, 9 May 2024 20:54:00 -0700 Subject: [PATCH 8/8] perf: review feedback --- lib/modules/manager/mix/__fixtures__/mix.lock | 1 + lib/modules/manager/mix/extract.ts | 17 ++++++----------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/modules/manager/mix/__fixtures__/mix.lock b/lib/modules/manager/mix/__fixtures__/mix.lock index df0a82ba80b452..c1b5eacc423a5e 100644 --- a/lib/modules/manager/mix/__fixtures__/mix.lock +++ b/lib/modules/manager/mix/__fixtures__/mix.lock @@ -12,4 +12,5 @@ "mason": {:hex, :mason, "1.1.0", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "hammer_backend_redis": {:hex, :hammer_backend_redis, "6.1.5", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, "public": {:hex, :public, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}, + "a_transient_dependency": {:hex, :a_transient_dependency, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"} } diff --git a/lib/modules/manager/mix/extract.ts b/lib/modules/manager/mix/extract.ts index 1cb7d82c2a01df..e8cc5eb8ff677b 100644 --- a/lib/modules/manager/mix/extract.ts +++ b/lib/modules/manager/mix/extract.ts @@ -80,20 +80,15 @@ export async function extractPackageFile( if (lockFileContent) { const lockFileLines = lockFileContent.split(newlineRegex).slice(1, -1); - const lockedVersions = new Map(); - for (const line of lockFileLines) { const groups = lockedVersionRegExp.exec(line)?.groups; if (groups?.app && groups?.lockedVersion) { - lockedVersions.set(groups.app, groups.lockedVersion); - } - } - - for (const [app, dep] of deps.entries()) { - const lockedVersion = lockedVersions.get(app); - if (lockedVersion) { - dep.lockedVersion = lockedVersion; - logger.trace(`Found ${lockedVersion} for ${app}`); + const dep = deps.get(groups.app); + if (!dep) { + continue; + } + dep.lockedVersion = groups.lockedVersion; + logger.trace(`Found ${groups.lockedVersion} for ${groups.app}`); } } }