Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.5.0 #5

Merged
merged 6 commits into from
Jun 5, 2024
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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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=<format>`: specify the output format of any warnings. `["minimal", "detailed", "json"]`

### ⚙️ Config

Expand All @@ -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"

Expand Down
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -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! ✨"
Expand Down
3 changes: 1 addition & 2 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
97 changes: 62 additions & 35 deletions src/go_over.gleam
Original file line number Diff line number Diff line change
@@ -1,46 +1,66 @@
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
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

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,
)

iffnil(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

Expand All @@ -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
}
Expand All @@ -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_small)
|> 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")
iffnil(!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)

iffnil(flags.fake, fn() {
iff_nil(conf.fake, fn() {
print_warnings(
[
Warning(
Expand All @@ -138,7 +165,7 @@ pub fn main() {
option.None,
"another_fake",
"1.2.3",
"Vulnerabe",
"Vulnerable",
warning.Vulnerable,
"High",
warning.Direct,
Expand All @@ -147,7 +174,7 @@ pub fn main() {
option.None,
"and_another",
"4.5.6",
"Vulnerabe",
"Vulnerable",
warning.Vulnerable,
"Moderate",
warning.Direct,
Expand All @@ -156,7 +183,7 @@ pub fn main() {
option.None,
"one_more",
"7.8.9",
"Vulnerabe",
"Vulnerable",
warning.Vulnerable,
"LOW",
warning.Indirect,
Expand Down
61 changes: 29 additions & 32 deletions src/go_over/advisories/advisories.gleam
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
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}
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}
import shellout
import simplifile

Expand Down Expand Up @@ -52,15 +52,15 @@ 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,
)
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,
Expand Down Expand Up @@ -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",
Expand All @@ -129,23 +127,22 @@ fn delete_and_clone() -> Nil {

pub fn check_for_advisories(
packages: List(packages.Package),
pull: Bool,
force_pull: Bool,
) -> List(#(Package, List(Advisory))) {
iffnil(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()

list.map(packages, fn(pkg) {
case is_vulnerable(pkg, advs) {
[] -> option.None
vulns -> option.Some(#(pkg, vulns))
[] -> None
vulns -> Some(#(pkg, vulns))
}
})
|> option.values
Expand Down
7 changes: 3 additions & 4 deletions src/go_over/advisories/comparisons.gleam
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand Down
Loading