Current section
Files
Jump to
Current section
Files
src/go_over.gleam
import gleam/function
import gleam/int
import gleam/io
import gleam/json
import gleam/list
import gleam/option.{None, Some}
import gleam/string
import go_over/config.{type Config, Config}
import go_over/packages
import go_over/sources
import go_over/util/constants
import go_over/util/print
import go_over/util/spinner
import go_over/warning.{
type Warning, Direct, Indirect, SeverityCritical, SeverityHigh, SeverityLow,
SeverityModerate, SeverityPackageRetiredSecurity, SeverityRejectedLicense,
Warning, WarningReasonRetired, WarningReasonVulnerable,
}
import gxyz/function as gfunction
import shellout
import simplifile
fn print_warnings_count(vulns: List(Warning)) -> Nil {
{
"⛔ "
<> int.to_string(list.length(vulns))
<> " WARNING(s) FOUND!"
<> constants.long_ass_dashes
}
|> io.print_error()
}
fn print_warnings(vulns: List(Warning), conf: Config) -> Nil {
case conf.format {
config.Minimal ->
vulns
|> function.tap(print_warnings_count)
|> list.map(warning.format_as_string_minimal)
|> string.join("")
|> io.print_error()
config.JSON ->
vulns
|> list.map(warning.format_as_json)
|> json.preprocessed_array()
|> json.to_string()
|> io.print_error()
_ ->
vulns
|> function.tap(print_warnings_count)
|> list.map(warning.format_as_string)
|> string.join(constants.long_ass_dashes)
|> io.print_error()
}
shellout.exit(1)
}
pub fn main() {
let conf = case
config.spin_up(config.read_config("gleam.toml"), shellout.arguments())
{
Error(e) -> {
io.println_error(e)
shellout.exit(0)
panic as "Unreachable, please create an issue in https://github.com/bwireman/go-over if you see this"
}
Ok(conf) -> conf
}
let spinner = spinner.new_spinner("Let's do this!", conf.verbose)
gfunction.ignore_result(
conf.force,
gfunction.freeze1(simplifile.delete, constants.go_over_path(conf.global)),
)
spinner.set_text_spinner(spinner, "Reading manifest", conf.verbose)
let pkgs =
packages.read_manifest("manifest.toml")
|> config.filter_dev_dependencies(conf, _)
|> config.filter_packages(conf, _)
|> config.filter_indirect(conf, _)
spinner.set_text_spinner(
spinner,
"Checking packages: " <> print.raw("vulnerable", "red"),
conf.verbose,
)
let vulnerable_warnings = sources.get_vulnerable_warnings(pkgs, conf)
spinner.set_text_spinner(
spinner,
"Checking packages: " <> print.raw("retired", "yellow"),
conf.verbose,
)
let retired_warnings = sources.get_retired_warnings(pkgs, conf)
let hex_warnings =
gfunction.iff(
conf.outdated || list.length(conf.allowed_licenses) > 0,
fn() {
let msg = case conf.outdated, list.length(conf.allowed_licenses) > 0 {
True, True -> "outdated & licenses"
True, False -> "outdated"
False, True -> "licenses"
False, False ->
panic as "Unreachable, please create an issue in https://github.com/bwireman/go-over if you see this"
}
spinner.set_text_spinner(
spinner,
"Checking packages: " <> print.raw(msg, "brightmagenta"),
conf.verbose,
)
sources.get_hex_warnings(pkgs, conf)
},
[],
)
gfunction.iff_nil(
conf.fake,
gfunction.freeze2(print_warnings, example_warnings, conf),
)
spinner.set_text_spinner(spinner, "Filtering warnings", conf.verbose)
let warnings =
list.append(retired_warnings, vulnerable_warnings)
|> list.append(hex_warnings)
|> config.filter_severity(conf, _)
spinner.stop_spinner(spinner)
case warnings {
[] -> print.success("✅ No warnings found!")
vulns -> print_warnings(vulns, conf)
}
}
const example_warnings = [
Warning(
None,
"fake",
Some("x.y.z"),
"Retired",
WarningReasonVulnerable,
SeverityCritical,
Direct,
),
Warning(
None,
"another_fake",
Some("1.2.3"),
"Vulnerable",
WarningReasonVulnerable,
SeverityHigh,
Direct,
),
Warning(
None,
"and_another",
Some("4.5.6"),
"Vulnerable",
WarningReasonVulnerable,
SeverityModerate,
Direct,
),
Warning(
None,
"one_more",
Some("7.8.9"),
"Vulnerable",
WarningReasonVulnerable,
SeverityLow,
Indirect,
),
Warning(
None,
"this_one_was_retired",
Some("10.11.12"),
"Retired",
WarningReasonRetired,
SeverityPackageRetiredSecurity,
Indirect,
),
Warning(
None,
"rejected_license",
None,
"Retired",
WarningReasonRetired,
SeverityRejectedLicense,
Indirect,
),
]