Add support for Nuget restore (#4157)

* Nuget lock file support

Signed-off-by: balteraivshay <avishay.balter@gmail.com>

* fix shell download

Signed-off-by: balteraivshay <avishay.balter@gmail.com>

* Revert "fix shell download"

This reverts commit 9e66eb2280.

Signed-off-by: Spencer Schrock <sschrock@google.com>

---------

Signed-off-by: balteraivshay <avishay.balter@gmail.com>
Signed-off-by: Spencer Schrock <sschrock@google.com>
Co-authored-by: Spencer Schrock <sschrock@google.com>
This commit is contained in:
Avishay Balter 2024-07-11 00:04:59 +01:00 committed by GitHub
parent 32c4a43d7e
commit 78115dedad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 272 additions and 14 deletions

View File

@ -281,7 +281,7 @@ func TestGithubWorkflowPkgManagerPinning(t *testing.T) {
{
name: "npm packages without verification",
filename: "./testdata/.github/workflows/github-workflow-pkg-managers.yaml",
unpinned: 49,
unpinned: 52,
},
{
name: "Can't identify OS but doesn't crash",
@ -1409,7 +1409,7 @@ func TestDockerfileScriptDownload(t *testing.T) {
{
name: "pkg managers",
filename: "./testdata/Dockerfile-pkg-managers",
unpinned: 60,
unpinned: 63,
},
{
name: "download with some python",

View File

@ -764,19 +764,19 @@ func isUnpinnedNugetCliInstall(cmd []string) bool {
return unpinnedDependency
}
func isDotNetCliInstall(cmd []string) bool {
func isDotNetCliAdd(cmd []string) bool {
// Search for command of type dotnet add <PROJECT> package <PACKAGE_NAME>
if len(cmd) < 4 {
return false
}
// Search for dotnet add <PROJECT> package <PACKAGE_NAME>
// Search for dotnet add [PROJECT] package <PACKAGE_NAME>
// where package command can be either the second or the third word
return (isBinaryName("dotnet", cmd[0]) || isBinaryName("dotnet.exe", cmd[0])) &&
strings.EqualFold(cmd[1], "add") &&
(strings.EqualFold(cmd[2], "package") || strings.EqualFold(cmd[3], "package"))
}
func isUnpinnedDotNetCliInstall(cmd []string) bool {
func isUnpinnedDotNetCliAdd(cmd []string) bool {
unpinnedDependency := true
for i := 3; i < len(cmd); i++ {
// look for version flag
@ -789,12 +789,16 @@ func isUnpinnedDotNetCliInstall(cmd []string) bool {
return unpinnedDependency
}
func isNugetDownload(cmd []string) bool {
return isDotNetCliInstall(cmd) || isNugetCliInstall(cmd)
func isNuget(cmd []string) bool {
return isDotNetCliAdd(cmd) ||
isNugetCliInstall(cmd) ||
isDotNetCliRestore(cmd) ||
isNugetCliRestore(cmd) ||
isMsBuildRestore(cmd)
}
func isNugetUnpinnedDownload(cmd []string) bool {
if isDotNetCliInstall(cmd) && isUnpinnedDotNetCliInstall(cmd) {
func isNugetUnpinned(cmd []string) bool {
if isDotNetCliAdd(cmd) && isUnpinnedDotNetCliAdd(cmd) {
return true
}
@ -802,9 +806,97 @@ func isNugetUnpinnedDownload(cmd []string) bool {
return true
}
if isDotNetCliRestore(cmd) && isUnpinnedDotNetCliRestore(cmd) {
return true
}
if isNugetCliRestore(cmd) && isUnpinnedNugetCliRestore(cmd) {
return true
}
if isMsBuildRestore(cmd) && isUnpinnedMsBuildCliRestore(cmd) {
return true
}
return false
}
func isNugetCliRestore(cmd []string) bool {
// Search for command of type nuget restore
if len(cmd) < 2 {
return false
}
// Search for nuget restore
return (isBinaryName("nuget", cmd[0]) || isBinaryName("nuget.exe", cmd[0])) &&
strings.EqualFold(cmd[1], "restore")
}
func isDotNetCliRestore(cmd []string) bool {
// Search for command of type dotnet restore
if len(cmd) < 2 {
return false
}
// Search for dotnet restore
return (isBinaryName("dotnet", cmd[0]) || isBinaryName("dotnet.exe", cmd[0])) &&
strings.EqualFold(cmd[1], "restore")
}
func isMsBuildRestore(cmd []string) bool {
// Search for command of type msbuild /t:restore
if len(cmd) < 2 {
return false
}
// Search for msbuild /t:restore
if isBinaryName("msbuild", cmd[0]) || isBinaryName("msbuild.exe", cmd[0]) {
for i := 1; i < len(cmd); i++ {
// look for /t:restore flag
if strings.EqualFold(cmd[i], "/t:restore") {
return true
}
}
}
return false
}
func isUnpinnedNugetCliRestore(cmd []string) bool {
unpinnedDependency := true
for i := 2; i < len(cmd); i++ {
// look for LockedMode flag
// https://learn.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-restore
if strings.EqualFold(cmd[i], "-LockedMode") {
unpinnedDependency = false
break
}
}
return unpinnedDependency
}
func isUnpinnedDotNetCliRestore(cmd []string) bool {
unpinnedDependency := true
for i := 2; i < len(cmd); i++ {
// look for locked-mode flag
// https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-restore
if strings.EqualFold(cmd[i], "--locked-mode") {
unpinnedDependency = false
break
}
}
return unpinnedDependency
}
func isUnpinnedMsBuildCliRestore(cmd []string) bool {
unpinnedDependency := true
for i := 2; i < len(cmd); i++ {
// look for /p:RestoreLockedMode=true
// https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-restore
if strings.EqualFold(cmd[i], "/p:RestoreLockedMode=true") {
unpinnedDependency = false
break
}
}
return unpinnedDependency
}
func collectUnpinnedPackageManagerDownload(startLine, endLine uint, node syntax.Node,
cmd, pathfn string, r *checker.PinningDependenciesData,
) {
@ -900,8 +992,8 @@ func collectUnpinnedPackageManagerDownload(startLine, endLine uint, node syntax.
return
}
// Nuget install.
if isNugetDownload(c) {
// Nuget install and restore
if isNuget(c) {
r.Dependencies = append(r.Dependencies,
checker.Dependency{
Location: &checker.File{
@ -911,13 +1003,14 @@ func collectUnpinnedPackageManagerDownload(startLine, endLine uint, node syntax.
EndOffset: endLine,
Snippet: cmd,
},
Pinned: asBoolPointer(!isNugetUnpinnedDownload(c)),
Pinned: asBoolPointer(!isNugetUnpinned(c)),
Type: checker.DependencyUseTypeNugetCommand,
},
)
return
}
// TODO(laurent): add other package managers.
}

View File

@ -128,11 +128,95 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: true,
},
{
name: "nuget.exe install",
args: args{
cmd: []string{"nuget.exe", "install", "Newtonsoft.Json"},
},
want: true,
},
{
name: "nuget restore",
args: args{
cmd: []string{"nuget", "restore"},
},
want: true,
},
{
name: "nuget.exe restore",
args: args{
cmd: []string{"nuget.exe", "restore"},
},
want: true,
},
{
name: "msbuild restore",
args: args{
cmd: []string{"msbuild", "/t:restore"},
},
want: true,
},
{
name: "msbuild.exe restore",
args: args{
cmd: []string{"msbuild.exe", "/t:restore"},
},
want: true,
},
{
name: "nuget restore locked",
args: args{
cmd: []string{"nuget", "restore", "-LockedMode"},
},
want: false,
},
{
name: "nuget.exe restore locked",
args: args{
cmd: []string{"nuget.exe", "restore", "-LockedMode"},
},
want: false,
},
{
name: "msbuild restore locked",
args: args{
cmd: []string{"msbuild", "/t:restore", "/p:RestoreLockedMode=true"},
},
want: false,
},
{
name: "msbuild.exe restore locked",
args: args{
cmd: []string{"msbuild.exe", "/t:restore", "/p:RestoreLockedMode=true"},
},
want: false,
},
{
name: "dotnet restore",
args: args{
cmd: []string{"dotnet", "restore"},
},
want: true,
},
{
name: "dotnet.exe restore",
args: args{
cmd: []string{"dotnet.exe", "restore"},
},
want: true,
},
{
name: "dotnet restore locked",
args: args{
cmd: []string{"dotnet", "restore", "--locked-mode"},
},
want: false,
},
{
name: "dotnet.exe restore locked",
args: args{
cmd: []string{"dotnet.exe", "restore", "--locked-mode"},
},
want: false,
},
{
@ -142,6 +226,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "nuget.exe install with -Version",
args: args{
cmd: []string{"nuget.exe", "install", "Newtonsoft.Json", "-Version", "2"},
},
want: false,
},
{
name: "nuget install with packages.config",
args: args{
@ -149,6 +240,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "nuget.exe install with packages.config",
args: args{
cmd: []string{"nuget.exe", "install", "config\\packages.config"},
},
want: false,
},
{
name: "dotnet add",
args: args{
@ -156,6 +254,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: true,
},
{
name: "dotnet.exe add",
args: args{
cmd: []string{"dotnet.exe", "add", "package", "Newtonsoft.Json"},
},
want: true,
},
{
name: "dotnet add to project",
args: args{
@ -163,6 +268,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: true,
},
{
name: "dotnet.exe add to project",
args: args{
cmd: []string{"dotnet.exe", "add", "project1", "package", "Newtonsoft.Json"},
},
want: true,
},
{
name: "dotnet add reference to project",
args: args{
@ -170,6 +282,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "dotnet.exe add reference to project",
args: args{
cmd: []string{"dotnet.exe", "add", "project1", "reference", "OtherProject"},
},
want: false,
},
{
name: "dotnet build",
args: args{
@ -184,6 +303,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "dotnet.exe add with -v",
args: args{
cmd: []string{"dotnet.exe", "add", "package", "Newtonsoft.Json", "-v", "2.0"},
},
want: false,
},
{
name: "dotnet add to project with -v",
args: args{
@ -191,6 +317,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "dotnet.exe add to project with -v",
args: args{
cmd: []string{"dotnet.exe", "add", "project1", "package", "Newtonsoft.Json", "-v", "2.0"},
},
want: false,
},
{
name: "dotnet add reference to project with -v",
args: args{
@ -198,6 +331,13 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "dotnet.exe add reference to project with -v",
args: args{
cmd: []string{"dotnet.exe", "add", "project1", "reference", "Newtonsoft.Json", "-v", "2.0"},
},
want: false,
},
{
name: "dotnet add with --version",
args: args{
@ -205,12 +345,19 @@ func Test_isDotNetUnpinnedDownload(t *testing.T) {
},
want: false,
},
{
name: "dotnet.exe add with --version",
args: args{
cmd: []string{"dotnet.exe", "add", "package", "Newtonsoft.Json", "--version", "2.0"},
},
want: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := isNugetUnpinnedDownload(tt.args.cmd); got != tt.want {
if got := isNugetUnpinned(tt.args.cmd); got != tt.want {
t.Errorf("isNugetUnpinnedDownload() = %v, want %v", got, tt.want)
}
})

View File

@ -166,6 +166,16 @@ jobs:
run: nuget install 'some-package'
- name:
run: nuget restore
- name:
run: nuget restore -LockedMode
- name:
run: dotnet restore
- name:
run: dotnet restore --locked-mode
- name:
run: msbuild /t:restore /p:RestoreLockedMode=true
- name:
run: msbuild /t:restore
- name:
run: dotnet add package 'some-package'
- name:

View File

@ -127,6 +127,12 @@ RUN choco install --require-checksums 'some-package'
RUN nuget install some-package
RUN nuget restore
RUN nuget restore -LockedMode
RUN dotnet restore
RUN dotnet restore --locked-mode
RUN msbuild.exe /t:restore /p:RestoreLockedMode=true
RUN msbuild.exe /t:restore
RUN nuget restore -LockedMode
RUN nuget install some-package -Version 1.2.3
RUN nuget install packages.config
RUN dotnet add package some-package

View File

@ -125,7 +125,9 @@ choco install --requirechecksums 'some-package'
choco install --require-checksums 'some-package'
nuget install some-package
nuget restore
nuget restore -LockedMode
dotnet restore --locked-mode
msbuild.exe /t:restore /p:RestoreLockedMode=true
nuget install some-package -Version 1.2.3
nuget install packages.config
dotnet add package some-package