diff --git a/trestlebot/cli/base.py b/trestlebot/cli/base.py deleted file mode 100644 index 051fe290..00000000 --- a/trestlebot/cli/base.py +++ /dev/null @@ -1,90 +0,0 @@ -import argparse -import logging -from typing import List - -from trestlebot.bot import TrestleBot -from trestlebot.cli.options.common import handle_exceptions -from trestlebot.tasks.assemble_task import AssembleTask -from trestlebot.tasks.authored import types -from trestlebot.tasks.authored.base_authored import AuthoredObjectBase -from trestlebot.tasks.base_task import ModelFilter, TaskBase -from trestlebot.tasks.regenerate_task import RegenerateTask - - -logger = logging.getLogger(__name__) - - -def comma_sep_to_list(string: str) -> List[str]: - """Convert comma-sep string to list of strings and strip.""" - string = string.strip() if string else "" - return list(map(str.strip, string.split(","))) if string else [] - - -def run_base(args: argparse.Namespace, pre_tasks: List[TaskBase]) -> None: - """Reusable logic for all commands.""" - # from trestlebot.reporter import BotResults, ResultsReporter - # git_provider: Optional[GitProvider] = self.set_git_provider(args) - # results_reporter: ResultsReporter = self.set_reporter() - - # Configure and run the bot - bot = TrestleBot( - working_dir=args.working_dir, - branch=args.branch, - commit_name=args.committer_name, - commit_email=args.committer_email, - author_name=args.author_name, - author_email=args.author_email, - # target_branch=args.target_branch, - ) - # results: BotResults = bot.run( - bot.run( - pre_tasks=pre_tasks, - patterns=comma_sep_to_list(args.patterns), - commit_message=args.commit_message, - # git_provider=git_provider, - # pull_request_title=args.pull_request_title, - dry_run=args.dry_run, - ) - - # # Report the results - # results_reporter.report_results(results) - - -@handle_exceptions -def run(oscal_model: str, args: argparse.Namespace, ssp_index_path: str = "") -> None: - """Run the autosync for oscal model.""" - - pre_tasks: List[TaskBase] = [] - # Allow any model to be skipped from the args, by default include all - model_filter: ModelFilter = ModelFilter( - skip_patterns=comma_sep_to_list(args.skip_items), - include_patterns=["*"], - ) - authored_object: AuthoredObjectBase = types.get_authored_object( - oscal_model, args.working_dir, ssp_index_path - ) - - # Assuming an edit has occurred assemble would be run before regenerate. - # Adding this to the list first - if not args.skip_assemble: - assemble_task: AssembleTask = AssembleTask( - authored_object=authored_object, - markdown_dir=args.markdown_path, - version=args.version, - model_filter=model_filter, - ) - pre_tasks.append(assemble_task) - else: - logger.info("Assemble task skipped.") - - if not args.skip_regenerate: - regenerate_task: RegenerateTask = RegenerateTask( - authored_object=authored_object, - markdown_dir=args.markdown_path, - model_filter=model_filter, - ) - pre_tasks.append(regenerate_task) - else: - logger.info("Regeneration task skipped.") - - run_base(args, pre_tasks) diff --git a/trestlebot/cli/commands/autosync.py b/trestlebot/cli/commands/autosync.py index cb7dadc6..e9576c7f 100644 --- a/trestlebot/cli/commands/autosync.py +++ b/trestlebot/cli/commands/autosync.py @@ -1,11 +1,63 @@ """ Autosync command""" -import argparse +import logging +from typing import Any, Dict, List import click -from trestlebot.cli.base import comma_sep_to_list, run -from trestlebot.cli.options.common import git_options +from trestlebot.cli.options.common import git_options, handle_exceptions +from trestlebot.cli.run import comma_sep_to_list +from trestlebot.cli.run import run as bot_run +from trestlebot.tasks.assemble_task import AssembleTask +from trestlebot.tasks.authored import types +from trestlebot.tasks.authored.base_authored import AuthoredObjectBase +from trestlebot.tasks.base_task import ModelFilter, TaskBase +from trestlebot.tasks.regenerate_task import RegenerateTask + + +logger = logging.getLogger(__name__) + + +@handle_exceptions +def run(oscal_model: str, ctx_obj: Dict[str, Any]) -> None: + """Run the autosync for oscal model.""" + + pre_tasks: List[TaskBase] = [] + # Allow any model to be skipped from the args, by default include all + model_filter: ModelFilter = ModelFilter( + skip_patterns=comma_sep_to_list(ctx_obj.get("skip_items", "")), + include_patterns=["*"], + ) + authored_object: AuthoredObjectBase = types.get_authored_object( + oscal_model, + ctx_obj["working_dir"], + ctx_obj.get("ssp_index_path", ""), + ) + + # Assuming an edit has occurred assemble would be run before regenerate. + # Adding this to the list first + if not ctx_obj.get("skip_assemble"): + assemble_task: AssembleTask = AssembleTask( + authored_object=authored_object, + markdown_dir=ctx_obj["markdown_path"], + version=ctx_obj.get("version", ""), + model_filter=model_filter, + ) + pre_tasks.append(assemble_task) + else: + logger.info("Assemble task skipped.") + + if not ctx_obj.get("skip_regenerate"): + regenerate_task: RegenerateTask = RegenerateTask( + authored_object=authored_object, + markdown_dir=ctx_obj["markdown_path"], + model_filter=model_filter, + ) + pre_tasks.append(regenerate_task) + else: + logger.info("Regeneration task skipped.") + + bot_run(pre_tasks, ctx_obj) @click.group(name="autosync", help="Autosync operations") @@ -13,21 +65,19 @@ "--working-dir", help="Working directory wit git repository", type=click.Path(exists=True), -) -@click.option( - "--dry-run", - help="Run tasks, but do not push to the repository", - is_flag=True, -) + prompt="Enter path to git repo (workspace directory)", + default=".", +) # TODO: use path in config @click.option( "--markdown-path", help="Path to Trestle markdown files", - type=click.Path(exists=True), # Should it exist? + type=click.Path(exists=True), + prompt="Enter path to to Trestle markdown files", ) @click.option( "--skip-items", help="Comma-separated list of glob patterns to skip when running tasks", - type=str, # What's the type? + type=str, ) @click.option( "--skip-assemble", @@ -48,6 +98,11 @@ help="Version of the OSCAL model to set during assembly into JSON", type=str, ) +@click.option( + "--dry-run", + help="Run tasks, but do not push to the repository", + is_flag=True, +) @git_options @click.pass_context def autosync_cmd( @@ -69,43 +124,7 @@ def autosync_cmd( ) -> None: """Command to autosync catalog, profile, compdef and ssp.""" - need_to_prompt = any( - ( - not working_dir, - not markdown_path, - not branch, - not committer_email, - not committer_name, - ) - ) - if need_to_prompt: - click.echo("\n* Welcome to the Trestle-bot CLI *\n") - click.echo("Please provide the following values to start autosync operations.") - if not working_dir: - working_dir = click.prompt( - "Enter path to working directory wit git repository", - default=".", - type=click.Path(exists=True), - ) - if not markdown_path: - markdown_path = click.prompt( - "Enter path to to Trestle markdown files", - type=click.Path(exists=True), - ) - if not branch: - branch = click.prompt( - "Enter branch name to push changes to", - ) - if not committer_email: - committer_email = click.prompt( - "Enter email for committer", - ) - if not committer_name: - committer_name = click.prompt( - "Enter name of committer", - ) - - ctx.trestle_args = argparse.Namespace( + ctx.obj = dict( working_dir=working_dir, markdown_path=markdown_path, skip_items=skip_items, @@ -119,37 +138,44 @@ def autosync_cmd( committer_email=committer_email, author_name=author_name, author_email=author_email, - # target_branch=target_branch, - # pull_request_title=pull_request_title, dry_run=dry_run, ) @autosync_cmd.command("ssp") +@click.option( + "--ssp-index-path", + help="Path to ssp index file", + type=click.File("r"), +) @click.pass_context -@click.option("--ssp-index-path", help="Path to ssp index file", type=click.File("r")) def autosync_ssp_cmd(ctx: click.Context, ssp_index_path: str) -> None: if not ssp_index_path: ssp_index_path = click.prompt( "Enter path to ssp index file", type=click.Path(exists=True), ) - run("ssp", ctx.parent.trestle_args, ssp_index_path) + ctx.obj.update( + { + "ssp_index_path": ssp_index_path, + } + ) + run("ssp", ctx.obj) @autosync_cmd.command("compdef") @click.pass_context def autosync_compdef_cmd(ctx: click.Context) -> None: - run("compdef", ctx.parent.trestle_args) + run("compdef", ctx.obj) @autosync_cmd.command("catalog") @click.pass_context def autosync_catalog_cmd(ctx: click.Context) -> None: - run("catalog", ctx.parent.trestle_args) + run("catalog", ctx.obj) @autosync_cmd.command("profile") @click.pass_context def autosync_profile_cmd(ctx: click.Context) -> None: - run("profile", ctx.parent.trestle_args) + run("profile", ctx.obj) diff --git a/trestlebot/cli/options/common.py b/trestlebot/cli/options/common.py index 5a1167e2..b77e3a6f 100644 --- a/trestlebot/cli/options/common.py +++ b/trestlebot/cli/options/common.py @@ -111,16 +111,19 @@ def git_options(f: F) -> Any: "--branch", help="Branch name to push changes to", type=str, + prompt="Enter branch name to push changes to", ) @click.option( "--committer-name", help="Name of committer", type=str, + prompt="Enter name for committer", ) @click.option( "--committer-email", help="Email for committer", type=str, + prompt="Enter email for committer", ) @click.option( "--file-patterns", diff --git a/trestlebot/cli/run.py b/trestlebot/cli/run.py new file mode 100644 index 00000000..561e2dfe --- /dev/null +++ b/trestlebot/cli/run.py @@ -0,0 +1,29 @@ +from typing import Any, Dict, List + +from trestlebot.bot import TrestleBot +from trestlebot.tasks.base_task import TaskBase + + +def comma_sep_to_list(string: str) -> List[str]: + """Convert comma-sep string to list of strings and strip.""" + string = string.strip() if string else "" + return list(map(str.strip, string.split(","))) if string else [] + + +def run(pre_tasks: List[TaskBase], kwargs: Dict[Any, Any]) -> None: + """Reusable logic for all commands.""" + # Configure and run the bot + bot = TrestleBot( + working_dir=kwargs["working_dir"], + branch=kwargs["branch"], + commit_name=kwargs["committer_name"], + commit_email=kwargs["committer_email"], + author_name=kwargs.get("author_name", ""), + author_email=kwargs.get("author_email", ""), + ) + bot.run( + pre_tasks=pre_tasks, + patterns=comma_sep_to_list(kwargs.get("patterns", "")), + commit_message=kwargs.get("commit_message", "Automatic updates from bot"), + dry_run=kwargs.get("dry_run", False), + )