|
| 1 | +import logging |
| 2 | +from typing import Annotated, Optional |
| 3 | + |
| 4 | +import typer |
| 5 | + |
| 6 | +from cycode import __version__ |
| 7 | +from cycode.cli.apps import ai_remediation, auth, configure, ignore, report, scan, status |
| 8 | +from cycode.cli.cli_types import OutputTypeOption |
| 9 | +from cycode.cli.consts import CLI_CONTEXT_SETTINGS |
| 10 | +from cycode.cli.user_settings.configuration_manager import ConfigurationManager |
| 11 | +from cycode.cli.utils.progress_bar import SCAN_PROGRESS_BAR_SECTIONS, get_progress_bar |
| 12 | +from cycode.cli.utils.sentry import add_breadcrumb, init_sentry |
| 13 | +from cycode.cli.utils.version_checker import version_checker |
| 14 | +from cycode.cyclient.config import set_logging_level |
| 15 | +from cycode.cyclient.cycode_client_base import CycodeClientBase |
| 16 | +from cycode.cyclient.models import UserAgentOptionScheme |
| 17 | + |
| 18 | +app = typer.Typer( |
| 19 | + pretty_exceptions_show_locals=False, |
| 20 | + pretty_exceptions_short=True, |
| 21 | + context_settings=CLI_CONTEXT_SETTINGS, |
| 22 | + rich_markup_mode='rich', |
| 23 | +) |
| 24 | + |
| 25 | +app.add_typer(ai_remediation.app) |
| 26 | +app.add_typer(auth.app) |
| 27 | +app.add_typer(configure.app) |
| 28 | +app.add_typer(ignore.app) |
| 29 | +app.add_typer(report.app) |
| 30 | +app.add_typer(scan.app) |
| 31 | +app.add_typer(status.app) |
| 32 | + |
| 33 | + |
| 34 | +def check_latest_version_on_close(ctx: typer.Context) -> None: |
| 35 | + output = ctx.obj.get('output') |
| 36 | + # don't print anything if the output is JSON |
| 37 | + if output == OutputTypeOption.JSON: |
| 38 | + return |
| 39 | + |
| 40 | + # we always want to check the latest version for "version" and "status" commands |
| 41 | + should_use_cache = ctx.invoked_subcommand not in {'version', 'status'} |
| 42 | + version_checker.check_and_notify_update( |
| 43 | + current_version=__version__, use_color=ctx.color, use_cache=should_use_cache |
| 44 | + ) |
| 45 | + |
| 46 | + |
| 47 | +@app.callback() |
| 48 | +def app_callback( |
| 49 | + ctx: typer.Context, |
| 50 | + verbose: Annotated[bool, typer.Option('--verbose', '-v', help='Show detailed logs.')] = False, |
| 51 | + no_progress_meter: Annotated[ |
| 52 | + bool, typer.Option('--no-progress-meter', help='Do not show the progress meter.') |
| 53 | + ] = False, |
| 54 | + no_update_notifier: Annotated[ |
| 55 | + bool, typer.Option('--no-update-notifier', help='Do not check CLI for updates.') |
| 56 | + ] = False, |
| 57 | + output: Annotated[ |
| 58 | + OutputTypeOption, typer.Option('--output', '-o', case_sensitive=False, help='Specify the output type.') |
| 59 | + ] = OutputTypeOption.TEXT, |
| 60 | + user_agent: Annotated[ |
| 61 | + Optional[str], |
| 62 | + typer.Option(hidden=True, help='Characteristic JSON object that lets servers identify the application.'), |
| 63 | + ] = None, |
| 64 | +) -> None: |
| 65 | + init_sentry() |
| 66 | + add_breadcrumb('cycode') |
| 67 | + |
| 68 | + ctx.ensure_object(dict) |
| 69 | + configuration_manager = ConfigurationManager() |
| 70 | + |
| 71 | + verbose = verbose or configuration_manager.get_verbose_flag() |
| 72 | + ctx.obj['verbose'] = verbose |
| 73 | + if verbose: |
| 74 | + set_logging_level(logging.DEBUG) |
| 75 | + |
| 76 | + ctx.obj['output'] = output |
| 77 | + if output == OutputTypeOption.JSON: |
| 78 | + no_progress_meter = True |
| 79 | + |
| 80 | + ctx.obj['progress_bar'] = get_progress_bar(hidden=no_progress_meter, sections=SCAN_PROGRESS_BAR_SECTIONS) |
| 81 | + |
| 82 | + if user_agent: |
| 83 | + user_agent_option = UserAgentOptionScheme().loads(user_agent) |
| 84 | + CycodeClientBase.enrich_user_agent(user_agent_option.user_agent_suffix) |
| 85 | + |
| 86 | + if not no_update_notifier: |
| 87 | + ctx.call_on_close(lambda: check_latest_version_on_close(ctx)) |
0 commit comments