Skip to content

Commit

Permalink
feat(mix): extract lockedVersion (#27924)
Browse files Browse the repository at this point in the history
Co-authored-by: Rhys Arkins <[email protected]>
Co-authored-by: Michael Kriese <[email protected]>
  • Loading branch information
3 people authored May 27, 2024
1 parent 842f205 commit 30926c9
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 17 deletions.
6 changes: 3 additions & 3 deletions lib/modules/manager/mix/__fixtures__/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ 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"},
{:secret, "~> 1.0", organization: "acme"},
{: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
16 changes: 16 additions & 0 deletions lib/modules/manager/mix/__fixtures__/mix.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%{
"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"},
"a_transient_dependency": {:hex, :a_transient_dependency, "1.6.14", "344dbbf6610d205760ec37e2848bff2aab5a2de182bb5cdaa72cc2fd19d74535", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "19c205c8de0e2e5817f2250100281c58e717cb11ff1bb410bf661ee78c24e79b"}
}
108 changes: 102 additions & 6 deletions lib/modules/manager/mix/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ 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', async () => {
it('extracts all dependencies when no lockfile', async () => {
const res = await extractPackageFile(Fixtures.get('mix.exs'), 'mix.exs');
expect(res?.deps).toEqual([
{
Expand All @@ -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,
Expand Down Expand Up @@ -76,21 +76,117 @@ describe('modules/manager/mix/extract', () => {
{
currentValue: '~> 1.0',
datasource: 'hex',
depName: 'mason',
packageName: 'mason',
},
{
currentValue: '~> 6.1',
datasource: 'hex',
depName: 'hammer_backend_redis',
packageName: 'hammer_backend_redis',
},
{
currentValue: '== 1.6.14',
currentVersion: '1.6.14',
datasource: 'hex',
depName: 'public',
packageName: 'public',
},
]);
});

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: 'phoenix',
packageName: 'phoenix',
depName: 'public',
packageName: 'public',
lockedVersion: '1.6.14',
},
]);
});
Expand Down
39 changes: 31 additions & 8 deletions lib/modules/manager/mix/extract.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -16,13 +16,16 @@ const refRegexp = regEx(/ref:\s*"(?<value>[^"]+)"/);
const branchOrTagRegexp = regEx(/(?:branch|tag):\s*"(?<value>[^"]+)"/);
const organizationRegexp = regEx(/organization:\s*"(?<value>[^"]+)"/);
const commentMatchRegExp = regEx(/#.*$/);
const lockedVersionRegExp = regEx(
/^\s+"(?<app>\w+)".*?"(?<lockedVersion>\d+\.\d+\.\d+)"/,
);

export async function extractPackageFile(
content: string,
packageFile: string,
): Promise<PackageFileContent | null> {
logger.trace(`mix.extractPackageFile(${packageFile})`);
const deps: PackageDependency[] = [];
const deps = new Map<string, PackageDependency>();
const contentArr = content
.split(newlineRegex)
.map((line) => line.replace(commentMatchRegExp, ''));
Expand Down Expand Up @@ -64,17 +67,37 @@ export async function extractPackageFile(
}
}

deps.push(dep);
deps.set(app, dep);
logger.trace({ dep }, `setting ${app}`);
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, 'utf8');

if (lockFileContent) {
const lockFileLines = lockFileContent.split(newlineRegex).slice(1, -1);

for (const line of lockFileLines) {
const groups = lockedVersionRegExp.exec(line)?.groups;
if (groups?.app && groups?.lockedVersion) {
const dep = deps.get(groups.app);
if (!dep) {
continue;
}
dep.lockedVersion = groups.lockedVersion;
logger.trace(`Found ${groups.lockedVersion} for ${groups.app}`);
}
}
}
const depsArray = Array.from(deps.values());
if (depsArray.length === 0) {
return null;
}
return res;
return {
deps: depsArray,
lockFiles: lockFileContent ? [lockFileName] : undefined,
};
}

0 comments on commit 30926c9

Please sign in to comment.