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

New pipenv check with minimal output #5480

Merged
merged 3 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion pipenv/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def run(state, command, args):
)
@option(
"--output",
type=Choice(["default", "json", "full-report", "bare", "screen", "text"]),
type=Choice(["default", "json", "full-report", "bare", "screen", "text", "minimal"]),
default="default",
help="Translates to --json, --full-report or --bare from PyUp Safety check",
)
Expand Down
90 changes: 70 additions & 20 deletions pipenv/core.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import io
import json as simplejson
import logging
import os
Expand Down Expand Up @@ -2922,7 +2923,8 @@ def do_check(
if not quiet and not project.s.is_quiet():
click.echo(
click.style(
decode_for_output("Checking installed package safety..."), bold=True
decode_for_output("Checking installed packages for vulnerabilities..."),
yeisonvargasf marked this conversation as resolved.
Show resolved Hide resolved
bold=True,
)
)
if ignore:
Expand All @@ -2947,6 +2949,8 @@ def do_check(

if output == "full-report":
options.append("--full-report")
elif output == "minimal":
options.append("--json")
elif output not in ["screen", "default"]:
options.append(f"--output={output}")

Expand All @@ -2959,7 +2963,7 @@ def do_check(
if safety_project:
options.append(f"--project={safety_project}")

cmd = _cmd + [safety_path, "--debug", "check"] + options
cmd = _cmd + [safety_path, "check"] + options

if db:
if not quiet and not project.s.is_quiet():
Expand All @@ -2968,35 +2972,81 @@ def do_check(
elif key or project.s.PIPENV_PYUP_API_KEY:
cmd = cmd + [f"--key={key or project.s.PIPENV_PYUP_API_KEY}"]
else:
# TODO: Define the source
PIPENV_SAFETY_DB = (
"https://raw.githubusercontent.com/pyupio/safety-db/master/data/"
"https://d2qjmgddvqvu75.cloudfront.net/aws/safety/pipenv/1.0.0/"
)
os.environ["SAFETY_ANNOUNCEMENTS_URL"] = f"{PIPENV_SAFETY_DB}announcements.json"
cmd.append(f"--db={PIPENV_SAFETY_DB}")

if ignored:
for cve in ignored:
cmd += cve
click.secho("Running the command", fg="red")

safety_env = os.environ.copy()
safety_env["SAFETY_CUSTOM_INTEGRATION"] = "True"
safety_env["SAFETY_ANNOUNCEMENTS_URL"] = "https://foo-bar" # TODO: Define the source
safety_env["SAFETY_SOURCE"] = "pipenv"
os.environ["SAFETY_CUSTOM_INTEGRATION"] = "True"
os.environ["SAFETY_SOURCE"] = "pipenv"
os.environ["SAFETY_PURE_YAML"] = "True"

c = run_command(
cmd, catch_exceptions=False, is_verbose=project.s.is_verbose(), env=safety_env
)
from pipenv.patched.safety.cli import cli

if c.stdout:
click.echo(c.stdout)
elif c.stderr:
raise exceptions.PipenvCmdError(
cmd_list_to_shell(c.args), c.stdout, c.stderr, c.returncode
)
sys.argv = cmd[1:]

# Let to Safety handles the exit code behavior
sys.exit(c.returncode)
if output == "minimal":
from contextlib import redirect_stderr, redirect_stdout

code = 0

with redirect_stdout(io.StringIO()) as out, redirect_stderr(io.StringIO()) as err:
try:
cli(prog_name="pipenv")
except SystemExit as exit_signal:
code = exit_signal.code

report = out.getvalue()
error = err.getvalue()

try:
json_report = simplejson.loads(report)
except Exception:
raise exceptions.PipenvCmdError(
cmd_list_to_shell(cmd), report, error, exit_code=code
)
meta = json_report.get("report_meta")
vulnerabilities_found = meta.get("vulnerabilities_found")

fg = "green"
message = "All good!"
db_type = "commercial" if meta.get("api_key", False) else "free"

if vulnerabilities_found >= 0:
fg = "red"
message = (
f"Scan was complete using Safety’s {db_type} vulnerability database."
)

click.echo()
click.secho(f"{vulnerabilities_found} vulnerabilities found.", fg=fg)
click.echo()

vulnerabilities = json_report.get("vulnerabilities", [])

for vuln in vulnerabilities:
click.echo(
"{}: {} {} open to vulnerability {} ({}). More info: {}".format(
click.style(vuln["vulnerability_id"], bold=True, fg="red"),
click.style(vuln["package_name"], fg="green"),
click.style(vuln["analyzed_version"], fg="yellow", bold=True),
click.style(vuln["vulnerability_id"], bold=True),
click.style(vuln["vulnerable_spec"], fg="yellow", bold=False),
click.style(vuln["more_info_url"], bold=True),
)
)
click.echo(f"{vuln['advisory']}")
click.echo()

click.echo(click.style(message, fg="white", bold=True))
sys.exit(code)

cli(prog_name="pipenv")


def do_graph(project, bare=False, json=False, json_tree=False, reverse=False):
Expand Down