def run(self, action, skip_clone, skip_pull, skip, workspace, reuse, dry_run, parallel, with_dependencies, runtime, skip_secrets_prompt=False): """Run the workflow or a specific action. """ new_wf = deepcopy(self.wf) if skip: new_wf = Workflow.skip_actions(self.wf, skip) if action: new_wf = Workflow.filter_action(self.wf, action, with_dependencies) new_wf.check_for_unreachable_actions(skip) WorkflowRunner.check_secrets(new_wf, dry_run, skip_secrets_prompt) WorkflowRunner.download_actions(new_wf, dry_run, skip_clone, self.wid) WorkflowRunner.instantiate_runners(runtime, new_wf, workspace, dry_run, skip_pull, self.wid) for s in new_wf.get_stages(): WorkflowRunner.run_stage(runtime, new_wf, s, reuse, parallel)
def cli(ctx, wfile, skip, recursive, colors): """ Creates a graph in the .dot format representing the workflow. """ def add_to_graph(dot_str, wf, parent, children, node_attrs, stage_edges): """Recursively goes over the children ("next" attribute) of the given parent, adding an edge from parent to children """ for n in children: edge = ' "{}" -> "{}";\n'.format(parent, n) if edge in stage_edges: continue dot_str += edge + ' "{}" [{}];\n'.format(n, node_attrs) stage_edges.add(edge) for M in wf.get_action(n).get('next', []): dot_str = add_to_graph(dot_str, wf, n, [M], node_attrs, stage_edges) return dot_str wfile_list = list() if recursive: wfile_list = pu.find_recursive_wfile() else: wfile_list.append(pu.find_default_wfile(wfile)) for wfile in wfile_list: wf = Workflow(wfile) wf.skip_actions(skip) wf.check_for_unreachable_actions() node_attrs = ('shape=box, style="filled{}", fillcolor=transparent{}') wf_attr = node_attrs.format(',rounded', ',color=red' if colors else '') act_attr = node_attrs.format('', ',color=cyan' if colors else '') dot_str = add_to_graph("", wf, wf.name, wf.root, act_attr, set()) dot_str += ' "{}" [{}];\n'.format(wf.name, wf_attr) log.info("digraph G { graph [bgcolor=transparent];\n" + dot_str + "}\n")
def run(self, action, skip_clone, skip_pull, skip, workspace, reuse, dry_run, parallel, with_dependencies, engine, skip_secrets_prompt=False): """Run the workflow or a specific action. Args: action(str): Name of particular action being executed from workflow. skip_clone(bool): True if cloning action has to be skipped. skip_pull(bool): True if pulling action has to be skipped. skip(tuple): Tuple containing the actions to be skipped. workspace(str): Location of the workspace. reuse(bool): True if existing containers are to be reused. dry_run(bool): True if workflow flag is being dry-run. parallel(bool): True if actions are to be executed in parallel. with_dependencies(bool): True if with-dependencies flag is passed as an argument. engine(str): Name of the run time being used in workflow. skip_secrets_prompt(bool): True if part of the workflow has to be skipped.(Default value = False) Returns: None """ new_wf = deepcopy(self.wf) if skip: new_wf = Workflow.skip_actions(self.wf, skip) if action: new_wf = Workflow.filter_action(self.wf, action, with_dependencies) new_wf.check_for_unreachable_actions(skip) WorkflowRunner.check_secrets(new_wf, dry_run, skip_secrets_prompt) WorkflowRunner.download_actions(new_wf, dry_run, skip_clone, self.wid) WorkflowRunner.instantiate_runners(engine, new_wf, workspace, dry_run, skip_pull, self.wid) for s in new_wf.get_stages(): WorkflowRunner.run_stage(engine, new_wf, s, reuse, parallel)
def test_check_for_unreachable_actions(self): self.create_workflow_file(""" workflow "example" { resolves = "end" } action "a" { uses = "sh" args = "ls" } action "b" { uses = "sh" args = "ls" } action "c" { uses = "sh" args = "ls" } action "d" { needs = ["c"] uses = "sh" args = "ls" } action "e" { needs = ["d", "b", "a"] uses = "sh" args = "ls" } action "end" { needs = "e" uses = "sh" args = "ls" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() changed_wf = Workflow.skip_actions(wf, ['d', 'a', 'b']) self.assertDictEqual( changed_wf.action, { 'a': { 'uses': 'sh', 'args': ['ls'], 'name': 'a', 'next': set() }, 'b': { 'uses': 'sh', 'args': ['ls'], 'name': 'b', 'next': set() }, 'c': { 'uses': 'sh', 'args': ['ls'], 'name': 'c', 'next': set() }, 'd': { 'needs': [], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': set() }, 'e': { 'needs': [], 'uses': 'sh', 'args': ['ls'], 'name': 'e', 'next': {'end'} }, 'end': { 'needs': ['e'], 'uses': 'sh', 'args': ['ls'], 'name': 'end' } }) self.assertRaises(SystemExit, changed_wf.check_for_unreachable_actions, True) self.create_workflow_file(""" workflow "sample" { resolves = ["reachable"] } action "reachable" { uses = "popperized/bin/sh@master" args = "ls" } action "unreachable" { uses = "popperized/bin/sh@master" args = ["ls -ltr"] } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() wf.check_for_unreachable_actions()
def test_skip_actions(self): self.create_workflow_file(""" workflow "example" { resolves = "end" } action "a" { uses = "sh" args = "ls" } action "b" { uses = "sh" args = "ls" } action "c" { uses = "sh" args = "ls" } action "d" { needs = ["c"] uses = "sh" args = "ls" } action "e" { needs = ["d", "b", "a"] uses = "sh" args = "ls" } action "end" { needs = "e" uses = "sh" args = "ls" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() changed_wf = Workflow.skip_actions(wf, ['b']) self.assertDictEqual( changed_wf.action, { 'a': { 'uses': 'sh', 'args': ['ls'], 'name': 'a', 'next': {'e'} }, 'b': { 'uses': 'sh', 'args': ['ls'], 'name': 'b', 'next': set() }, 'c': { 'uses': 'sh', 'args': ['ls'], 'name': 'c', 'next': {'d'} }, 'd': { 'needs': ['c'], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': {'e'} }, 'e': { 'needs': ['d', 'a'], 'uses': 'sh', 'args': ['ls'], 'name': 'e', 'next': {'end'} }, 'end': { 'needs': ['e'], 'uses': 'sh', 'args': ['ls'], 'name': 'end' } }) changed_wf = Workflow.skip_actions(wf, ['d', 'a']) self.assertDictEqual( changed_wf.action, { 'a': { 'uses': 'sh', 'args': ['ls'], 'name': 'a', 'next': set() }, 'b': { 'uses': 'sh', 'args': ['ls'], 'name': 'b', 'next': {'e'} }, 'c': { 'uses': 'sh', 'args': ['ls'], 'name': 'c', 'next': set() }, 'd': { 'needs': [], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': set() }, 'e': { 'needs': ['b'], 'uses': 'sh', 'args': ['ls'], 'name': 'e', 'next': {'end'} }, 'end': { 'needs': ['e'], 'uses': 'sh', 'args': ['ls'], 'name': 'end' } })