Source code for hammurabi.main

from enum import Enum
import logging
import os
from pathlib import Path
import sys

import github3
import typer

from hammurabi import Pillar, __version__
from hammurabi.config import (
    DEFAULT_ALLOW_PUSH,
    DEFAULT_DRY_RUN,
    DEFAULT_GENERATE_REPORT,
    DEFAULT_GITHUB_TOKEN,
    DEFAULT_LOG_LEVEL,
    DEFAULT_PROJECT_CONFIG,
    DEFAULT_REPOSITORY,
    config,
)

NON_ACTIONABLE_SUBCOMMANDS = ["version"]


[docs]class LoggingChoices(str, Enum): """ Logging choices for CLI settings. """ DEBUG = "DEBUG" INFO = "INFO" WARNING = "WARNING" ERROR = "ERROR"
app = typer.Typer()
[docs]def error_message(message: str, should_exit: bool = True, code: int = 1): """ Print error message and exit the CLI application """ print_message(message, typer.colors.RED, True, should_exit, code)
[docs]def success_message(message: str): """ Print error message and exit the CLI application """ print_message(message, typer.colors.GREEN, True, False, 0)
[docs]@app.callback() def main( ctx: typer.Context, cfg: Path = typer.Option( DEFAULT_PROJECT_CONFIG, "--config", "-c", help="Set the configuration file." ), repository: str = typer.Option( DEFAULT_REPOSITORY, help="Set the remote repository. Required format: owner/repository.", ), token: str = typer.Option(DEFAULT_GITHUB_TOKEN, help="Set github access token."), log_level: LoggingChoices = typer.Option( DEFAULT_LOG_LEVEL, help="Set logging level." ), ): """ Hammurabi is an extensible CLI tool responsible for enforcing user-defined rules on a git repository. Find more information at: https://hammurabi.readthedocs.io/latest/ """ if ctx.invoked_subcommand in NON_ACTIONABLE_SUBCOMMANDS: return os.environ.setdefault("HAMMURABI_SETTINGS_PATH", str(cfg.expanduser())) try: # Reload the configuration config.load() success_message("Configuration loaded") except Exception as exc: # pylint: disable=broad-except error_message(f"Failed to load configuration: {str(exc)}") return if token != DEFAULT_GITHUB_TOKEN: config.github = github3.login(token=token) if repository != DEFAULT_REPOSITORY: config.settings.repository = repository if log_level != DEFAULT_LOG_LEVEL: logging.root.setLevel(log_level.value) ctx.ensure_object(dict) ctx.obj["config"] = config
[docs]@app.command(short_help="Print hammurabi version.") def version(): """ Print hammurabi version. """ typer.echo(__version__)
[docs]@app.command(short_help="Execute registered laws.") def enforce( ctx: typer.Context, dry_run: bool = typer.Option(DEFAULT_DRY_RUN, help="Execute laws in dry run mode."), allow_push: bool = typer.Option(DEFAULT_ALLOW_PUSH, help="Push changes to remote."), report: bool = typer.Option( DEFAULT_GENERATE_REPORT, help="Generate execution report." ), ): """ The `enforce` command executes the laws registered on the pillar. But the command has other responsibilities too. It will make sure the execution report is generated and controls if the changes are pushed to remote or not. """ if allow_push != DEFAULT_ALLOW_PUSH: ctx.obj["config"].settings.allow_push = allow_push if dry_run != DEFAULT_DRY_RUN: ctx.obj["config"].settings.dry_run = dry_run pillar: Pillar = ctx.obj["config"].settings.pillar pillar.enforce() success_message("Finished successfully") if report: pillar.reporter.report() success_message("Report generated")
if __name__ == "__main__": app()