Skip to content

Commit fac56f8

Browse files
committed
(#365) Update Guidelines to include Cake 5.0.0
1 parent fe1bc78 commit fac56f8

File tree

8 files changed

+254
-15
lines changed

8 files changed

+254
-15
lines changed

docs/input/guidelines/CakeInternalReferences.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Title: Target Frameworks
1212
- [Cake v2.0.0](#cake-v200)
1313
- [Cake v3.0.0](#cake-v300)
1414
- [Cake v4.0](#cake-v40)
15+
- [Cake v5.0](#cake-v50)
1516
- [Related rules](#related-rules)
1617
- [Usage](#usage)
1718
- [Settings](#settings)
@@ -113,6 +114,31 @@ Also, the reference of the package in the addin/module should be set as private
113114
| System.Reflection.Metadata | 8.0.0 |
114115
| xunit | 2.6.1 |
115116

117+
#### Cake v5.0
118+
119+
| Reference | Version |
120+
| ---------------------------------------- | -------------- |
121+
| Autofac | 8.1.1 |
122+
| Microsoft.CodeAnalysis.CSharp.Scripting | 4.12.0-3.final |
123+
| Microsoft.CSharp | 4.7.0 |
124+
| Microsoft.Extensions.DependencyInjection | 9.0.0 |
125+
| Microsoft.IdentityModel.JsonWebTokens | 8.2.0 |
126+
| Microsoft.NETCore.Platforms | 7.0.4 |
127+
| Microsoft.SourceLink.GitHub | 8.0.0 |
128+
| Microsoft.Win32.Registry | 5.0.0 |
129+
| Newtonsoft.Json | 13.0.3 |
130+
| NuGet.Common | 6.11.1 |
131+
| NuGet.Frameworks | 6.11.1 |
132+
| NuGet.Packaging | 6.11.1 |
133+
| NuGet.Protocol | 6.11.1 |
134+
| NuGet.Resolver | 6.11.1 |
135+
| NuGet.Versioning | 6.11.1 |
136+
| StyleCop.Analyzers | 1.1.118 |
137+
| System.Collections.Immutable | 9.0.0 |
138+
| System.Reflection.Metadata | 9.0.0 |
139+
| System.Security.Cryptography.Pkcs | 9.0.0 |
140+
| xunit | 2.9.2 |
141+
116142
## Related rules
117143

118144
* [CCG0010](../rules/ccg0010)
@@ -127,4 +153,4 @@ Using this package automatically enables this guideline.
127153

128154
### Cake Version
129155

130-
<?! Include "../settings/fragments/OverrideCakeVersion.md" /?>
156+
<?! Include "../settings/fragments/OverrideCakeVersion.md" /?>

docs/input/guidelines/TargetFramework.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ while missing a suggested target version will raise [CCG0007](../rules/ccg0007)
4848
* Required: `net6.0`
4949
* Required: `net7.0`
5050
* Required: `net8.0`
51+
* Cake.Core >= 5.0.0
52+
* Required: `net8.0`
53+
* Required: `net9.0`
5154
* Package type: module
5255
* Cake.Core < 2.0.0
5356
* Required: `netstandard2.0`
@@ -61,6 +64,9 @@ while missing a suggested target version will raise [CCG0007](../rules/ccg0007)
6164
* Cake.Core >= 4.0.0
6265
* Required: `net6.0`
6366
* No additional targets are allowed.
67+
* Cake.Core >= 5.0.0
68+
* Required: `net8.0`
69+
* No additional targets are allowed.
6470

6571
For package type recipe no framework reference is required or suggested.
6672

src/Generators/Commands/PackageReferencesCommand.cs

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,35 @@ public class Settings : CommandSettings
4242

4343
public override int Execute(CommandContext context, Settings settings)
4444
{
45+
var opts = new EnumerationOptions { RecurseSubdirectories = true, MatchCasing = MatchCasing.CaseInsensitive };
46+
var globals = Directory.GetFiles(
47+
settings.CakeSourcePath,
48+
"Directory.Packages.props",
49+
opts);
4550
var projects = Directory.GetFiles(
4651
settings.CakeSourcePath,
4752
"*.csproj",
48-
new EnumerationOptions { RecurseSubdirectories = true, MatchCasing = MatchCasing.CaseInsensitive });
53+
opts);
4954

5055
console.WriteLine($"Found {projects.Length} projects");
5156

5257
var references = new Dictionary<string, PkgReference[]>();
5358

59+
var cpm = new CentralPackageManagement();
60+
foreach (string global in globals)
61+
{
62+
var relativePath = Path.GetRelativePath(settings.CakeSourcePath, global);
63+
console.MarkupLineInterpolated($"Processing CPM: {relativePath}");
64+
var foo = ProcessCentralPackageManagement(global, settings.ReferencesToSkip);
65+
if (foo is null)
66+
{
67+
continue;
68+
}
69+
70+
cpm.GlobalReferences.AddRange(foo.GlobalReferences);
71+
cpm.PackageVersions.AddRange(foo.PackageVersions);
72+
}
73+
5474
foreach (string proj in projects)
5575
{
5676
var file = Path.GetFileName(proj);
@@ -61,7 +81,7 @@ public override int Execute(CommandContext context, Settings settings)
6181
}
6282

6383
console.MarkupLineInterpolated($"Processing {file}");
64-
var refs = ProcessProject(proj, settings.ReferencesToSkip);
84+
var refs = ProcessProject(proj, settings.ReferencesToSkip, cpm);
6585
if (refs.Length > 0)
6686
{
6787
references.Add(file, refs);
@@ -71,7 +91,8 @@ public override int Execute(CommandContext context, Settings settings)
7191
console.MarkupLine("Flattening references");
7292
var allRefs = references
7393
.SelectMany(x => x.Value)
74-
.DistinctBy(x => $"{x.Name}|{x.Version ?? "0"}")
94+
.Where(x => x.Version != null)
95+
.DistinctBy(x => $"{x.Name}|{x.Version}")
7596
.ToLookup(x => x.Name)
7697
.OrderBy(x => x.Key)
7798
.ToArray();
@@ -207,7 +228,8 @@ private void PrintFlatList(IReadOnlyDictionary<string, string?> refs, string? gi
207228

208229
private PkgReference[] ProcessProject(
209230
string fullFile,
210-
Predicate<PkgReference>[] referencesToSkip)
231+
Predicate<PkgReference>[] referencesToSkip,
232+
CentralPackageManagement cpm)
211233
{
212234
var project = ProjectRootElement.Open(fullFile);
213235
if (project == null)
@@ -216,12 +238,12 @@ private PkgReference[] ProcessProject(
216238
return Array.Empty<PkgReference>();
217239
}
218240

219-
var foo = project.ItemGroups
241+
var packageReferences = project.ItemGroups
220242
.SelectMany(g => g.Children)
221243
.Where(c => c.ElementName.Equals("PackageReference", StringComparison.OrdinalIgnoreCase))
222244
.Cast<ProjectItemElement>()
223245
.ToArray();
224-
var references = foo
246+
var references = packageReferences
225247
.Select(x => new PkgReference
226248
{
227249
Name = x.Include,
@@ -231,12 +253,75 @@ private PkgReference[] ProcessProject(
231253
.Where(x => !referencesToSkip.Any(p => p(x)))
232254
.ToArray();
233255

234-
return references;
256+
var fromGlobals = references
257+
.Where(x => x.Version == null)
258+
.Select(x => cpm.PackageVersions.FirstOrDefault(y => y.Name == x.Name))
259+
.Where(x => x != null)
260+
.Cast<PkgReference>();
261+
262+
return references
263+
.Where(x => x.Version != null)
264+
.Concat(fromGlobals)
265+
.Concat(cpm.GlobalReferences)
266+
.ToArray();
267+
}
268+
269+
private CentralPackageManagement? ProcessCentralPackageManagement(string filePath, Predicate<PkgReference>[] referencesToSkip)
270+
{
271+
var project = ProjectRootElement.Open(filePath);
272+
if (project == null)
273+
{
274+
console.MarkupLineInterpolated($"[red]Failed to parse {Path.GetFileName(filePath)}[/]");
275+
return null;
276+
}
277+
278+
var globalPackageRefItems = project.ItemGroups
279+
.SelectMany(g => g.Children)
280+
.Where(c => c.ElementName.Equals("GlobalPackageReference", StringComparison.OrdinalIgnoreCase))
281+
.Cast<ProjectItemElement>()
282+
.ToArray();
283+
284+
var packageVersionItems = project.ItemGroups
285+
.SelectMany(g => g.Children)
286+
.Where(c => c.ElementName.Equals("PackageVersion", StringComparison.OrdinalIgnoreCase))
287+
.Cast<ProjectItemElement>()
288+
.ToArray();
289+
290+
var globalPackageRefs = globalPackageRefItems
291+
.Select(x => new PkgReference
292+
{
293+
Name = x.Include,
294+
Version = x.Metadata
295+
.FirstOrDefault(y => y.Name.Equals("Version", StringComparison.OrdinalIgnoreCase))?.Value,
296+
})
297+
.Where(x => !referencesToSkip.Any(p => p(x)))
298+
.ToArray();
299+
var packageVersions = packageVersionItems
300+
.Select(x => new PkgReference
301+
{
302+
Name = x.Include,
303+
Version = x.Metadata
304+
.FirstOrDefault(y => y.Name.Equals("Version", StringComparison.OrdinalIgnoreCase))?.Value,
305+
})
306+
.Where(x => !referencesToSkip.Any(p => p(x)))
307+
.ToArray();
308+
309+
var ret = new CentralPackageManagement();
310+
ret.GlobalReferences.AddRange(globalPackageRefs);
311+
ret.PackageVersions.AddRange(packageVersions);
312+
313+
return ret;
235314
}
236315

237316
public class PkgReference
238317
{
239318
public string Name { get; init; } = string.Empty;
240319
public string? Version { get; init; }
241320
}
321+
322+
public class CentralPackageManagement
323+
{
324+
public List<PkgReference> GlobalReferences { get; set; } = new();
325+
public List<PkgReference> PackageVersions { get; set; } = new();
326+
}
242327
}

src/Tasks.Tests/CheckCakeInternalReferencesTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,25 @@ public void Should_Warn_If_Newtonsoft_Is_Wrong_For_Cake_4()
170170
// then
171171
fixture.BuildEngine.WarningEvents.Count.ShouldBe(1);
172172
fixture.BuildEngine.WarningEvents.First().Code.ShouldBe(CcgRule10);
173-
fixture.BuildEngine.WarningEvents.First().Message.ShouldContain("13.0.3"); // the required version for NuGet.Common
173+
fixture.BuildEngine.WarningEvents.First().Message.ShouldContain("13.0.3"); // the required version for Newtonsoft
174+
}
175+
176+
[Fact]
177+
public void Should_Warn_If_NuGet_Is_Wrong_For_Cake_5()
178+
{
179+
// given
180+
var fixture = new CheckCakeInternalReferencesFixture();
181+
fixture.WithReference("NuGet.Packaging", "6.7.0");
182+
fixture.WithReference("Cake.Core", "5.0.0");
183+
fixture.WithCakeVersion(string.Empty);
184+
185+
// when
186+
fixture.Execute();
187+
188+
// then
189+
fixture.BuildEngine.WarningEvents.Count.ShouldBe(1);
190+
fixture.BuildEngine.WarningEvents.First().Code.ShouldBe(CcgRule10);
191+
fixture.BuildEngine.WarningEvents.First().Message.ShouldContain("6.11.1"); // the required version for NuGet.Packaging
174192
}
175193
}
176194
}

src/Tasks.Tests/TargetFrameworkVersionsTests.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class TargetFrameworkVersionsTests
2020
private const string Net60 = "net6.0";
2121
private const string Net70 = "net7.0";
2222
private const string Net80 = "net8.0";
23+
private const string Net90 = "net9.0";
2324

2425
[Fact]
2526
public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted()
@@ -369,6 +370,38 @@ public static IEnumerable<object[]> Should_Error_If_RequiredTargetFramework_Is_N
369370
yield return new object[] { new[] { Net60, Net70, Net80 }, false, string.Empty };
370371
}
371372

373+
[Theory]
374+
[MemberData(nameof(Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_5_Data))]
375+
public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_5(string[] targetFrameworks, bool expectedError, string missingTargetFramework)
376+
{
377+
// given
378+
var fixture = new TargetFrameworkVersionsFixture();
379+
fixture.WithCakeCoreReference(5);
380+
fixture.WithTargetFrameworks(targetFrameworks);
381+
382+
// when
383+
fixture.Execute();
384+
385+
// then
386+
if (expectedError)
387+
{
388+
fixture.BuildEngine.ErrorEvents.Count.ShouldBe(1);
389+
fixture.BuildEngine.ErrorEvents.First().Message.ShouldContain(missingTargetFramework);
390+
}
391+
else
392+
{
393+
fixture.BuildEngine.ErrorEvents.Count.ShouldBe(0);
394+
}
395+
}
396+
397+
public static IEnumerable<object[]> Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_5_Data()
398+
{
399+
yield return new object[] { Array.Empty<string>(), true, Net80 };
400+
yield return new object[] { new[] { Net80 }, true, Net90 };
401+
yield return new object[] { new[] { Net90 }, true, Net80 };
402+
yield return new object[] { new[] { Net80, Net90 }, false, string.Empty };
403+
}
404+
372405
[Fact]
373406
public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_2_Module()
374407
{
@@ -417,6 +450,22 @@ public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_4_Modul
417450
fixture.BuildEngine.ErrorEvents.First().Message.ShouldContain(Net60);
418451
}
419452

453+
[Fact]
454+
public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Cake_5_Module()
455+
{
456+
// given
457+
var fixture = new TargetFrameworkVersionsFixture();
458+
fixture.WithProjectType("module");
459+
fixture.WithCakeCoreReference("5.0.0");
460+
461+
// when
462+
fixture.Execute();
463+
464+
// then
465+
fixture.BuildEngine.ErrorEvents.Count.ShouldBe(1);
466+
fixture.BuildEngine.ErrorEvents.First().Message.ShouldContain(Net80);
467+
}
468+
420469
[Fact]
421470
public void Should_Error_If_RequiredTargetFramework_Is_Not_Targeted_Module_Explicit_Version()
422471
{

src/Tasks/CakeVersions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ internal static class CakeVersions
1919
// Cake 4.0.0
2020
public static readonly Version V4 = new Version(4, 0, 0);
2121

22+
// Cake 5.0.0
23+
public static readonly Version V5 = new Version(5, 0, 0);
24+
2225
// The next, currently non-existing cake version
23-
public static Version VNext = new Version(5, 0, 0);
26+
public static Version VNext = new Version(6, 0, 0);
2427
}
2528
}

src/Tasks/CheckCakeInternalReferences.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,31 @@ public class CheckCakeInternalReferences : Task
128128
{ "xunit", "2.6.1" },
129129
};
130130

131+
// parsed from Cake: v5.0
132+
private static readonly Dictionary<string, string> CakeV50 = new Dictionary<string, string>
133+
{
134+
{ "Autofac", "8.1.1" },
135+
{ "Microsoft.CodeAnalysis.CSharp.Scripting", "4.12.0-3.final" },
136+
{ "Microsoft.CSharp", "4.7.0" },
137+
{ "Microsoft.Extensions.DependencyInjection", "9.0.0" },
138+
{ "Microsoft.IdentityModel.JsonWebTokens", "8.2.0" },
139+
{ "Microsoft.NETCore.Platforms", "7.0.4" },
140+
{ "Microsoft.SourceLink.GitHub", "8.0.0" },
141+
{ "Microsoft.Win32.Registry", "5.0.0" },
142+
{ "Newtonsoft.Json", "13.0.3" },
143+
{ "NuGet.Common", "6.11.1" },
144+
{ "NuGet.Frameworks", "6.11.1" },
145+
{ "NuGet.Packaging", "6.11.1" },
146+
{ "NuGet.Protocol", "6.11.1" },
147+
{ "NuGet.Resolver", "6.11.1" },
148+
{ "NuGet.Versioning", "6.11.1" },
149+
{ "StyleCop.Analyzers", "1.1.118" },
150+
{ "System.Collections.Immutable", "9.0.0" },
151+
{ "System.Reflection.Metadata", "9.0.0" },
152+
{ "System.Security.Cryptography.Pkcs", "9.0.0" },
153+
{ "xunit", "2.9.2" },
154+
};
155+
131156
private readonly Dictionary<Predicate<Version>, Dictionary<string, string>> allInternalReferences =
132157
new Dictionary<Predicate<Version>, Dictionary<string, string>>
133158
{
@@ -148,9 +173,13 @@ public class CheckCakeInternalReferences : Task
148173
CakeV30
149174
},
150175
{
151-
x => x.GreaterEqual(CakeVersions.V4) && x.LessThan(CakeVersions.VNext),
176+
x => x.GreaterEqual(CakeVersions.V4) && x.LessThan(CakeVersions.V5),
152177
CakeV40
153178
},
179+
{
180+
x => x.GreaterEqual(CakeVersions.V5) && x.LessThan(CakeVersions.VNext),
181+
CakeV50
182+
},
154183
};
155184

156185
/// <summary>

0 commit comments

Comments
 (0)