Skip to content

Commit 857146a

Browse files
committed
Added code to add nuget audit settings to csproj files
1 parent bebfdb1 commit 857146a

File tree

4 files changed

+102
-41
lines changed

4 files changed

+102
-41
lines changed

src/CodeUpdater/CodeUpdater/Options/UpdateOptions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ public class UpdateOptions
5656
[Required]
5757
public required bool EnforceCodeStyleInBuild { get; set; }
5858

59+
/// <summary>
60+
/// Settings to use for configuring Nuget Audit settings in csproj files.
61+
/// You can read more at https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages#configuring-nuget-audit
62+
/// </summary>
63+
[Required]
64+
public required NugetAuditOptions NugetAudit { get; set; }
65+
5966
/// <summary>
6067
/// True to run the `dotnet format` command
6168
/// </summary>
@@ -71,4 +78,9 @@ public class UpdateOptions
7178
/// Verbosity level to log. Valid values are: Verbose, Info, Warn, Error. Default value: verbose.
7279
/// </summary>
7380
public string? LogLevel { get; set; } = "verbose";
81+
82+
public record NugetAuditOptions(
83+
[property: Required] bool NuGetAudit,
84+
[property: Required] string AuditMode,
85+
[property: Required] string AuditLevel);
7486
}

src/CodeUpdater/CodeUpdater/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"CodeUpdater": {
44
"commandName": "Project",
5-
"commandLineArgs": "--config-file \"../../../sampleUpdateOptions.json"
5+
"commandLineArgs": "--config \"../../../sampleUpdateOptions.json"
66
}
77
}
88
}

src/CodeUpdater/CodeUpdater/Updaters/CsProjUpdater.cs

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,38 @@ public CsProjUpdateResult UpdateCsProjPropertyValues(string csProjFilePath)
3535
CsprojUpdateTracker.EnforceCodeStyleInBuild,
3636
UpdateOptions.EnforceCodeStyleInBuild.ToString().ToLower(),
3737
addIfElementNotFound: true);
38+
var nuGetAuditUpdates = new CsprojUpdateTracker(
39+
CsprojUpdateTracker.NuGetAudit,
40+
UpdateOptions.NugetAudit.NuGetAudit.ToString().ToLower(),
41+
addIfElementNotFound: true);
42+
var nugetAuditModeUpdates = new CsprojUpdateTracker(
43+
CsprojUpdateTracker.NuGetAuditMode,
44+
UpdateOptions.NugetAudit.AuditMode.ToString().ToLower(),
45+
addIfElementNotFound: true);
46+
var nugetAuditLevelUpdates = new CsprojUpdateTracker(
47+
CsprojUpdateTracker.NuGetAuditLevel,
48+
UpdateOptions.NugetAudit.AuditLevel,
49+
addIfElementNotFound: true);
3850

3951
UpdateOrAddCsProjValues(
4052
csProjXmlDoc,
4153
propertyGroups,
42-
targetFrameworkUpdates,
43-
langUpdates,
44-
enableNETAnalyzersUpdates,
45-
enforceCodeStyleInBuildUpdates);
54+
new CsprojUpdateGroupTracker(CsprojUpdateGroupTracker.NotFoundActionType.DoNothing,
55+
[
56+
targetFrameworkUpdates,
57+
]),
58+
new CsprojUpdateGroupTracker(CsprojUpdateGroupTracker.NotFoundActionType.AddElementToFirstPropertyGroup,
59+
[
60+
langUpdates,
61+
enableNETAnalyzersUpdates,
62+
enforceCodeStyleInBuildUpdates,
63+
]),
64+
new CsprojUpdateGroupTracker(CsprojUpdateGroupTracker.NotFoundActionType.AddElementToNewPropertyGroup,
65+
[
66+
nuGetAuditUpdates,
67+
nugetAuditModeUpdates,
68+
nugetAuditLevelUpdates
69+
]));
4670

4771
//Write the file back out
4872
//Note: Use File.WriteAllText instead of Save() because calling XDocument.ToString() doesn't include the xml header
@@ -53,56 +77,60 @@ public CsProjUpdateResult UpdateCsProjPropertyValues(string csProjFilePath)
5377
return new CsProjUpdateResult(csProjFilePath, langVersionUpdateType, targetFrameworkUpdate);
5478
}
5579

56-
private void UpdateOrAddCsProjValues(XDocument csProjXmlDoc, List<XElement> propertyGroupsElements, params CsprojUpdateTracker[] updates)
80+
private void UpdateOrAddCsProjValues(XDocument csProjXmlDoc, List<XElement> propertyGroupsElements, params CsprojUpdateGroupTracker[] updateGroups)
5781
{
58-
foreach (var propertyGroupElement in propertyGroupsElements)
82+
//Separate updates into groups
83+
// This way, when the groups are added to the csproj, they are grouped together to the same PropetyGroup
84+
// Not important for functional reasons, but it makes the csproj file easier to read
85+
foreach (var group in updateGroups)
5986
{
60-
foreach (var update in updates)
87+
foreach (var propertyGroupElement in propertyGroupsElements)
6188
{
62-
if (update.ElementName == CsprojUpdateTracker.TargetFramework)
63-
{
64-
UpdateTargetFrameworkValue(propertyGroupElement, update);
65-
}
66-
else
89+
foreach (var update in group.UpdateTrackers)
6790
{
68-
UpdateCsprojValue(propertyGroupElement, update);
91+
if (update.ElementName == CsprojUpdateTracker.TargetFramework)
92+
{
93+
UpdateTargetFrameworkValue(propertyGroupElement, update);
94+
}
95+
else
96+
{
97+
UpdateCsprojValue(propertyGroupElement, update);
98+
}
6999
}
70100
}
71-
}
72101

73-
AddMissingElements(csProjXmlDoc, updates);
102+
AddMissingElements(csProjXmlDoc, group);
103+
}
74104
}
75105

76-
private void AddMissingElements(XDocument csProjXmlDoc, params CsprojUpdateTracker[] updates)
106+
private void AddMissingElements(XDocument csProjXmlDoc, CsprojUpdateGroupTracker updateGroup)
77107
{
78-
var updatesToMake = new List<CsprojUpdateTracker>();
79-
foreach (var update in updates)
108+
XElement? propertyGroupToAddTo = null;
109+
if (updateGroup.NotFoundAction == CsprojUpdateGroupTracker.NotFoundActionType.AddElementToFirstPropertyGroup)
80110
{
81-
if (update.ShouldAddElement())
82-
{
83-
updatesToMake.Add(update);
84-
}
111+
propertyGroupToAddTo = csProjXmlDoc.Descendants("PropertyGroup").FirstOrDefault();
85112
}
86-
87-
if (updatesToMake.Any())
113+
else if (updateGroup.NotFoundAction == CsprojUpdateGroupTracker.NotFoundActionType.AddElementToNewPropertyGroup)
88114
{
89-
var propertyGroup = csProjXmlDoc.Descendants("PropertyGroup").FirstOrDefault();
90-
if (propertyGroup is null)
91-
{
92-
Logger.Information("Adding new PropertyGroup element for other required elements");
93-
var newPropertyGroup = new XElement("PropertyGroup");
94-
csProjXmlDoc.Add(newPropertyGroup);
115+
Logger.Information("Adding new PropertyGroup element for other required elements");
116+
var newPropertyGroup = new XElement("PropertyGroup");
117+
csProjXmlDoc.Root!.Add(newPropertyGroup);
95118

96-
propertyGroup = newPropertyGroup;
97-
}
119+
propertyGroupToAddTo = newPropertyGroup;
120+
}
98121

99-
foreach (var elementToAdd in updatesToMake)
122+
//Add the trackers that haven't already set the final value
123+
var toUpdate = updateGroup.UpdateTrackers.Where(x => !x.HasMadeRequiredUpdate()).ToImmutableArray();
124+
if (propertyGroupToAddTo is not null
125+
&& toUpdate.Any())
126+
{
127+
foreach (var trackers in toUpdate)
100128
{
101-
Logger.Information($"Adding {elementToAdd.ElementName} element to csproj");
102-
var newElement = new XElement(elementToAdd.ElementName, elementToAdd.NewValue);
103-
propertyGroup.Add(newElement);
129+
Logger.Information($"Adding {trackers.ElementName} element to csproj");
130+
var newElement = new XElement(trackers.ElementName, trackers.NewValue);
131+
propertyGroupToAddTo.Add(newElement);
104132

105-
elementToAdd.SetResults.Add(CsprojValueUpdateResultType.AddedElement);
133+
trackers.SetResults.Add(CsprojValueUpdateResultType.AddedElement);
106134
}
107135
}
108136
}
@@ -197,13 +225,28 @@ private void UpdateTargetFrameworksValue(XElement childElm, CsprojUpdateTracker
197225
}
198226
}
199227

228+
private record CsprojUpdateGroupTracker(
229+
CsprojUpdateGroupTracker.NotFoundActionType NotFoundAction,
230+
IEnumerable<CsprojUpdateTracker> UpdateTrackers)
231+
{
232+
public enum NotFoundActionType
233+
{
234+
DoNothing,
235+
AddElementToFirstPropertyGroup,
236+
AddElementToNewPropertyGroup
237+
}
238+
}
239+
200240
private class CsprojUpdateTracker
201241
{
202242
public const string TargetFramework = "TargetFramework";
203243
public const string TargetFrameworks = "TargetFrameworks";
204244
public const string LangVersion = "LangVersion";
205245
public const string EnableNETAnalyzers = "EnableNETAnalyzers";
206246
public const string EnforceCodeStyleInBuild = "EnforceCodeStyleInBuild";
247+
public const string NuGetAudit = "NuGetAudit";
248+
public const string NuGetAuditMode = "NuGetAuditMode";
249+
public const string NuGetAuditLevel = "NuGetAuditLevel";
207250

208251
public CsprojUpdateTracker(string elementName, string newValue, bool addIfElementNotFound)
209252
: this(elementName, newValue, addIfElementNotFound, ImmutableArray<string>.Empty)
@@ -242,9 +285,10 @@ public CsprojValueUpdateResultType GetFinalResult()
242285
return CsprojValueUpdateResultType.NotFound;
243286
}
244287

245-
public bool ShouldAddElement()
288+
public bool HasMadeRequiredUpdate()
246289
{
247-
return AddIfElementNotFound && SetResults.All(x => x == CsprojValueUpdateResultType.NotFound);
290+
return SetResults.Any(x => x != CsprojValueUpdateResultType.NotFound
291+
&& x != CsprojValueUpdateResultType.Unknown);
248292
}
249293
}
250294
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
{
2-
"RootDirectory": "D:\\GitHub\\Purple-Spike\\arcade-machine-local-services\\src\\DeviceApp",
2+
"RootDirectory": "C:\\GitHub\\ProgrammerAl\\ProgrammerAlSite",
33
"IgnorePatterns": [],
44
"NpmBuildCommand": "publish",
55
"DotNetTargetFramework": "net8.0",
66
"DotNetLangVersion": "latest",
77
"EnableNetAnalyzers": true,
88
"EnforceCodeStyleInBuild": true,
99
"RunDotnetFormat": true,
10+
"NugetAudit": {
11+
"NuGetAudit": true,
12+
"AuditMode": "all",
13+
"AuditLevel": "low"
14+
},
1015
"OutputFile": "./code-updater-output.txt",
1116
"LogLevel": "Verbose"
1217
}

0 commit comments

Comments
 (0)