Skip to content

Commit b449f8a

Browse files
committed
We will now maintain a package cache to speed-up the analysis.
1 parent 2344d84 commit b449f8a

25 files changed

+375
-94
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
run: ./build.ps1
2626
env:
2727
NuGetApiKey: ${{ secrets.NUGETAPIKEY }}
28+
GitHubApiKey: ${{ secrets.GITHUB_TOKEN }}
2829

2930
- name: Check for 'lcov.info' existence
3031
id: check_files

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ AppPackages/
115115

116116
# Others
117117
sql/
118-
*.Cache
119118
ClientBin/
120119
[Ss]tyle[Cc]op.*
121120
~$*
@@ -191,4 +190,4 @@ Tests/FluentAssertions.Specs/FluentAssertions.Specs.xml
191190
Tests/Benchmarks/BenchmarkDotNet.Artifacts/
192191

193192
# Documentation spell check
194-
node_modules/
193+
node_modules/

.nuke/build.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@
114114
"Release"
115115
]
116116
},
117+
"GitHubApiKey": {
118+
"type": "string",
119+
"description": "The key to use for scanning packages on GitHub",
120+
"default": "Secrets must be entered via 'nuke :secrets [profile]'"
121+
},
117122
"NuGetApiKey": {
118123
"type": "string",
119124
"description": "The key to push to Nuget",

.packageguard/.cache

73.7 KB
Binary file not shown.

Build/Build.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ class Build : NukeBuild
3737
[Secret]
3838
readonly string NuGetApiKey;
3939

40+
[Parameter("The key to use for scanning packages on GitHub")]
41+
[Secret]
42+
readonly string GitHubApiKey;
43+
4044
[Solution(GenerateProjects = true)]
4145
readonly Solution Solution;
4246

@@ -129,6 +133,10 @@ class Build : NukeBuild
129133
.SetProjectFile(project)
130134
.SetConfiguration(Configuration == Configuration.Debug ? "Debug" : "Release")
131135
.AddApplicationArguments($"--configpath={RootDirectory / "PackageGuard.config.json"}")
136+
.WhenNotNull(GitHubApiKey, (ss, key) => ss
137+
.AddApplicationArguments($"--github-api-key={key}")
138+
.AddProcessRedactedSecrets(key))
139+
.AddApplicationArguments("--use-caching")
132140
.AddApplicationArguments($"{RootDirectory}")
133141
.EnableNoBuild()
134142
.EnableNoRestore());

README.md

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,20 @@ Then use `packageguard --help` to see a list of options.
5757

5858
```
5959
USAGE:
60-
PackageGuard.dll [path] [OPTIONS]
60+
PackageGuard.dll [path] [OPTIONS]
6161
6262
ARGUMENTS:
6363
[path] The path to a directory containing a .sln file, a specific .sln file, or a specific .csproj file. Defaults to the current working directory
6464
6565
OPTIONS:
66-
-h, --help Prints help information
67-
--configPath The path to the configuration file. Defaults to the config.json in the current working directory
68-
--restore-interactive Allow enabling or disabling an interactive mode of "dotnet restore". Defaults to true
69-
--force-restore Force restoring the NuGet dependencies, even if the lockfile is up-to-date
70-
--skip-restore Prevent the restore operation from running, even if the lock file is missing or out-of-date
71-
--github-api-key GitHub API key to use for fetching package licenses. If not specified, you may run into GitHub's rate limiting issues
66+
-h, --help Prints help information
67+
-c, --config-path The path to the configuration file. Defaults to the config.json in the current working directory
68+
-i, --restore-interactive Allow enabling or disabling an interactive mode of "dotnet restore". Defaults to true
69+
-f, --force-restore Force restoring the NuGet dependencies, even if the lockfile is up-to-date
70+
-s, --skip-restore Prevent the restore operation from running, even if the lock file is missing or out-of-date
71+
-a, --github-api-key GitHub API key to use for fetching package licenses. If not specified, you may run into GitHub's rate limiting issues
72+
--use-caching Maintains a cache of the package information to speed up future analysis
73+
--cache-file-path Overrides the file path where analysis data is cached. Defaults to the "<workingdirectory>/.packageguard/.cache"
7274
```
7375

7476
## How do I configure it?
@@ -149,6 +151,14 @@ The exit code indicates either 0 for success or 1 for failure.
149151

150152
## Additional notes
151153

154+
### Speeding up the analysis using caching
155+
156+
One of the most expensive operations that PackageGuard needs to do is to download find the license information from GitHub or other sources. You can significantly speed-up the analysis process by using the `--use-caching` flag.
157+
158+
By default, this will cause PackageGuard to persist the license information it retrieved to a binary file under `.packageguard\.cache`. You can commit this file to source control so successive runs can reuse the license information it collected during a previous run.
159+
160+
If PackageGuard finds new packages in your project or solution that did not exist during the previous run, then it will update the cache after the analysis is completed.
161+
152162
### Github rate limiting issues
153163

154164
If you're running into errors from GitHub like
@@ -163,21 +173,20 @@ After having generated such a token, pass it to PackageGuard through its `github
163173

164174
This is a rough list of items from my personal backlog that I'll be working on the coming weeks.
165175

166-
**Complete the MVP**
176+
**Major features**
177+
- Add support for the new .slnx file
178+
- Add NPM support
179+
180+
**Minor features**
167181
- Allow specifying the location of `dotnet.exe`
168182
- Allow ignoring certain .csproj files or folders using Globs or wildcards (e.g. build.csproj)
169183
- Allow marking all violations as a warning
170184
- Allow marking individual violations as a warning
171-
- Add caching of licenses
172185
- Expose the internal engine through the `PackageGuard.Core` NuGet package
173186
- Add direct support for [Nuke](https://nuke.build/)
174187
- Allow loading settings from the directory of the scanned project and move up if not found
175188
- Display the reason why a package was marked as a violation
176189

177-
**Major features**
178-
- Add support for the new .slnx file
179-
- Add NPM support
180-
181190
## Building
182191

183192
To build this repository locally, you need the following:
@@ -220,9 +229,13 @@ This library wouldn't have been possible without the following tools, packages a
220229
* [ReportGenerator](https://reportgenerator.io/) - Converts coverage reports by [Daniel Palme](https://github.com/danielpalme)
221230
* [StyleCopyAnalyzer](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) - StyleCop rules for .NET
222231
* [Roslynator](https://github.com/dotnet/roslynator) - A set of code analysis tools for C# by [Josef Pihrt](https://github.com/josefpihrt)
232+
* [Serilog](https://serilog.net/) - Flexible, structured events — log file convenience
223233
* [CSharpCodingGuidelines](https://github.com/bkoelman/CSharpGuidelinesAnalyzer) - Roslyn analyzers by [Bart Koelman](https://github.com/bkoelman) to go with the [C# Coding Guidelines](https://csharpcodingguidelines.com/)
224234
* [Meziantou](https://github.com/meziantou/Meziantou.Framework) - Another set of awesome Roslyn analyzers by [Gérald Barré](https://github.com/meziantou)
235+
* [FluentAssertions](https://github.com/fluentassertions/fluentassertions) - Extension methods to fluently assert the outcome of .NET tests
225236
* [Verify](https://github.com/VerifyTests/Verify) - Snapshot testing by [Simon Cropp](https://github.com/SimonCropp)
237+
* [Pathy](https://github.com/dennisdoomen/pathy?tab=readme-ov-file#readme) - Fluently building and using file and directory paths without binary dependencies
238+
* [MemoryPack](https://github.com/Cysharp/MemoryPack) - Zero encoding extreme performance binary serializer for C# and Unity by [Yoshifumi Kawai](https://github.com/neuecc)
226239

227240
## Support the project
228241
* [Sponsor me](https://github.com/sponsors/dennisdoomen)
@@ -233,9 +246,7 @@ This library wouldn't have been possible without the following tools, packages a
233246

234247
* [My Blog](https://www.dennisdoomen.com)
235248
* [Reflectify](https://github.com/dennisdoomen/reflectify) - Reflection extensions without causing dependency pains
236-
* [Pathy](https://github.com/dennisdoomen/pathy?tab=readme-ov-file#readme) - Fluently building and using file and directory paths without binary dependencies
237249
* [.NET Library Starter Kit](https://github.com/dennisdoomen/dotnet-package-templates) - A battle-tested starter kit for building open-source and internal NuGet libraries using "dotnet new", born from half a billion downloads
238-
* [FluentAssertions](https://github.com/fluentassertions/fluentassertions) - Extension methods to fluently assert the outcome of .NET tests
239250
* [C# Coding Guidelines](https://csharpcodingguidelines.com/) - Forkable coding guidelines for all C# versions
240251

241252
## License

Src/PackageGuard.ApiVerificationTests/ApiApproval.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using System.Xml.Linq;
77
using System.Xml.XPath;
8+
using PackageGuard.Core;
89
using Pathy;
910
using PublicApiGenerator;
1011
using VerifyTests;
@@ -26,9 +27,7 @@ static ApiApproval()
2627
[Fact]
2728
public Task ApproveApi()
2829
{
29-
var configuration = typeof(ApiApproval).Assembly.GetCustomAttribute<AssemblyConfigurationAttribute>()!.Configuration;
30-
var assemblyFile = SourcePath / "PackageGuard.Core" / "bin" / configuration / "net8.0" / "PackageGuard.Core.dll";
31-
var assembly = Assembly.LoadFile(assemblyFile);
30+
var assembly = typeof(LicenseFetcher).Assembly;
3231
var publicApi = assembly.GeneratePublicApi(options: null);
3332

3433
return Verifier

Src/PackageGuard.ApiVerificationTests/ApprovedApi/net8.0.verified.txt

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ namespace PackageGuard.Core
1010
{
1111
public CSharpProjectAnalyzer(PackageGuard.Core.CSharpProjectScanner scanner, PackageGuard.Core.NuGetPackageAnalyzer analyzer) { }
1212
public PackageGuard.Core.AllowList AllowList { get; set; }
13+
public string CacheFilePath { get; set; }
1314
public PackageGuard.Core.DenyList DenyList { get; set; }
1415
public bool ForceRestore { get; set; }
1516
public string[] IgnoredFeeds { get; set; }
1617
public bool InteractiveRestore { get; set; }
1718
public Microsoft.Extensions.Logging.ILogger Logger { get; set; }
1819
public string ProjectPath { get; set; }
1920
public bool SkipRestore { get; set; }
21+
public bool UseCaching { get; set; }
2022
public System.Threading.Tasks.Task<PackageGuard.Core.PolicyViolation[]> ExecuteAnalysis() { }
2123
}
2224
public class CSharpProjectScanner
@@ -53,13 +55,14 @@ namespace PackageGuard.Core
5355
public string[] IgnoredFeeds { get; set; }
5456
public System.Threading.Tasks.Task CollectPackageMetadata(string projectPath, string packageName, NuGet.Versioning.NuGetVersion packageVersion, PackageGuard.Core.PackageInfoCollection packages) { }
5557
}
56-
public class PackageInfo
58+
[MemoryPack.MemoryPackable(MemoryPack.GenerateType.Object)]
59+
public class PackageInfo : MemoryPack.IMemoryPackFormatterRegister, MemoryPack.IMemoryPackable<PackageGuard.Core.PackageInfo>
5760
{
5861
public PackageInfo() { }
59-
public string Id { get; set; }
6062
public string? License { get; set; }
6163
public string? LicenseUrl { get; set; }
62-
public System.Collections.Generic.List<string> Projects { get; set; }
64+
public string Name { get; set; }
65+
public string[] Projects { get; set; }
6366
public string? RepositoryUrl { get; set; }
6467
public string Source { get; set; }
6568
public string SourceUrl { get; set; }
@@ -71,10 +74,12 @@ namespace PackageGuard.Core
7174
}
7275
public class PackageInfoCollection : System.Collections.Generic.IEnumerable<PackageGuard.Core.PackageInfo>, System.Collections.IEnumerable
7376
{
74-
public PackageInfoCollection() { }
77+
public PackageInfoCollection(Microsoft.Extensions.Logging.ILogger logger) { }
7578
public void Add(PackageGuard.Core.PackageInfo package) { }
76-
public PackageGuard.Core.PackageInfo? Find(string libraryName, string libraryVersion) { }
79+
public PackageGuard.Core.PackageInfo? Find(string name, string version, NuGet.Protocol.Core.Types.SourceRepository[] projectNuGetSources) { }
7780
public System.Collections.Generic.IEnumerator<PackageGuard.Core.PackageInfo> GetEnumerator() { }
81+
public System.Threading.Tasks.Task TryInitializeFromCache(string cacheFilePath) { }
82+
public System.Threading.Tasks.Task WriteToCache(string cacheFilePath) { }
7883
}
7984
public abstract class PackagePolicy
8085
{

Src/PackageGuard.ApiVerificationTests/PackageGuard.ApiVerificationTests.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@
2020
<PackageReference Include="Verify.Xunit" Version="30.4.0" />
2121
</ItemGroup>
2222

23+
<ItemGroup>
24+
<ProjectReference Include="..\PackageGuard.Core\PackageGuard.Core.csproj" />
25+
</ItemGroup>
26+
2327
</Project>

Src/PackageGuard.Core/AllowList.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal bool Allows(PackageInfo package)
2626

2727
foreach (PackageSelector selector in Packages)
2828
{
29-
if (package.Id == selector.Id)
29+
if (package.Name == selector.Id)
3030
{
3131
if (selector.VersionRange is not null &&
3232
!package.SatisfiesRange(selector.Id, selector.VersionRange))

0 commit comments

Comments
 (0)