From a480205fbab22185a853d9ba623372d9e44a82f0 Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 4 Jun 2024 17:18:40 -0500 Subject: [PATCH 1/6] hard_fail use panic --- src/go_over/advisories/advisories.gleam | 42 +++++++++++------------- src/go_over/advisories/comparisons.gleam | 7 ++-- src/go_over/config.gleam | 4 +-- src/go_over/packages.gleam | 23 +++++-------- src/go_over/retired.gleam | 25 +++++++------- src/go_over/util/cache.gleam | 3 +- src/go_over/util/constants.gleam | 3 +- src/go_over/util/util.gleam | 7 ++-- 8 files changed, 50 insertions(+), 64 deletions(-) diff --git a/src/go_over/advisories/advisories.gleam b/src/go_over/advisories/advisories.gleam index 33d11f1..2743fca 100644 --- a/src/go_over/advisories/advisories.gleam +++ b/src/go_over/advisories/advisories.gleam @@ -1,6 +1,6 @@ import filepath import gleam/list -import gleam/option.{Some} +import gleam/option.{None, Some} import gleam/string import go_over/advisories/comparisons import go_over/packages.{type Package} @@ -52,7 +52,7 @@ fn read_adv(path: String) -> Advisory { fn read_all_adv() -> List(Advisory) { let packages_path = filepath.join(path(), "packages") - let assert Some(packages) = + let packages = hard_fail( simplifile.read_directory(packages_path), "could not read " <> packages_path, @@ -60,7 +60,7 @@ fn read_all_adv() -> List(Advisory) { list.flat_map(packages, fn(dir) { let dir_path = filepath.join(packages_path, dir) - let assert Some(adv_names) = + let adv_names = hard_fail( simplifile.read_directory(dir_path), "could not read " <> dir_path, @@ -101,23 +101,21 @@ fn delete_and_clone() -> Nil { let _ = simplifile.delete(p) print.progress("Cloning: " <> constants.advisories_repo <> "...") - let assert Some(Nil) = - path() - |> simplifile.create_directory_all() - |> hard_fail("could not create directory at " <> path()) - - let assert Some(_) = - shellout.command( - run: "git", - with: [ - "clone", - "https://github.com/" <> constants.advisories_repo <> ".git", - path(), - ], - in: ".", - opt: [], - ) - |> hard_fail("could not clone " <> constants.advisories_repo) + path() + |> simplifile.create_directory_all() + |> hard_fail("could not create directory at " <> path()) + + shellout.command( + run: "git", + with: [ + "clone", + "https://github.com/" <> constants.advisories_repo <> ".git", + path(), + ], + in: ".", + opt: [], + ) + |> hard_fail("could not clone " <> constants.advisories_repo) [ ".git", ".gitignore", ".github", "config", "lib", ".formatter.exs", @@ -144,8 +142,8 @@ pub fn check_for_advisories( list.map(packages, fn(pkg) { case is_vulnerable(pkg, advs) { - [] -> option.None - vulns -> option.Some(#(pkg, vulns)) + [] -> None + vulns -> Some(#(pkg, vulns)) } }) |> option.values diff --git a/src/go_over/advisories/comparisons.gleam b/src/go_over/advisories/comparisons.gleam index 414ebed..711d08b 100644 --- a/src/go_over/advisories/comparisons.gleam +++ b/src/go_over/advisories/comparisons.gleam @@ -1,17 +1,16 @@ import gleam/list -import gleam/option.{Some} import gleam/order import gleam/string import gleamsver.{type SemVer} import go_over/util/util.{hard_fail} pub fn parse(ver: String) -> SemVer { - let assert Some(parsed) = + let parsed = string.split(ver, " ") |> list.last |> hard_fail("could not parse " <> ver) - let assert Some(semver) = + let semver = gleamsver.parse(parsed) |> hard_fail("could not parse " <> parsed) semver @@ -35,7 +34,7 @@ pub fn get_comparator(ver: String) -> fn(SemVer) -> Bool { } fn do_get_comparator(ver: String) -> fn(SemVer) -> Bool { - let assert Some(op) = + let op = string.split(ver, " ") |> list.first |> hard_fail("could not parse " <> ver) diff --git a/src/go_over/config.gleam b/src/go_over/config.gleam index 6bc3f45..557ecc7 100644 --- a/src/go_over/config.gleam +++ b/src/go_over/config.gleam @@ -28,9 +28,9 @@ pub type Config { } pub fn read_config(path: String) -> Config { - let assert Some(res) = + let res = simplifile.read(path) |> hard_fail("could not read config file at " <> path) - let assert Some(gleam) = + let gleam = tom.parse(res) |> hard_fail("could not read config file at " <> path) let go_over = diff --git a/src/go_over/packages.gleam b/src/go_over/packages.gleam index 5f0b9b4..8b3bd03 100644 --- a/src/go_over/packages.gleam +++ b/src/go_over/packages.gleam @@ -14,14 +14,12 @@ pub type Package { } pub fn read_manifest(path: String) -> List(Package) { - let assert Some(res) = - simplifile.read(path) |> hard_fail("could not parse " <> path) - let assert Some(manifest) = - tom.parse(res) |> hard_fail("could not parse " <> path) - let assert Some(packages) = + let res = simplifile.read(path) |> hard_fail("could not parse " <> path) + let manifest = tom.parse(res) |> hard_fail("could not parse " <> path) + let packages = tom.get_array(manifest, ["packages"]) |> hard_fail("could not parse " <> path <> " value: packages") - let assert Some(requirements) = + let requirements = tom.get_table(manifest, ["requirements"]) |> hard_fail("could not parse " <> path <> " value: requirements") let required_packages = dict.keys(requirements) @@ -29,22 +27,17 @@ pub fn read_manifest(path: String) -> List(Package) { list.map(packages, fn(p) { case p { tom.InlineTable(t) -> { - let assert Some(name) = + let name = tom.get_string(t, ["name"]) |> hard_fail("could not parse parckage: " <> string.inspect(t)) - let assert Some(ver) = + let ver = tom.get_string(t, ["version"]) |> hard_fail("could not parse parckage: " <> string.inspect(t)) - let assert Some(semver) = + let semver = gleamsver.parse(ver) |> hard_fail("could not parse parckage version: " <> ver) - option.Some(Package( - name, - semver, - ver, - list.contains(required_packages, name), - )) + Some(Package(name, semver, ver, list.contains(required_packages, name))) } _ -> { diff --git a/src/go_over/retired.gleam b/src/go_over/retired.gleam index 9f79d53..68eed40 100644 --- a/src/go_over/retired.gleam +++ b/src/go_over/retired.gleam @@ -28,7 +28,7 @@ fn pull_retired(pkg: packages.Package) -> Nil { print.progress("Checking: " <> pkg.name <> " From hex.pm") // Prepare a HTTP request record - let assert Some(request) = + let request = request.to( "https://hex.pm/api/packages/" <> pkg.name @@ -38,7 +38,7 @@ fn pull_retired(pkg: packages.Package) -> Nil { |> hard_fail("request to hex.pm for package: " <> pkg.name <> " failed") // Send the HTTP request to the server - let assert Some(resp) = + let resp = request |> request.prepend_header("accept", "application/json") |> hackney.send @@ -51,14 +51,13 @@ fn pull_retired(pkg: packages.Package) -> Nil { <> " at path " <> pkg_path - let assert Some(_) = - simplifile.create_directory_all(pkg_path) - |> hard_fail(pkg_path_fail) - let assert Some(_) = - pkg - |> filename - |> simplifile.write(resp.body) - |> hard_fail(pkg_path_fail) + simplifile.create_directory_all(pkg_path) + |> hard_fail(pkg_path_fail) + + pkg + |> filename + |> simplifile.write(resp.body) + |> hard_fail(pkg_path_fail) Nil } @@ -80,12 +79,12 @@ pub fn check_retired( }) let cached_file_name = filename(pkg) - let assert Some(resp) = + let resp = cached_file_name |> simplifile.read() |> hard_fail("failed to read " <> cached_file_name) - let assert Some(release) = + let release = json.decode(resp, hexpm.decode_release) |> hard_fail("failed to parse " <> cached_file_name) @@ -95,7 +94,7 @@ pub fn check_retired( pub fn print_ret(ret: hexpm.ReleaseRetirement) -> String { let reason = hexpm.retirement_reason_to_string(ret.reason) case ret.message { - option.Some(msg) -> reason <> ": " <> msg + Some(msg) -> reason <> ": " <> msg _ -> reason } } diff --git a/src/go_over/util/cache.gleam b/src/go_over/util/cache.gleam index 2f6388a..9bbd18c 100644 --- a/src/go_over/util/cache.gleam +++ b/src/go_over/util/cache.gleam @@ -1,7 +1,6 @@ import birl import filepath import gleam/int -import gleam/option.{Some} import gleam/order import gleam/result import go_over/util/print @@ -48,7 +47,7 @@ pub fn pull_if_not_cached( birl.utc_now() |> birl.to_unix() |> int.to_string() - let assert Some(_) = + let _ = path |> cache_name() |> simplifile.write(now) diff --git a/src/go_over/util/constants.gleam b/src/go_over/util/constants.gleam index 71d839f..c4a30d2 100644 --- a/src/go_over/util/constants.gleam +++ b/src/go_over/util/constants.gleam @@ -1,5 +1,4 @@ import filepath -import gleam/option.{Some} import go_over/util/util.{hard_fail} import simplifile @@ -12,7 +11,7 @@ pub const advisories_repo = "mirego/elixir-security-advisories" pub const long_ass_dashes = "\n-----------------------------------------------\n" pub fn go_over_path() -> String { - let assert Some(curr) = + let curr = simplifile.current_directory() |> hard_fail("could not get current path") filepath.join(curr, ".go-over") diff --git a/src/go_over/util/util.gleam b/src/go_over/util/util.gleam index 9becbe2..0f18e21 100644 --- a/src/go_over/util/util.gleam +++ b/src/go_over/util/util.gleam @@ -1,4 +1,3 @@ -import gleam/option.{type Option, None, Some} import go_over/util/print import shellout @@ -24,13 +23,13 @@ pub fn throwaway(v: Bool, f: fn() -> Result(a, b)) -> Nil { } } -pub fn hard_fail(res: Result(a, b), msg: String) -> Option(a) { +pub fn hard_fail(res: Result(a, b), msg: String) -> a { case res { - Ok(val) -> Some(val) + Ok(val) -> val _ -> { print.warning("Error: " <> msg) shellout.exit(1) - None + panic as "unreachable" } } } From a0c03fa73c9eae96f96910e1ce4080d3bd75499b Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 4 Jun 2024 17:20:55 -0500 Subject: [PATCH 2/6] use nil_error --- src/go_over/util/cache.gleam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go_over/util/cache.gleam b/src/go_over/util/cache.gleam index 9bbd18c..b9566c1 100644 --- a/src/go_over/util/cache.gleam +++ b/src/go_over/util/cache.gleam @@ -15,7 +15,7 @@ fn file_cached(path: String, max_age_seconds: Int) -> Result(Bool, Nil) { path |> cache_name() |> simplifile.read() - |> result.replace_error(Nil) + |> result.nil_error() |> result.try(int.base_parse(_, 10)) |> result.map(fn(v) { let cutoff = birl.from_unix(v + max_age_seconds) From c0683dd125a4663e147b3130f8e8059e08b03a41 Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 4 Jun 2024 17:24:58 -0500 Subject: [PATCH 3/6] iifnil -> iff_nil --- src/go_over.gleam | 8 ++++---- src/go_over/advisories/advisories.gleam | 4 ++-- src/go_over/retired.gleam | 4 ++-- src/go_over/util/util.gleam | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/go_over.gleam b/src/go_over.gleam index 6f46324..b387ec6 100644 --- a/src/go_over.gleam +++ b/src/go_over.gleam @@ -9,7 +9,7 @@ import go_over/packages import go_over/retired import go_over/util/constants import go_over/util/print -import go_over/util/util.{iffnil, throwaway} +import go_over/util/util.{iff_nil, throwaway} import go_over/warning.{type Warning, Warning} import shellout import simplifile @@ -27,7 +27,7 @@ fn spin_up() -> Flags { fake: list.any(args, fn(arg) { arg == "--fake" }), ) - iffnil(flags.force && flags.skip, fn() { + iff_nil(flags.force && flags.skip, fn() { print.warning("Cannot specify both `--skip` & `--force`") shellout.exit(1) }) @@ -106,7 +106,7 @@ fn print_warnings(vulns: List(Warning), conf: Config) -> Nil { pub fn main() { let flags = spin_up() let conf = config.read_config("./gleam.toml") - iffnil(!conf.cache && flags.skip, fn() { + iff_nil(!conf.cache && flags.skip, fn() { print.warning("Cannot specify both `--skip` & `cache=false`") shellout.exit(1) }) @@ -122,7 +122,7 @@ pub fn main() { let vulnerable_packages = get_vulnerable_packages(pkgs, conf, flags) let retired_packages = get_retired_packges(pkgs, flags) - iffnil(flags.fake, fn() { + iff_nil(flags.fake, fn() { print_warnings( [ Warning( diff --git a/src/go_over/advisories/advisories.gleam b/src/go_over/advisories/advisories.gleam index 2743fca..06289f5 100644 --- a/src/go_over/advisories/advisories.gleam +++ b/src/go_over/advisories/advisories.gleam @@ -7,7 +7,7 @@ import go_over/packages.{type Package} import go_over/util/cache import go_over/util/constants.{go_over_path, six_hours} import go_over/util/print -import go_over/util/util.{hard_fail, iffnil} +import go_over/util/util.{hard_fail, iff_nil} import shellout import simplifile @@ -129,7 +129,7 @@ pub fn check_for_advisories( packages: List(packages.Package), pull: Bool, ) -> List(#(Package, List(Advisory))) { - iffnil(pull, fn() { + iff_nil(pull, fn() { cache.pull_if_not_cached( path(), six_hours, diff --git a/src/go_over/retired.gleam b/src/go_over/retired.gleam index 68eed40..f02c760 100644 --- a/src/go_over/retired.gleam +++ b/src/go_over/retired.gleam @@ -8,7 +8,7 @@ import go_over/packages import go_over/util/cache import go_over/util/constants import go_over/util/print -import go_over/util/util.{hard_fail, iffnil} +import go_over/util/util.{hard_fail, iff_nil} import simplifile fn path(pkg: packages.Package) -> String { @@ -65,7 +65,7 @@ pub fn check_retired( pkg: packages.Package, pull: Bool, ) -> Option(ReleaseRetirement) { - iffnil(pull, fn() { + iff_nil(pull, fn() { pkg |> path() |> cache.pull_if_not_cached( diff --git a/src/go_over/util/util.gleam b/src/go_over/util/util.gleam index 0f18e21..68d7d32 100644 --- a/src/go_over/util/util.gleam +++ b/src/go_over/util/util.gleam @@ -9,7 +9,7 @@ pub fn iff(v: Bool, f: fn() -> a, default: a) -> a { } } -pub fn iffnil(v: Bool, f: fn() -> Nil) -> Nil { +pub fn iff_nil(v: Bool, f: fn() -> Nil) -> Nil { iff(v, f, Nil) } From d28777bc06096f14591f9df3367e4ee5073a0c33 Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 4 Jun 2024 17:53:30 -0500 Subject: [PATCH 4/6] rename minimal internal function --- src/go_over.gleam | 2 +- src/go_over/warning.gleam | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/go_over.gleam b/src/go_over.gleam index b387ec6..d96b608 100644 --- a/src/go_over.gleam +++ b/src/go_over.gleam @@ -89,7 +89,7 @@ fn print_warnings(vulns: List(Warning), conf: Config) -> Nil { case conf.format { config.Minimal -> { vulns - |> list.map(warning.format_as_string_small) + |> list.map(warning.format_as_string_minimal) |> string.join("") } diff --git a/src/go_over/warning.gleam b/src/go_over/warning.gleam index 980c2ea..174bc20 100644 --- a/src/go_over/warning.gleam +++ b/src/go_over/warning.gleam @@ -83,7 +83,7 @@ pub fn format_as_string(w: Warning) -> String { |> color(w, _) } -pub fn format_as_string_small(w: Warning) -> String { +pub fn format_as_string_minimal(w: Warning) -> String { color( w, w.package <> "-" <> w.version <> ": " <> string.lowercase(w.severity), From cfca7a45e3473aaa0ff01c16204b7fcc4c4f0d5e Mon Sep 17 00:00:00 2001 From: bwireman Date: Wed, 5 Jun 2024 18:35:29 -0500 Subject: [PATCH 5/6] adds json format and merges flags and config --- README.md | 6 +- scripts/test.sh | 3 +- src/go_over.gleam | 93 ++++++++++++++++--------- src/go_over/advisories/advisories.gleam | 19 +++-- src/go_over/config.gleam | 28 +++++--- src/go_over/retired.gleam | 27 ++++--- src/go_over/util/cache.gleam | 7 +- src/go_over/warning.gleam | 18 ++++- 8 files changed, 128 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 6da1d8d..3c3cecf 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,10 @@ gleam run -m go_over ### 🏴 Flags -- `--skip`: will skip checking the cache and used the stored data no matter what +Override config values if set + - `--force`: will force pulling new data even if the cached data is still valid +- `--format=`: specify the output format of any warnings. `["minimal", "detailed", "json"]` ### ⚙️ Config @@ -42,7 +44,7 @@ Optional settings that can be added to your project's `gleam.toml` # disables caching if false # default: true cache = true -# sets output format ("minimal", "detailed") +# sets output format for warnings ["minimal", "detailed", "json"] # default: "minimal" format = "minimal" diff --git a/scripts/test.sh b/scripts/test.sh index b53e6c9..ee15c1d 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -6,7 +6,6 @@ gleam build gleam format gleam test rm -rf .go-over/ -gleam run -gleam run -- --skip --force +gleam run -- --force gleam run -- --fake gleam run \ No newline at end of file diff --git a/src/go_over.gleam b/src/go_over.gleam index d96b608..ad66754 100644 --- a/src/go_over.gleam +++ b/src/go_over.gleam @@ -1,10 +1,12 @@ import gleam/int import gleam/io +import gleam/json import gleam/list import gleam/option +import gleam/result import gleam/string import go_over/advisories/advisories -import go_over/config.{type Config} +import go_over/config.{type Config, Config} import go_over/packages import go_over/retired import go_over/util/constants @@ -15,32 +17,50 @@ import shellout import simplifile type Flags { - Flags(skip: Bool, force: Bool, fake: Bool) + Flags(force: Bool, fake: Bool, format: option.Option(config.Format)) } -fn spin_up() -> Flags { +fn merge_flags_and_config(flgs: Flags, cfg: Config) -> Config { + Config( + cache: cfg.cache, + force: flgs.force, + fake: flgs.fake, + format: option.unwrap(flgs.format, cfg.format), + ignore_packages: cfg.ignore_packages, + ignore_severity: cfg.ignore_severity, + ignore_ids: cfg.ignore_ids, + ) +} + +fn spin_up(cfg: Config) -> Config { let args = shellout.arguments() + + let format = + list.find(args, fn(arg) { string.starts_with(arg, "--format") }) + |> result.try(fn(arg) { string.split_once(arg, "=") }) + |> result.map(fn(arg) { + case arg { + #(_, val) -> val + } + }) + |> result.map(config.parse_config_format) + |> option.from_result + let flags = Flags( - skip: list.any(args, fn(arg) { arg == "--skip" }), force: list.any(args, fn(arg) { arg == "--force" }), fake: list.any(args, fn(arg) { arg == "--fake" }), + format: format, ) - iff_nil(flags.force && flags.skip, fn() { - print.warning("Cannot specify both `--skip` & `--force`") - shellout.exit(1) - }) - - flags + merge_flags_and_config(flags, cfg) } fn get_vulnerable_packages( pkgs: List(packages.Package), conf: Config, - flags: Flags, ) -> List(Warning) { - advisories.check_for_advisories(pkgs, !flags.skip) + advisories.check_for_advisories(pkgs, conf.force || !conf.cache) |> list.map(fn(p) { let #(pkg, adv) = p @@ -61,11 +81,11 @@ fn get_vulnerable_packages( fn get_retired_packges( pkgs: List(packages.Package), - flags: Flags, + conf: Config, ) -> List(Warning) { pkgs |> list.map(fn(pkg) { - case retired.check_retired(pkg, !flags.skip) { + case retired.check_retired(pkg, conf.force || !conf.cache) { option.Some(ret) -> option.Some(#(pkg, ret)) option.None -> option.None } @@ -77,52 +97,59 @@ fn get_retired_packges( }) } -fn print_warnings(vulns: List(Warning), conf: Config) -> Nil { +fn print_warnings_count(vulns: List(Warning)) -> Nil { { "⛔ " <> int.to_string(list.length(vulns)) <> " WARNING(s) FOUND!" <> constants.long_ass_dashes } - |> io.print + |> io.print_error +} +fn print_warnings(vulns: List(Warning), conf: Config) -> Nil { case conf.format { config.Minimal -> { + print_warnings_count(vulns) + vulns |> 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 } _ -> { + print_warnings_count(vulns) + vulns |> list.map(warning.format_as_string) |> string.join(constants.long_ass_dashes) + |> io.print_error } } - |> io.print shellout.exit(1) } pub fn main() { - let flags = spin_up() - let conf = config.read_config("./gleam.toml") - iff_nil(!conf.cache && flags.skip, fn() { - print.warning("Cannot specify both `--skip` & `cache=false`") - shellout.exit(1) - }) - - throwaway(flags.force || !conf.cache, fn() { - simplifile.delete(constants.go_over_path()) - }) + let conf = spin_up(config.read_config("./gleam.toml")) + throwaway(!conf.cache, fn() { simplifile.delete(constants.go_over_path()) }) let pkgs = packages.read_manifest("./manifest.toml") |> config.filter_packages(conf, _) - let vulnerable_packages = get_vulnerable_packages(pkgs, conf, flags) - let retired_packages = get_retired_packges(pkgs, flags) + let vulnerable_packages = get_vulnerable_packages(pkgs, conf) + let retired_packages = get_retired_packges(pkgs, conf) - iff_nil(flags.fake, fn() { + iff_nil(conf.fake, fn() { print_warnings( [ Warning( @@ -138,7 +165,7 @@ pub fn main() { option.None, "another_fake", "1.2.3", - "Vulnerabe", + "Vulnerable", warning.Vulnerable, "High", warning.Direct, @@ -147,7 +174,7 @@ pub fn main() { option.None, "and_another", "4.5.6", - "Vulnerabe", + "Vulnerable", warning.Vulnerable, "Moderate", warning.Direct, @@ -156,7 +183,7 @@ pub fn main() { option.None, "one_more", "7.8.9", - "Vulnerabe", + "Vulnerable", warning.Vulnerable, "LOW", warning.Indirect, diff --git a/src/go_over/advisories/advisories.gleam b/src/go_over/advisories/advisories.gleam index 06289f5..6b00bf9 100644 --- a/src/go_over/advisories/advisories.gleam +++ b/src/go_over/advisories/advisories.gleam @@ -7,7 +7,7 @@ import go_over/packages.{type Package} import go_over/util/cache import go_over/util/constants.{go_over_path, six_hours} import go_over/util/print -import go_over/util/util.{hard_fail, iff_nil} +import go_over/util/util.{hard_fail} import shellout import simplifile @@ -127,16 +127,15 @@ fn delete_and_clone() -> Nil { pub fn check_for_advisories( packages: List(packages.Package), - pull: Bool, + force_pull: Bool, ) -> List(#(Package, List(Advisory))) { - iff_nil(pull, fn() { - cache.pull_if_not_cached( - path(), - six_hours, - delete_and_clone, - constants.advisories_repo, - ) - }) + cache.pull_if_not_cached( + path(), + six_hours, + force_pull, + delete_and_clone, + constants.advisories_repo, + ) let advs = read_all_adv() diff --git a/src/go_over/config.gleam b/src/go_over/config.gleam index 557ecc7..5281cb6 100644 --- a/src/go_over/config.gleam +++ b/src/go_over/config.gleam @@ -15,11 +15,14 @@ import tom.{type Toml} pub type Format { Minimal Detailed + JSON } pub type Config { Config( cache: Bool, + force: Bool, + fake: Bool, format: Format, ignore_packages: List(String), ignore_severity: List(String), @@ -58,13 +61,14 @@ pub fn read_config(path: String) -> Config { Config( cache: cache, - format: case format { - "minimal" -> Minimal - _ -> Detailed - }, - ignore_packages: list.map(packages, as_string) |> option.values, - ignore_severity: list.map(severity, as_string) |> option.values, - ignore_ids: list.map(ids, as_string) |> option.values, + //read from flags only + force: False, + //read from flags only + fake: False, + format: parse_config_format(format), + ignore_packages: list.map(packages, toml_as_string) |> option.values, + ignore_severity: list.map(severity, toml_as_string) |> option.values, + ignore_ids: list.map(ids, toml_as_string) |> option.values, ) } @@ -82,7 +86,15 @@ pub fn filter_severity(conf: Config, warnings: List(Warning)) -> List(Warning) { }) } -fn as_string(toml: Toml) -> Option(String) { +pub fn parse_config_format(val: String) -> Format { + case val { + "json" -> JSON + "detailed" -> Detailed + _ -> Minimal + } +} + +fn toml_as_string(toml: Toml) -> Option(String) { case toml { tom.String(s) -> Some(s) _ -> { diff --git a/src/go_over/retired.gleam b/src/go_over/retired.gleam index f02c760..cc9f776 100644 --- a/src/go_over/retired.gleam +++ b/src/go_over/retired.gleam @@ -8,7 +8,7 @@ import go_over/packages import go_over/util/cache import go_over/util/constants import go_over/util/print -import go_over/util/util.{hard_fail, iff_nil} +import go_over/util/util.{hard_fail} import simplifile fn path(pkg: packages.Package) -> String { @@ -63,20 +63,19 @@ fn pull_retired(pkg: packages.Package) -> Nil { pub fn check_retired( pkg: packages.Package, - pull: Bool, + force_pull: Bool, ) -> Option(ReleaseRetirement) { - iff_nil(pull, fn() { - pkg - |> path() - |> cache.pull_if_not_cached( - constants.hour, - fn() { - let _ = simplifile.delete(path(pkg)) - pull_retired(pkg) - }, - pkg.name <> ":" <> pkg.version_raw, - ) - }) + pkg + |> path() + |> cache.pull_if_not_cached( + constants.hour, + force_pull, + fn() { + let _ = simplifile.delete(path(pkg)) + pull_retired(pkg) + }, + pkg.name <> ":" <> pkg.version_raw, + ) let cached_file_name = filename(pkg) let resp = diff --git a/src/go_over/util/cache.gleam b/src/go_over/util/cache.gleam index b9566c1..688fafa 100644 --- a/src/go_over/util/cache.gleam +++ b/src/go_over/util/cache.gleam @@ -30,17 +30,18 @@ fn file_cached(path: String, max_age_seconds: Int) -> Result(Bool, Nil) { pub fn pull_if_not_cached( path: String, max_age: Int, + force_pull: Bool, pullfn: fn() -> Nil, cache_message: String, ) -> Nil { - case file_cached(path, max_age) { - Ok(True) -> { + case force_pull, file_cached(path, max_age) { + False, Ok(True) -> { print.progress("Cached: " <> cache_message) Nil } - _ -> { + _, _ -> { pullfn() let now = diff --git a/src/go_over/warning.gleam b/src/go_over/warning.gleam index 174bc20..346f70f 100644 --- a/src/go_over/warning.gleam +++ b/src/go_over/warning.gleam @@ -1,4 +1,5 @@ import gleam/hexpm.{type ReleaseRetirement} +import gleam/json.{type Json, object, string} import gleam/list import gleam/option.{type Option, None, Some} import gleam/string @@ -71,7 +72,7 @@ pub fn retired_to_warning(pkg: Package, ret: ReleaseRetirement) -> Warning { pub fn format_as_string(w: Warning) -> String { [ - "ID: " <> option.unwrap(w.advisory_id, "N/A"), + "ID: " <> option.unwrap(w.advisory_id, "null"), "Package: " <> w.package, "Version: " <> w.version, "WarningReason: " <> warning_reason_code_as_string(w.warning_reason_code), @@ -90,6 +91,21 @@ pub fn format_as_string_minimal(w: Warning) -> String { ) } +pub fn format_as_json(w: Warning) -> Json { + object([ + #("id", json.nullable(w.advisory_id, string)), + #("package", string(w.package)), + #("version", string(w.version)), + #( + "warning_reason", + string(warning_reason_code_as_string(w.warning_reason_code)), + ), + #("dependency_type", string(dep_code_as_string(w.dep))), + #("severity", string(string.lowercase(w.severity))), + #("reason", string(w.reason)), + ]) +} + fn color(w: Warning, str: String) { case string.lowercase(w.severity) { "critical" -> print.format_critical(str) From b2632c5b5edc3922a67a4028f993573c18027d03 Mon Sep 17 00:00:00 2001 From: bwireman Date: Wed, 5 Jun 2024 18:48:22 -0500 Subject: [PATCH 6/6] as 0.5.0 --- gleam.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gleam.toml b/gleam.toml index de97c89..d38b5e8 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,5 +1,5 @@ name = "go_over" -version = "0.4.0" +version = "0.5.0" licences = ["MIT"] repository = { type = "github", user = "bwireman", repo = "go-over" } description = "A tool to audit Erlang & Elixir dependencies, to make sure your gleam projects really sparkle! ✨"