Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/pkgchk-cli/Commands.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
namespace pkgchk

module Commands =

let private runProc logging proc =
try
proc |> Io.run logging
finally
proc.Dispose()

let console = Spectre.Console.AnsiConsole.MarkupLine

let trace traceLogging =
if traceLogging then Console.grey >> console else ignore

let getErrors procResults =
procResults
|> Seq.map (function
| Choice2Of2 x -> x
| _ -> "")
|> Seq.filter String.isNotEmpty
|> Seq.distinct

let returnError error =
error |> Console.error |> console
ReturnCodes.sysError

let renderTables (values: seq<Spectre.Console.Table>) =
values |> Seq.iter Spectre.Console.AnsiConsole.Write

let liftHits procResults =
procResults
|> Seq.collect (function
| Choice1Of2 xs -> xs
| _ -> [])
|> List.ofSeq

let sortHits (hits: seq<ScaHit>) =
hits
|> Seq.sortBy (fun h ->
((match h.kind with
| ScaHitKind.Vulnerability -> 0
| ScaHitKind.Dependency -> 1
| ScaHitKind.VulnerabilityTransitive -> 2
| ScaHitKind.Deprecated -> 3
| ScaHitKind.DependencyTransitive -> 4),
h.packageId))

let getHits x = x |> liftHits |> sortHits |> List.ofSeq

let restore (settings: PackageCommandSettings) logging =
if settings.NoRestore then
Choice1Of2 false
else
let runRestoreProcParse run proc =
proc
|> run
|> (function
| Choice2Of2 error -> Choice2Of2 error
| _ -> Choice1Of2 true)

settings.ProjectPath
|> Sca.restoreArgs
|> Io.createProcess
|> runRestoreProcParse (runProc logging)

let scan trace =
Sca.scanArgs
>> Array.map (fun (args, parser) -> (Io.createProcess args, parser))
>> Array.map (fun (proc, parser) ->
match proc |> (runProc trace) with
| Choice1Of2 json -> parser json
| Choice2Of2 x -> Choice2Of2 x)
30 changes: 30 additions & 0 deletions src/pkgchk-cli/PackageCommandSettings.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace pkgchk

open System
open System.ComponentModel
open System.Diagnostics.CodeAnalysis
open Spectre.Console.Cli

[<ExcludeFromCodeCoverage>]
type PackageCommandSettings() =
inherit CommandSettings()

[<CommandArgument(0, "[SOLUTION|PROJECT]")>]
[<Description("The solution or project file to check.")>]
[<DefaultValue("")>]
member val ProjectPath = "" with get, set

[<CommandOption("--trace")>]
[<Description("Show detailed working and Nuget results.")>]
[<DefaultValue(false)>]
member val TraceLogging = false with get, set

[<CommandOption("--no-restore")>]
[<Description("Don't automatically restore packages.")>]
[<DefaultValue(false)>]
member val NoRestore = false with get, set

[<CommandOption("--no-banner")>]
[<Description("Don't show the banner.")>]
[<DefaultValue(false)>]
member val NoBanner = false with get, set
107 changes: 10 additions & 97 deletions src/pkgchk-cli/PackageListCommand.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,124 +6,37 @@ open Spectre.Console.Cli

[<ExcludeFromCodeCoverage>]
type PackageListCommandSettings() =
inherit CommandSettings()

[<CommandArgument(0, "[SOLUTION|PROJECT]")>]
[<Description("The solution or project file to check.")>]
[<DefaultValue("")>]
member val ProjectPath = "" with get, set
inherit PackageCommandSettings()

[<CommandOption("-t|--transitive")>]
[<Description("Toggle transitive package checks. true to include them, false to exclude.")>]
[<DefaultValue(true)>]
member val IncludeTransitives = true with get, set

[<CommandOption("--trace")>]
[<Description("Show detailed working and Nuget results.")>]
[<DefaultValue(false)>]
member val TraceLogging = false with get, set

[<CommandOption("--no-restore")>]
[<Description("Don't automatically restore packages.")>]
[<DefaultValue(false)>]
member val NoRestore = false with get, set

[<CommandOption("--no-banner")>]
[<Description("Don't show the banner.")>]
[<DefaultValue(false)>]
member val NoBanner = false with get, set

[<ExcludeFromCodeCoverage>]
type PackageListCommand(nuget: Tk.Nuget.INugetClient) =
inherit Command<PackageListCommandSettings>()

let console = Spectre.Console.AnsiConsole.MarkupLine

let trace traceLogging =
if traceLogging then Console.grey >> console else ignore

let returnError error =
error |> Console.error |> console
ReturnCodes.sysError

let runProc logging proc =
try
proc |> Io.run logging
finally
proc.Dispose()

let runRestore (settings: PackageListCommandSettings) logging =
if settings.NoRestore then
Choice1Of2 false
else
let runRestoreProcParse run proc =
proc
|> run
|> (function
| Choice2Of2 error -> Choice2Of2 error
| _ -> Choice1Of2 true)

settings.ProjectPath
|> Sca.restoreArgs
|> Io.createProcess
|> runRestoreProcParse (runProc logging)

let getErrors procResults =
procResults
|> Seq.map (function
| Choice2Of2 x -> x
| _ -> "")
|> Seq.filter String.isNotEmpty
|> Seq.distinct

let renderTables (values: seq<Spectre.Console.Table>) =
values |> Seq.iter Spectre.Console.AnsiConsole.Write

let liftHits procResults =
procResults
|> Seq.collect (function
| Choice1Of2 xs -> xs
| _ -> [])
|> List.ofSeq

let sortHits (hits: seq<ScaHit>) =
hits
|> Seq.sortBy (fun h ->
((match h.kind with
| ScaHitKind.Vulnerability -> 0
| ScaHitKind.Dependency -> 1
| ScaHitKind.VulnerabilityTransitive -> 2
| ScaHitKind.Deprecated -> 3
| ScaHitKind.DependencyTransitive -> 4),
h.packageId))

let getHits = liftHits >> sortHits >> List.ofSeq

override _.Execute(context, settings) =
let trace = trace settings.TraceLogging
let trace = Commands.trace settings.TraceLogging

if settings.NoBanner |> not then
nuget |> App.banner |> console
nuget |> App.banner |> Commands.console

match runRestore settings trace with
| Choice2Of2 error -> error |> returnError
match Commands.restore settings trace with
| Choice2Of2 error -> error |> Commands.returnError
| _ ->
let results =
(settings.ProjectPath, false, settings.IncludeTransitives, false, true)
|> Sca.scanArgs
|> Array.map (fun (args, parser) -> (Io.createProcess args, parser))
|> Array.map (fun (proc, parser) ->
match proc |> (runProc trace) with
| Choice1Of2 json -> parser json
| Choice2Of2 x -> Choice2Of2 x)
|> Commands.scan trace

let errors = getErrors results
let errors = Commands.getErrors results

if Seq.isEmpty errors |> not then
errors |> String.joinLines |> returnError
errors |> String.joinLines |> Commands.returnError
else
trace "Analysing results..."
let hits = getHits results
let hits = Commands.getHits results
let hitCounts = hits |> Sca.hitCountSummary |> List.ofSeq

trace "Building display..."
Expand All @@ -136,6 +49,6 @@ type PackageListCommand(nuget: Tk.Nuget.INugetClient) =
hitCounts |> Console.hitSummaryTable
}

renderTables renderables
Commands.renderTables renderables

ReturnCodes.validationOk
Loading