Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nuget): Support for variables #33416

Merged
merged 10 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/modules/manager/nuget/__fixtures__/sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
<Version>0.1.0</Version>
<AutofacVersion>4.5.0</AutofacVersion>
</PropertyGroup>

<ItemGroup>
<Folder Include="Controllers\" />
<Folder Include="wwwroot\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac" Version="4.5.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.1.0" />
<PackageReference Include="Autofac" Version="$(AutofacVersion)" />
rarkins marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="$(UnknownVariable)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="1.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.2" />
Expand Down
7 changes: 1 addition & 6 deletions lib/modules/manager/nuget/__snapshots__/extract.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,12 @@ exports[`modules/manager/nuget/extract extractPackageFile() extracts all depende
"depName": "Microsoft.AspNetCore.Hosting",
"depType": "nuget",
},
{
"currentValue": "4.1.0",
"datasource": "nuget",
"depName": "Autofac.Extensions.DependencyInjection",
"depType": "nuget",
},
rarkins marked this conversation as resolved.
Show resolved Hide resolved
{
"currentValue": "4.5.0",
"datasource": "nuget",
"depName": "Autofac",
"depType": "nuget",
"groupName": "AutofacVersion",
},
]
`;
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/manager/nuget/extract.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('modules/manager/nuget/extract', () => {
const sample = Fixtures.get(packageFile);
const res = await extractPackageFile(sample, packageFile, config);
expect(res?.deps).toMatchSnapshot();
expect(res?.deps).toHaveLength(17);
expect(res?.deps).toHaveLength(16);
});

it('extracts msbuild sdk from the Sdk attr of Project element', async () => {
Expand Down
57 changes: 46 additions & 11 deletions lib/modules/manager/nuget/extract.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import is from '@sindresorhus/is';
import type { XmlElement, XmlNode } from 'xmldoc';
import { XmlDocument } from 'xmldoc';
import type { XmlNode } from 'xmldoc';
import { XmlDocument, XmlElement } from 'xmldoc';
import { logger } from '../../../logger';
import { getSiblingFileName, localPathExists } from '../../../util/fs';
import { hasKey } from '../../../util/object';
import { regEx } from '../../../util/regex';
import { NugetDatasource } from '../../datasource/nuget';
import { getDep } from '../dockerfile/extract';
Expand Down Expand Up @@ -37,12 +36,13 @@ const elemNames = new Set([
'GlobalPackageReference',
]);

function isXmlElem(node: XmlNode): boolean {
return hasKey('name', node);
function isXmlElem(node: XmlNode): node is XmlElement {
return node instanceof XmlElement;
}

function extractDepsFromXml(xmlNode: XmlDocument): NugetPackageDependency[] {
const results: NugetPackageDependency[] = [];
const vars = new Map<string, string>();
const todo: XmlElement[] = [xmlNode];
while (todo.length) {
const child = todo.pop()!;
Expand All @@ -58,22 +58,44 @@ function extractDepsFromXml(xmlNode: XmlDocument): NugetPackageDependency[] {

if (elemNames.has(name)) {
const depName = attr?.Include || attr?.Update;
const version =

let groupName: string | undefined;

let currentValue: string | undefined =
attr?.Version ??
attr?.version ??
child.valueWithPath('Version') ??
attr?.VersionOverride ??
child.valueWithPath('VersionOverride');
const currentValue = is.nonEmptyStringAndNotWhitespace(version)
? checkVersion.exec(version)?.groups?.currentValue?.trim()

currentValue = currentValue
?.trim()
?.replace(/^\$\((\w+)\)$/, (match, key) => {
const val = vars.get(key);
if (val) {
groupName = key;
return val;
}
return match;
});

currentValue = is.nonEmptyStringAndNotWhitespace(currentValue)
? checkVersion.exec(currentValue)?.groups?.currentValue?.trim()
: undefined;

if (depName && currentValue) {
results.push({
const dep: NugetPackageDependency = {
datasource: NugetDatasource.id,
depType: 'nuget',
depName,
currentValue,
});
};

if (groupName) {
dep.groupName = groupName;
}

results.push(dep);
}
} else if (name === 'Sdk') {
const depName = attr?.Name;
Expand Down Expand Up @@ -101,8 +123,21 @@ function extractDepsFromXml(xmlNode: XmlDocument): NugetPackageDependency[] {
});
}
}

const propertyGroup = child.childNamed('PropertyGroup');
if (propertyGroup) {
for (const propChild of propertyGroup.children) {
if (isXmlElem(propChild)) {
const { name, val } = propChild;
if (!['Version', 'TargetFramework'].includes(name)) {
vars.set(name, val);
}
}
}
}
}
todo.push(...(child.children.filter(isXmlElem) as XmlElement[]));

todo.push(...child.children.filter(isXmlElem));
}
}
return results;
Expand Down
Loading