Skip to content

Commit

Permalink
Adding dotnet package commands (#646)
Browse files Browse the repository at this point in the history
* Added new packages class

* Added initial calculation for outdated packages

* Created result object

* Updated test to use test repo

* Added base cases for 2 other nuget scanners

* updated tests

* Added sample to test project

* fixed tests

* added deprecated code

* Added vulnerable

* Updated paths

* Fix to path

* updated test name

* updated log

* update packages

* Update backslashes

* updated tests

* Added new item to post to

* Added new get for the controller
  • Loading branch information
samsmithnz committed Nov 12, 2023
1 parent 8facf95 commit 4cf18ed
Show file tree
Hide file tree
Showing 23 changed files with 455 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ jobs:
AppSettings.AzureClientSecret: "${{ secrets.AzureClientSecret }}"
#- run: echo "Tenant Id: $(env.AppSettings.AzureTenantId)"
- name: .NET test
run: dotnet test src/RepoGovernance.Tests/RepoGovernance.Tests.csproj --configuration Debug --logger trx -e:CollectCoverage=true -e:CoverletOutput=TestResults/ -e:CoverletOutputFormat=lcov
run: dotnet test src/RepoGovernance.Tests/RepoGovernance.Tests.csproj --configuration Debug --logger trx -e:CollectCoverage=true -e:CoverletOutput=TestResults/ -e:CoverletOutputFormat=lcov -l "console;verbosity=detailed"
- name: Publish coverage report to coveralls.io
uses: coverallsapp/github-action@master
with:
Expand Down
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
next-version: 0.18.0
next-version: 0.19.0
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.21.0" />
<PackageReference Include="RepoAutomation.Core" Version="1.5.6" />
<PackageReference Include="RepoAutomation.Core" Version="1.5.7" />
</ItemGroup>

<ItemGroup>
Expand Down
126 changes: 126 additions & 0 deletions src/RepoGovernance.Core/Helpers/DotnetPackages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
using Newtonsoft.Json;
using RepoGovernance.Core.Models.NuGetPackages;
using System.Diagnostics;
using Process = System.Diagnostics.Process;

namespace RepoGovernance.Core.Helpers
{
public class DotNetPackages
{
public List<NugetPackage> GetNugetPackagesDeprecated(string json)
{
List<NugetPackage> results = new();

//Process the output
Root? root = JsonConvert.DeserializeObject<Root>(json);
if (root != null && root.Projects != null && root.Projects.Count > 0)
{
foreach (Project project in root.Projects)
{
if (project.frameworks != null)
{
foreach (Framework framework in project.frameworks)
{
foreach (Package package in framework.topLevelPackages)
{
results.Add(new NugetPackage()
{
Path = project.path,
Framework = framework.framework,
PackageId = package.id,
PackageVersion = package.requestedVersion,
Type = "Deprecated"
});
}
}
}
}
}

return results;
}

public List<NugetPackage> GetNugetPackagesOutdated(string json)
{
List<NugetPackage> results = new();

//Process the output
Root? root = JsonConvert.DeserializeObject<Root>(json);
if (root != null && root.Projects != null && root.Projects.Count > 0)
{
foreach (Project project in root.Projects)
{
if (project.frameworks != null)
{
foreach (Framework framework in project.frameworks)
{
foreach (Package package in framework.topLevelPackages)
{
results.Add(new NugetPackage()
{
Path = project.path,
Framework = framework.framework,
PackageId = package.id,
PackageVersion = package.latestVersion,
Type = "Outdated"
});
}
}
}
}
}

return results;
}

public List<NugetPackage> GetNugetPackagesVulnerable(string json)
{
List<NugetPackage> results = new();

//Process the output
Root? root = JsonConvert.DeserializeObject<Root>(json);
if (root != null && root.Projects != null && root.Projects.Count > 0)
{
foreach (Project project in root.Projects)
{
if (project.frameworks != null)
{
foreach (Framework framework in project.frameworks)
{
foreach (Package package in framework.topLevelPackages)
{
results.Add(new NugetPackage()
{
Path = project.path,
Framework = framework.framework,
PackageId = package.id,
PackageVersion = package.requestedVersion,
Severity = package.GetFirstVulnerability(),
Type = "Vulnerable"
});
}
}
}
}
}

return results;
}

public string GetProcessOutput(string path, string arguments)
{
Process process = new();
ProcessStartInfo startInfo = new()
{
FileName = "dotnet.exe",
Arguments = arguments,
WorkingDirectory = path,
UseShellExecute = false,
RedirectStandardOutput = true,
};
process.StartInfo = startInfo;
process.Start();
return process.StandardOutput.ReadToEnd();
}
}
}
8 changes: 8 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/Framework.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class Framework
{
public string framework { get; set; }
public List<Package> topLevelPackages { get; set; }
}
}
12 changes: 12 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/NugetPackage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class NugetPackage
{
public string Path { get; set; }
public string Framework { get; set; }
public string PackageId { get; set; }
public string PackageVersion { get; set; }
public string Severity { get; set; }
public string Type { get; set; }
}
}
20 changes: 20 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/Package.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class Package
{
public string id { get; set; }

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'id' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'id' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string requestedVersion { get; set; }

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'requestedVersion' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'requestedVersion' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string resolvedVersion { get; set; }

Check warning on line 7 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'resolvedVersion' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 7 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'resolvedVersion' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string latestVersion { get; set; }

Check warning on line 8 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'latestVersion' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string[] deprecationReasons { get; set; }

Check warning on line 9 in src/RepoGovernance.Core/Models/NuGetPackages/Package.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'deprecationReasons' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public List<Vulnerability> vulnerabilities { get; set; }
public string GetFirstVulnerability()
{
if (vulnerabilities != null && vulnerabilities.Count > 0)
{
return vulnerabilities[0].severity;
}
return string.Empty;
}
}
}
8 changes: 8 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/Project.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class Project
{
public string path { get; set; }

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Project.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'path' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Project.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'path' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public List<Framework> frameworks { get; set; }

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Project.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'frameworks' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Project.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'frameworks' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}
}
7 changes: 7 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/Root.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class Root
{
public List<Project> Projects { get; set; }

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Root.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'Projects' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Root.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'Projects' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}
}
8 changes: 8 additions & 0 deletions src/RepoGovernance.Core/Models/NuGetPackages/Vulnerability.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace RepoGovernance.Core.Models.NuGetPackages
{
public class Vulnerability
{
public string severity { get; set; }

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Vulnerability.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'severity' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in src/RepoGovernance.Core/Models/NuGetPackages/Vulnerability.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'severity' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
public string advisoryurl { get; set; }

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Vulnerability.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable property 'advisoryurl' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 6 in src/RepoGovernance.Core/Models/NuGetPackages/Vulnerability.cs

View workflow job for this annotation

GitHub Actions / test

Non-nullable property 'advisoryurl' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}
}
3 changes: 3 additions & 0 deletions src/RepoGovernance.Core/Models/SummaryItem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GitHubActionsDotNet.Models.Dependabot;
using RepoAutomation.Core.Models;
using RepoGovernance.Core.Models.NuGetPackages;

namespace RepoGovernance.Core.Models
{
Expand All @@ -25,6 +26,7 @@ public SummaryItem(string user, string owner, string repo)
PullRequests = new();
RepoLanguages = new();
AzureDeployment = null;
NuGetPackages = new();
}

public string User { get; internal set; }
Expand Down Expand Up @@ -52,6 +54,7 @@ public SummaryItem(string user, string owner, string repo)
public CoverallsCodeCoverage? CoverallsCodeCoverage { get; set; }
public SonarCloud? SonarCloud { get; set; }
public AzureDeployment? AzureDeployment { get; set; }
public List<NugetPackage> NuGetPackages { get; set; }


public string OwnerRepo
Expand Down
2 changes: 1 addition & 1 deletion src/RepoGovernance.Core/RepoGovernance.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageReference Include="GitHubActionsDotNet" Version="1.2.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
<PackageReference Include="Microsoft.Graph" Version="5.34.0" />
<PackageReference Include="RepoAutomation.Core" Version="1.5.6" />
<PackageReference Include="RepoAutomation.Core" Version="1.5.7" />
</ItemGroup>

</Project>
47 changes: 45 additions & 2 deletions src/RepoGovernance.Core/SummaryItemsDA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using RepoGovernance.Core.APIAccess;
using RepoGovernance.Core.Helpers;
using RepoGovernance.Core.Models;
using RepoGovernance.Core.Models.NuGetPackages;
using RepoGovernance.Core.TableStorage;

namespace RepoGovernance.Core
Expand Down Expand Up @@ -162,7 +163,7 @@ public static List<UserOwnerRepo> GetRepos(string user)
int actionsCount = 0;
if (summaryItem?.DependabotRoot?.updates != null)
{
foreach (Package? item in summaryItem.DependabotRoot.updates)
foreach (GitHubActionsDotNet.Models.Dependabot.Package? item in summaryItem.DependabotRoot.updates)
{
if (item.package_ecosystem == "github-actions")
{
Expand Down Expand Up @@ -234,7 +235,7 @@ public static List<UserOwnerRepo> GetRepos(string user)
List<FrameworkSummary> frameworkSummaries = DotNetCensus.Core.Main.GetFrameworkSummary(null, repo2, false);
foreach (FrameworkSummary frameworkSummary in frameworkSummaries)
{
Framework framework = new()
Models.Framework framework = new()
{
Name = frameworkSummary.Framework,
Color = DotNetRepoScanner.GetColorFromStatus(frameworkSummary.Status),
Expand Down Expand Up @@ -402,5 +403,47 @@ public static List<UserOwnerRepo> GetRepos(string user)
return result;
;
}

public static async Task<int> UpdateSummaryItemNuGetPackageStats(string? connectionString,
string user,
string owner,
string repo,
string nugetPayload,
string payloadType)
{
int itemsUpdated = 0;

//Get the summary item
SummaryItem? summaryItem = await GetSummaryItem(connectionString, user, owner, repo);
if (summaryItem != null && nugetPayload != null && payloadType != null)
{
//Process the NuGet Package JSON payload
DotNetPackages dotNetPackages = new();
List<NugetPackage>? nugetResults = null;
switch (payloadType)
{
case "Deprecated":
nugetResults = dotNetPackages.GetNugetPackagesDeprecated(nugetPayload);
break;
case "Outdated":
nugetResults = dotNetPackages.GetNugetPackagesOutdated(nugetPayload);
break;
case "Vulnerable":
nugetResults = dotNetPackages.GetNugetPackagesVulnerable(nugetPayload);
break;
}
if (nugetResults != null)
{
//First remove results with the same type
summaryItem.NuGetPackages.RemoveAll(x => x.Type == payloadType);

//Add the results to the summary item
summaryItem.NuGetPackages.AddRange(nugetResults);
itemsUpdated += await AzureTableStorageDA.UpdateSummaryItemsIntoTable(connectionString, user, owner, repo, summaryItem);
}
}

return itemsUpdated;
}
}
}
7 changes: 7 additions & 0 deletions src/RepoGovernance.Service/Controllers/GitHubController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using RepoGovernance.Core.APIAccess;
using RepoGovernance.Core.Models;

namespace RepoGovernance.Service.Controllers
{
Expand All @@ -10,5 +12,10 @@ public class GitHubController : ControllerBase
//{
// RepoGovernance.Core.APIAccess.GitHubApiAccess.GetRepo();
//}
[HttpGet("GetRepos")]
public List<UserOwnerRepo> GetRepos(string user)
{
return DatabaseAccess.GetRepos(user);
}
}
}
27 changes: 27 additions & 0 deletions src/RepoGovernance.Service/Controllers/SummaryItemsController.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using RepoGovernance.Core;
using RepoGovernance.Core.Models;
using RepoGovernance.Service.Models;

namespace RepoGovernance.Service.Controllers
{
Expand Down Expand Up @@ -42,6 +43,32 @@ public async Task<int> UpdateSummaryItem(string user, string owner, string repo)
Configuration["AppSettings:AzureClientSecret"]);
}

[HttpPost("UpdateSummaryItemNuGetPackageStats")]
public async Task<int> UpdateSummaryItemNuGetPackageStats(NuGetPayload nugetPayload)
{
if (nugetPayload != null)
{
string? repo = nugetPayload?.Repo;
string? owner = nugetPayload?.Owner;
string? user = nugetPayload?.User;
string? jsonPayload = nugetPayload?.JsonPayload;
string? payloadType = nugetPayload?.PayloadType;

if (repo == null || owner == null || user == null || jsonPayload == null)
{
return -1;
}
return await SummaryItemsDA.UpdateSummaryItemNuGetPackageStats(
Configuration["AppSettings:CosmosDBConnectionString"],
user, owner, repo,
jsonPayload, payloadType);

Check warning on line 64 in src/RepoGovernance.Service/Controllers/SummaryItemsController.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'payloadType' in 'Task<int> SummaryItemsDA.UpdateSummaryItemNuGetPackageStats(string? connectionString, string user, string owner, string repo, string nugetPayload, string payloadType)'.
}
else
{
return -1;
}
}

/// <summary>
/// Get a list of summary item
/// </summary>
Expand Down
Loading

0 comments on commit 4cf18ed

Please sign in to comment.