Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/verify_and_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ jobs:
coverage run \
$(which cijoe) --monitor -l \
--config cijoe-example-${{ matrix.usage_example }}/cijoe-config.toml \
--workflow cijoe-example-${{ matrix.usage_example }}/cijoe-workflow.yaml
cijoe-example-${{ matrix.usage_example }}/cijoe-workflow.yaml

- name: Coverage report
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.coverage
cijoe-output*
cijoe-archive*
tags
selftest_results
*.egg-info
Expand Down
63 changes: 32 additions & 31 deletions docs/source/050_usage_help.out
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
usage: cijoe [-h] [--config CONFIG] [--workflow WORKFLOW] [--output OUTPUT]
[--log-level] [--monitor] [--no-report] [--skip-report]
[--tag TAG] [--archive] [--produce-report] [--integrity-check]
usage: cijoe [-h] [--config CONFIG] [--output OUTPUT] [--log-level]
[--monitor] [--no-report] [--skip-report] [--tag TAG]
[--archive] [--produce-report] [--integrity-check]
[--resources] [--example [EXAMPLE]] [--version]
[step ...]
[target] [step ...]

options:
-h, --help show this help message and exit

workflow:
Run workflow at '-w', using config at '-c', and output at '-o'
run:
Options for running a workflow script.

step Given a workflow; one or more workflow steps to run.
Else; one or more cijoe Python scripts to run.
(default: None)
target A cijoe workflow or script to run.
step Given a workflow, the steps of the workflow it
should run. If none are given, all steps are
run.
--config CONFIG, -c CONFIG
Path to the Configuration file. (default: cijoe-
config.toml)
--workflow WORKFLOW, -w WORKFLOW
Path to workflow file. (default: cijoe-workflow.yaml)
Path a Configuration file. Multiple can be
specified. (default: cijoe-config.toml)
(default: [])
--output OUTPUT, -o OUTPUT
Path to output directory. (default: /cijoe/docs/cijoe-
output)
--log-level, -l Increase log-level. Provide '-l' for info and '-ll'
for debug. (default: None)
Path to output directory. (default:
/cijoe/docs/cijoe-output)
--log-level, -l Increase log-level. Provide '-l' for info and
'-ll' for debug. (default: None)
--monitor, -m Dump command output to stdout (default: False)
--no-report, -n Skip the producing, and opening, a report at the end
of the workflow-run (default: False)
--skip-report, -s Skip the report opening at the end of the workflow-run
(default: True)
--tag TAG, -t TAG Tags to identify a workflow-run. This will be prefixed
while storing in archive (default: None)
--no-report, -n Skip the producing, and opening, a report at the
end of the workflow-run (default: False)
--skip-report, -s Skip the report opening at the end of the
workflow-run (default: True)
--tag TAG, -t TAG Tags to identify a workflow-run. This will be
prefixed while storing in archive (default:
None)

utilities:
Workflow, and workflow-related utilities
Expand All @@ -39,13 +40,13 @@ utilities:
--produce-report, -p Produce report, and open it, for output at '-o /
--output' and exit. (default: None)
--integrity-check, -i
Check integrity of workflow at '-w / --workflow' and
exit. (default: False)
--resources, -r List collected resources and exit. (default: False)
Check integrity of workflow given as positional
argument and exit. (default: False)
--resources, -r List collected resources and exit. (default:
False)
--example [EXAMPLE], -e [EXAMPLE]
Emits the given example. When no example is given,
then it prints a list of available examples. (default:
None)
Emits the given example. When no example is
given, then it prints a list of available
examples. (default: None)
--version, -v Print the version number of 'cijoe' and exit.
(default: False)

(default: False)
10 changes: 5 additions & 5 deletions docs/source/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ Which yields the following output:
Search Paths
============

The :ref:`sec-usage-cli` for the positional argument, and config-files
(``--c / --config``) and workflows (``-w / --workflow``) by default search for files
named ``cijoe-workflow.yaml`` and ``cijoe-config.toml``, respectfully. These files
are searched for, in order, in the following locations:
The :ref:`sec-usage-cli` for the positional target argument, and for config-files
(``--c / --config``) by default search for files named ``cijoe-workflow.yaml``
and ``cijoe-config.toml``, respectfully. These files are searched for, in order,
in the following locations:

``$PWD``
In your current working directory
Expand Down Expand Up @@ -179,7 +179,7 @@ as an artifact.
run: |
$(which cijoe) --monitor -l \
--config ./example/cijoe-config.toml \
--workflow ./example/cijoe-workflow.yaml
./example/cijoe-workflow.yaml

- name: Upload report
if: always()
Expand Down
150 changes: 76 additions & 74 deletions src/cijoe/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,45 +459,29 @@ def create_adhoc_workflow(args):
def parse_args():
"""Parse command-line interface."""

parent_dirs = set()
is_workflow = False

for i, argv in enumerate(sys.argv):
if i == 0 or sys.argv[i - 1].startswith("-"):
continue
if argv.endswith(".py"):
path = Path(argv).resolve()
parent_dirs.add(path.parent)
sys.argv[i] = path.stem
break
if argv.endswith(".yaml"):
is_workflow = True
sys.argv.insert(i, "--workflow")
sys.argv.insert(i, "workflow_path")
break

resource_scripts = get_resources(list(parent_dirs))["scripts"]

# A parent parser is added without help text to allow for parsing part of the
# arguments and evaluating them before proceeding with parsing the rest
parent_parser = argparse.ArgumentParser(add_help=False)

run_group = parent_parser.add_argument_group(
"run", "Options for running a workflow script."
)

run_group.add_argument(
"target",
nargs="?",
default=None,
help="A cijoe workflow or script to run.",
)
run_group.add_argument(
"step",
nargs="*",
default=[],
help="Given a workflow, the steps of the workflow it should run. If none are given, all steps are run.",
)

run_group.add_argument(
"--workflow",
"-w",
type=Path,
default=Path(
os.environ.get("CIJOE_DEFAULT_WORKFLOW", DEFAULT_WORKFLOW_FILENAME)
),
default=None,
help=argparse.SUPPRESS,
)
run_group.add_argument(
Expand Down Expand Up @@ -597,61 +581,79 @@ def parse_args():
help="Print the version number of 'cijoe' and exit.",
)

args, _ = parent_parser.parse_known_args()

# A parser inheriting from the parent_parser is added to allow for printing
# the help text if --help argument is given.
parser = argparse.ArgumentParser(
prog=Path(sys.argv[0]).stem,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
parents=[parent_parser],
)

subparsers = parser.add_subparsers()

# Create subparser for workflows
subparsers.add_parser(
"workflow_path", parents=[parent_parser], help="Path to a cijoe workflow file."
)
subparsers.add_parser("script_path", help="Path to a cijoe script.")
subparsers.add_parser(
"script_name",
help="Name of a cijoe script. You can see all reachable cijoe scripts with command 'cijoe -r'.",
)

# Create subparser for scripts
# Adding the subparser requires loading the whole script, so
# we only add the subparser to the script given in the arguments
if not is_workflow:
for i, argv in enumerate(sys.argv):
if i == 0 or argv.startswith("-") or sys.argv[i - 1].startswith("-"):
continue

# The first positional argument is the script identifier
ident = argv

script = resource_scripts.get(ident, None)
if not script:
log.error(f"Invalid target({ident})")
return errno.EINVAL, None
script.load()
help_text = (
next(line for line in script.docs.splitlines() if line)
if script.docs
else ""
)
subparser = subparsers.add_parser(
ident,
parents=[parent_parser],
help=help_text,
epilog=script.docs,
formatter_class=argparse.RawTextHelpFormatter,
)
subparser.add_argument(
"--script-name", default=ident, help=argparse.SUPPRESS
)
if script.argparser_func:
script.argparser_func(subparser)

break

args = parser.parse_args()
# For backwards compatibility: allow the --workflow argument.
# If the --workflow argument is used, and a positional argument is given, the
# parser will interpret it as a `target`, but we assume it to be a step
# identifier.
if args.workflow:
log.warning(
"The -w / --workflow argument is deprecated"
"please specify the workflow as a positional argument instead."
)
args = parser.parse_intermixed_args()
if args.target:
args.step = [args.target] + args.step
args.workflow = Path(args.workflow)

# If the target ends with .yaml, we run the workflow at the given path, and
# assume that the remaining positional args are step identifiers of the
# given workflow.
# note: the `parse_intermixed_args` allow for multiple groups of positional
# arguments, i.e. both the workflow path and step identifiers.
elif not args.target or args.target.endswith(".yaml"):
args = parser.parse_intermixed_args()
workflow = args.target or os.environ.get(
"CIJOE_DEFAULT_WORKFLOW", DEFAULT_WORKFLOW_FILENAME
)
setattr(args, "workflow", Path(workflow))

# Else, we assume the target is either a cijoe script identifier or path
else:
ident = args.target
parent_dirs = []

# If direct path to script is given, the parent directories must be
# included in the resource-collection
if ident.endswith(".py"):
path = Path(ident)
parent_dirs.append(path.parent)
ident = path.stem

resource_scripts = get_resources(parent_dirs)["scripts"]

# Load the script to get the name and arguments for the script, so
# arguments can be parsed and/or added to the help text
script = resource_scripts.get(ident, None)
if not script:
log.error(f"Invalid target({ident})")
return errno.EINVAL, None
script.load()

help_text = (
next(line for line in script.docs.splitlines() if line)
if script.docs
else ""
)
script_group = parser.add_argument_group(
help_text, "Options specific for the given script"
)
if script.argparser_func:
script.argparser_func(script_group)

args = parser.parse_args()

setattr(args, "script_name", ident)
args.step = []

levels = [log.ERROR, log.INFO, log.DEBUG]
log.basicConfig(
Expand Down
Loading
Loading