def test_check_secrets(self): os.environ['SECRET_ONE'] = '1234' os.environ['SECRET_TWO'] = '5678' pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "popperized/bin/sh@master" args = ["ls -ltr"] secrets = ["SECRET_ONE", "SECRET_TWO"] } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() WorkflowRunner.check_secrets(wf, False, False) WorkflowRunner.check_secrets(wf, True, False) WorkflowRunner.check_secrets(wf, False, True) os.environ.pop('SECRET_ONE') pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "popperized/bin/sh@master" args = ["ls -ltr"] secrets = ["SECRET_ONE", "SECRET_TWO"] } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() os.environ['CI'] = 'false' with patch('getpass.getpass', return_value='1234') as fake_input: WorkflowRunner.check_secrets(wf, False, False) os.environ['CI'] = 'true' os.environ.pop('SECRET_ONE') self.assertRaises(SystemExit, WorkflowRunner.check_secrets, wf, False, False)
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.parse() wf = Workflow.skip_actions(wf, 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 test_download_actions(self): pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "popperized/bin/sh@master" } action "b" { uses = "popperized/ansible@master" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() # Download actions in the default cache directory. WorkflowRunner.download_actions(wf, False, False, '12345') self.assertEqual( os.path.exists(os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com'), True) # Download actions in custom cache directory os.environ['POPPER_CACHE_DIR'] = '/tmp/somedir' WorkflowRunner.download_actions(wf, False, False, '12345') self.assertEqual( os.path.exists('/tmp/somedir/actions/12345/github.com'), True) os.environ.pop('POPPER_CACHE_DIR') # Release resources. shutil.rmtree('/tmp/somedir') shutil.rmtree(os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com') # Test with skipclone flag when action not present in cache. self.assertRaises(SystemExit, WorkflowRunner.download_actions, wf, False, True, '12345')
def test_get_workflow_env(self): pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "sh" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() env = WorkflowRunner.get_workflow_env(wf, '/tmp/test_folder') self.assertDictEqual( env, { 'HOME': os.environ['HOME'], 'GITHUB_WORKFLOW': 'sample', 'GITHUB_ACTION': '', 'GITHUB_ACTOR': 'popper', 'GITHUB_REPOSITORY': 'unknown', 'GITHUB_EVENT_NAME': 'push', 'GITHUB_EVENT_PATH': '/tmp/github_event.json', 'GITHUB_WORKSPACE': '/tmp/test_folder', 'GITHUB_SHA': 'unknown', 'GITHUB_REF': 'unknown', 'POPPER_WORKFLOW': 'sample', 'POPPER_ACTION': '', 'POPPER_ACTOR': 'popper', 'POPPER_REPOSITORY': 'unknown', 'POPPER_EVENT_NAME': 'push', 'POPPER_EVENT_PATH': '/tmp/github_event.json', 'POPPER_WORKSPACE': '/tmp/test_folder', 'POPPER_SHA': 'unknown', 'POPPER_REF': 'unknown' })
def test_instantiate_runners(self): pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "sh" args = "ls" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() env = WorkflowRunner.get_workflow_env(wf, '/tmp/test_folder') WorkflowRunner.instantiate_runners('docker', wf, '/tmp/test_folder', False, False, '12345') self.assertIsInstance(wf.action['a']['runner'], HostRunner) os.makedirs('/tmp/test_folder/actions/sample') pu.write_file('/tmp/test_folder/actions/sample/entrypoint.sh') pu.write_file('/tmp/test_folder/actions/sample/README.md') pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "./actions/sample" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() env = WorkflowRunner.get_workflow_env(wf, '/tmp/test_folder') WorkflowRunner.instantiate_runners('singularity', wf, '/tmp/test_folder', False, False, '12345') self.assertIsInstance(wf.action['a']['runner'], HostRunner) pu.write_file( '/tmp/test_folder/a.workflow', """ workflow "sample" { resolves = "a" } action "a" { uses = "popperized/bin/sh@master" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() env = WorkflowRunner.get_workflow_env(wf, '/tmp/test_folder') WorkflowRunner.instantiate_runners('singularity', wf, '/tmp/test_folder', False, False, '12345') self.assertIsInstance(wf.action['a']['runner'], SingularityRunner) WorkflowRunner.instantiate_runners('docker', wf, '/tmp/test_folder', False, False, '12345') self.assertIsInstance(wf.action['a']['runner'], DockerRunner) WorkflowRunner.instantiate_runners('vagrant', wf, '/tmp/test_folder', False, False, '12345') self.assertIsInstance(wf.action['a']['runner'], VagrantRunner)
class TestHostRunner(unittest.TestCase): def setUp(self): os.makedirs('/tmp/test_folder') os.chdir('/tmp/test_folder') log.setLevel('CRITICAL') workflow = """ workflow "sample" { resolves = "sample action" } action "sample action" { uses = "sh" args = ["echo", "Hello"] } """ pu.write_file('/tmp/test_folder/a.workflow', workflow) self.wf = Workflow('/tmp/test_folder/a.workflow') self.wf.parse() WorkflowRunner.instantiate_runners('docker', self.wf, '/tmp/test_folder', False, False, '12345') def tearDown(self): os.chdir('/tmp') shutil.rmtree('/tmp/test_folder') log.setLevel('NOTSET') def test_run(self): runner = self.wf.action['sample action']['runner'] self.assertRaises(SystemExit, runner.run, reuse=True) runner.run() def test_host_prepare(self): runner = self.wf.action['sample action']['runner'] runner.action['runs'] = ['script1'] runner.action['args'] = ['github.com'] cmd = runner.host_prepare() self.assertEqual(cmd, ['/tmp/test_folder/script1', 'github.com']) os.makedirs('/tmp/test_folder/action/myaction') runner.action['uses'] = './action/myaction' runner.action['runs'] = ['script'] runner.action['args'] = ['arg1', 'arg2'] cmd = runner.host_prepare() self.assertEqual( cmd, ['/tmp/test_folder/./action/myaction/./script', 'arg1', 'arg2']) os.chdir('/tmp/test_folder') runner.action.pop('runs') cmd = runner.host_prepare() self.assertEqual(cmd, [ '/tmp/test_folder/./action/myaction/./entrypoint.sh', 'arg1', 'arg2' ]) def test_host_start(self): runner = self.wf.action['sample action']['runner'] runner.prepare_environment(set_env=True) e = runner.host_start( ["sh", "-c", "echo 'Hello from Popper 2.x !' > popper.file"]) self.assertEqual(e, 0) self.assertEqual(os.path.exists('popper.file'), True) runner.remove_environment()
class TestVagrantRunner(unittest.TestCase): def setUp(self): os.makedirs('/tmp/test_folder') os.chdir('/tmp/test_folder') log.setLevel('CRITICAL') workflow = """ workflow "sample" { resolves = "sample action" } action "sample action" { uses = "popperized/bin/sh@master" args = ["echo", "Hello"] } """ pu.write_file('/tmp/test_folder/a.workflow', workflow) self.wf = Workflow('/tmp/test_folder/a.workflow') self.wf.parse() WorkflowRunner.download_actions(self.wf, False, False, '12345') WorkflowRunner.instantiate_runners('vagrant', self.wf, '/tmp/test_folder', False, False, '12345') self.runner = self.wf.action['sample action']['runner'] VagrantRunner.setup_vagrant_cache('12345') def tearDown(self): os.chdir('/tmp') shutil.rmtree('/tmp/test_folder') log.setLevel('NOTSET') @unittest.skipIf(os.environ['RUNTIME'] != 'vagrant', 'Skipping vagrant tests...') def test_setup_vagrant_cache(self): cache_path = os.path.join(os.environ['HOME'], '.cache/.popper/vagrant/12345') shutil.rmtree(cache_path) self.assertEqual(os.path.exists(cache_path), False) VagrantRunner.setup_vagrant_cache('12345') self.assertEqual(os.path.exists(cache_path), True) @unittest.skipIf(os.environ['RUNTIME'] != 'vagrant', 'Skipping vagrant tests...') def test_vagrant_start(self): os.makedirs('/tmp/test_folder/test_vm') vagrantfile_content = """ Vagrant.configure("2") do |config| config.vm.box = "ailispaw/barge" end """ pu.write_file('/tmp/test_folder/test_vm/Vagrantfile', vagrantfile_content) self.runner.vagrant_start('/tmp/test_folder/test_vm') self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), True) vagrant.Vagrant(root='/tmp/test_folder/test_vm').halt() vagrant.Vagrant(root='/tmp/test_folder/test_vm').destroy() @unittest.skipIf(os.environ['RUNTIME'] != 'vagrant', 'Skipping vagrant tests...') def test_vagrant_stop(self): os.makedirs('/tmp/test_folder/test_vm') vagrantfile_content = """ Vagrant.configure("2") do |config| config.vm.box = "ailispaw/barge" end """ pu.write_file('/tmp/test_folder/test_vm/Vagrantfile', vagrantfile_content) v = vagrant.Vagrant(root='/tmp/test_folder/test_vm') v.up() self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), True) self.runner.vagrant_stop('/tmp/test_folder/test_vm') self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), False) vagrant.Vagrant(root='/tmp/test_folder/test_vm').destroy() @unittest.skipIf(os.environ['RUNTIME'] != 'vagrant', 'Skipping vagrant tests...') def test_vagrant_exists(self): os.makedirs('/tmp/test_folder/test_vm') vagrantfile_content = """ Vagrant.configure("2") do |config| config.vm.box = "ailispaw/barge" end """ pu.write_file('/tmp/test_folder/test_vm/Vagrantfile', vagrantfile_content) v = vagrant.Vagrant(root='/tmp/test_folder/test_vm') v.up() self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), True) v.halt() self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), False) vagrant.Vagrant(root='/tmp/test_folder/test_vm').destroy() shutil.rmtree('/tmp/test_folder/test_vm') self.assertEqual( self.runner.vagrant_exists('/tmp/test_folder/test_vm'), False) @unittest.skipIf(os.environ['RUNTIME'] != 'vagrant', 'Skipping vagrant tests...') def test_vagrant_write_vagrantfile(self): self.runner.vagrant_write_vagrantfile('/tmp/test_folder/test_vm') required_content = """ Vagrant.configure("2") do |config| config.vm.box = "ailispaw/barge" config.vm.synced_folder "{}", "{}" config.vm.synced_folder "/tmp/test_folder", "/tmp/test_folder" end """.format(os.environ['HOME'], os.environ['HOME']) f = open('/tmp/test_folder/test_vm/Vagrantfile') content = f.readlines() f.close() for line in content: self.assertEqual(line in required_content, True)
class TestSingularityRunner(unittest.TestCase): def setUp(self): os.makedirs('/tmp/test_folder') os.chdir('/tmp/test_folder') log.setLevel('CRITICAL') workflow = """ workflow "sample" { resolves = "sample action" } action "sample action" { uses = "popperized/bin/sh@master" args = ["echo", "Hello"] } """ pu.write_file('/tmp/test_folder/a.workflow', workflow) self.wf = Workflow('/tmp/test_folder/a.workflow') self.wf.parse() WorkflowRunner.download_actions(self.wf, False, False, '12345') WorkflowRunner.instantiate_runners('singularity', self.wf, '/tmp/test_folder', False, False, '12345') self.runner = self.wf.action['sample action']['runner'] SingularityRunner.setup_singularity_cache('12345') def tearDown(self): os.chdir('/tmp') shutil.rmtree('/tmp/test_folder') shutil.rmtree(os.path.join(os.environ['HOME'], '.cache/.popper')) log.setLevel('NOTSET') @unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_singularity_exists(self): pu.write_file('/tmp/test_folder/testimg.sif', 'fake image file') self.assertEqual( self.runner.singularity_exists('/tmp/test_folder/testimg.sif'), True) os.remove('/tmp/test_folder/testimg.sif') @unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_singularity_rm(self): pu.write_file('/tmp/test_folder/testimg.sif', 'fake image file') self.runner.singularity_rm('/tmp/test_folder/testimg.sif') self.assertEqual( self.runner.singularity_exists('/tmp/test_folder/testimg.sif'), False) @unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_singularity_build_from_image(self): self.runner.singularity_build_from_image( 'docker://*****:*****@unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_singularity_build_from_recipe(self): os.chdir( os.path.join( os.environ['HOME'], '.cache/.popper/actions/12345/github.com/popperized/bin/sh')) self.runner.singularity_build_from_recipe( os.path.join( os.environ['HOME'], '.cache/.popper/actions/12345/github.com/popperized/bin/sh'), os.path.join(os.environ['HOME'], '.cache/.popper/singularity/12345/testimg.sif')) self.assertEqual( os.path.exists( os.path.join(os.environ['HOME'], '.cache/.popper/singularity/12345/testimg.sif')), True) @unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_get_recipe_file(self): os.chdir(os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com/popperized/bin/sh') file = SingularityRunner.get_recipe_file(os.getcwd(), '12345') self.assertEqual( file, os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com/popperized/bin/sh/' + 'Singularity.12345') os.remove( os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com/popperized/bin/sh/' + 'Dockerfile') self.assertRaises(SystemExit, SingularityRunner.get_recipe_file, os.getcwd(), '12345') @unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_singularity_start(self): self.runner.action['runs'] = [ "sh", "-c", "echo 'Hello from Popper 2.x !' > popper.file" ] self.runner.singularity_build_from_image( 'docker://*****:*****@unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_get_build_resources(self): res = self.runner.get_build_resources() self.assertTupleEqual( res, (True, 'popperized/bin/sh@master', os.path.join( os.environ['HOME'], '.cache/.popper/actions/12345/github.com/popperized/bin/sh'))) self.runner.action['uses'] = 'docker://*****:*****@unittest.skipIf(os.environ['RUNTIME'] != 'singularity', 'Skipping singularity tests...') def test_setup_singularity_cache(self): cache_path = os.path.join(os.environ['HOME'], '.cache/.popper/singularity/12345') shutil.rmtree(cache_path) self.assertEqual(os.path.exists(cache_path), False) SingularityRunner.setup_singularity_cache('12345') self.assertEqual(os.path.exists(cache_path), True)
class TestDockerRunner(unittest.TestCase): def setUp(self): os.makedirs('/tmp/test_folder') os.chdir('/tmp/test_folder') log.setLevel('CRITICAL') workflow = """ workflow "sample" { resolves = "sample action" } action "sample action" { uses = "popperized/bin/sh@master" args = ["echo", "Hello"] } """ pu.write_file('/tmp/test_folder/a.workflow', workflow) self.wf = Workflow('/tmp/test_folder/a.workflow') self.wf.parse() WorkflowRunner.download_actions(self.wf, False, False, '12345') WorkflowRunner.instantiate_runners('docker', self.wf, '/tmp/test_folder', False, False, '12345') self.docker_client = docker.from_env() self.runner = self.wf.action['sample action']['runner'] def tearDown(self): os.chdir('/tmp') shutil.rmtree('/tmp/test_folder') shutil.rmtree(os.path.join(os.environ['HOME'], '.cache/.popper')) log.setLevel('NOTSET') self.docker_client.close() @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_get_build_resources(self): res = self.runner.get_build_resources() self.assertTupleEqual( res, (True, 'popperized/bin:master', os.environ['HOME'] + '/.cache/.popper/actions/12345/github.com/popperized/bin/sh')) self.runner.action['uses'] = 'docker://*****:*****@unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_exists(self): image = self.docker_client.images.pull('debian:buster-slim') container = self.docker_client.containers.create( image='debian:buster-slim', name='popper_sample_action_12345') self.assertEqual(self.runner.docker_exists(), True) container.remove() self.docker_client.images.remove('debian:buster-slim') @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_image_exists(self): image = self.docker_client.images.pull('debian:buster-slim') self.assertEqual(self.runner.docker_image_exists('debian:buster-slim'), True) self.docker_client.images.remove('debian:buster-slim', force=True) @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_rm(self): self.docker_client.images.pull('debian:buster-slim') self.runner.docker_create('debian:buster-slim') self.runner.docker_rm() self.assertRaises(docker.errors.NotFound, self.runner.docker_rm) @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_pull(self): self.assertEqual(self.runner.docker_image_exists('debian:buster-slim'), False) self.runner.skip_pull = True self.assertRaises(SystemExit, self.runner.docker_pull, 'debian:buster-slim') self.runner.skip_pull = False self.runner.docker_pull('debian:buster-slim') self.assertEqual(self.runner.docker_image_exists('debian:buster-slim'), True) @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_start(self): self.runner.action['runs'] = [ "sh", "-c", "echo 'Hello from Popper 2.x !' > popper.file" ] self.runner.docker_pull('debian:buster-slim') self.runner.docker_create('debian:buster-slim') e = self.runner.docker_start() self.assertEqual(e, 0) self.assertEqual(os.path.exists('popper.file'), True) res = self.docker_client.containers.list(filters={'status': 'running'}) self.assertListEqual(res, []) self.runner.docker_rm() @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_build(self): pu.write_file( '/tmp/test_folder/Dockerfile', """ FROM debian:stable-slim RUN apt-get update && \ apt-get install curl -y && \ apt-get clean -y """) self.runner.docker_build('abcd:latest', '/tmp/test_folder') res = self.docker_client.images.get('abcd:latest') @unittest.skipIf(os.environ['RUNTIME'] != 'docker', 'Skipping docker tests...') def test_docker_create(self): self.runner.action['args'] = ['env'] self.runner.docker_pull('debian:buster-slim') self.runner.docker_create('debian:buster-slim') self.assertEqual(self.runner.docker_exists(), True) self.runner.docker_rm()
class TestActionRunner(unittest.TestCase): def setUp(self): os.makedirs('/tmp/test_folder') os.chdir('/tmp/test_folder') log.setLevel('CRITICAL') workflow = """ workflow "sample" { resolves = "sample action" } action "sample action" { uses = "popperized/bin/sh@master" args = ["echo", "Hello"] } """ pu.write_file('/tmp/test_folder/a.workflow', workflow) self.wf = Workflow('/tmp/test_folder/a.workflow') self.wf.parse() WorkflowRunner.instantiate_runners('docker', self.wf, '/tmp/test_folder', False, False, '12345') self.runner = self.wf.action['sample action']['runner'] def tearDown(self): os.chdir('/tmp') shutil.rmtree('/tmp/test_folder') log.setLevel('NOTSET') def test_check_executable(self): self.assertRaises(SystemExit, self.runner.check_executable, 'abcd') def test_handle_exit(self): self.flag = 0 def signal_handler(sig, frame): self.flag = 1 signal.signal(signal.SIGUSR1, signal_handler) self.assertRaises(SystemExit, self.runner.handle_exit, 1) self.runner.handle_exit(0) self.assertEqual(self.flag, 0) self.runner.handle_exit(78) self.assertEqual(self.flag, 1) def test_prepare_environment(self): env = self.runner.prepare_environment() self.assertDictEqual( env, { 'HOME': os.environ['HOME'], 'GITHUB_WORKFLOW': 'sample', 'GITHUB_ACTION': 'sample action', 'GITHUB_ACTOR': 'popper', 'GITHUB_REPOSITORY': 'unknown', 'GITHUB_EVENT_NAME': 'push', 'GITHUB_EVENT_PATH': '/tmp/github_event.json', 'GITHUB_WORKSPACE': '/tmp/test_folder', 'GITHUB_SHA': 'unknown', 'GITHUB_REF': 'unknown', 'POPPER_WORKFLOW': 'sample', 'POPPER_ACTION': 'sample action', 'POPPER_ACTOR': 'popper', 'POPPER_REPOSITORY': 'unknown', 'POPPER_EVENT_NAME': 'push', 'POPPER_EVENT_PATH': '/tmp/github_event.json', 'POPPER_WORKSPACE': '/tmp/test_folder', 'POPPER_SHA': 'unknown', 'POPPER_REF': 'unknown' }) self.assertEqual(set(env.keys()).issubset(set(os.environ)), False) env = self.runner.prepare_environment(set_env=True) self.assertEqual(set(env.keys()).issubset(set(os.environ)), True) self.runner.remove_environment() def test_prepare_volumes(self): env = self.runner.prepare_environment() volumes = self.runner.prepare_volumes(env) self.assertEqual(volumes, [ '{}:{}'.format(os.environ['HOME'], os.environ['HOME']), '{}:/github/home'.format( os.environ['HOME']), '/tmp/test_folder:/tmp/test_folder', '/tmp/test_folder:/github/workspace', '/tmp/github_event.json:/github/workflow/event.json' ]) volumes = self.runner.prepare_volumes(env, include_docker_socket=True) self.assertEqual(volumes, [ '/var/run/docker.sock:/var/run/docker.sock', '{}:{}'.format( os.environ['HOME'], os.environ['HOME']), '{}:/github/home'.format( os.environ['HOME']), '/tmp/test_folder:/tmp/test_folder', '/tmp/test_folder:/github/workspace', '/tmp/github_event.json:/github/workflow/event.json' ]) def test_remove_environment(self): env = self.runner.prepare_environment(set_env=True) self.assertEqual(set(env.keys()).issubset(set(os.environ)), True) self.runner.remove_environment() self.assertEqual(set(env.keys()).issubset(set(os.environ)), False) def test_setup_necessary_files(self): os.remove('/tmp/github_event.json') self.assertEqual(os.path.exists('/tmp/github_event.json'), False) self.runner.setup_necessary_files() self.assertEqual(os.path.exists('/tmp/github_event.json'), True) self.runner.workspace = '/tmp/a/b/c' self.runner.setup_necessary_files() self.assertEqual(os.path.exists('/tmp/a/b/c'), True)
def test_get_stages(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() stages = list() for stage in wf.get_stages(): stages.append(stage) self.assertListEqual(stages, [{'b', 'c', 'a'}, {'d'}, {'e'}, {'end'}]) self.create_workflow_file(""" workflow "example" { resolves = ["end"] } action "a" { uses = "sh" args = "ls" } action "b" { needs = "a" uses = "sh" args = "ls" } action "c" { uses = "sh" args = "ls" } action "d" { uses = "sh" needs = ["b", "c"] args = "ls" } action "g" { needs = "d" uses = "sh" args = "ls" } action "f" { needs = "d" uses = "sh" args = "ls" } action "h" { needs = "g" uses = "sh" args = "ls" } action "end" { needs = ["h", "f"] uses = "sh" args = "ls" } """) wf = Workflow('/tmp/test_folder/a.workflow') wf.parse() stages = list() for stage in wf.get_stages(): stages.append(stage) self.assertListEqual( stages, [{'a', 'c'}, {'b'}, {'d'}, {'g', 'f'}, {'h'}, {'end'}])
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_filter_action(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.filter_action(wf, 'e') self.assertSetEqual(changed_wf.root, {'e'}) self.assertDictEqual( changed_wf.action, { 'e': { 'needs': [], 'uses': 'sh', 'args': ['ls'], 'name': 'e', 'next': set() } }) changed_wf = Workflow.filter_action(wf, 'd') self.assertSetEqual(changed_wf.root, {'d'}) self.assertDictEqual( changed_wf.action, { 'd': { 'needs': [], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': set() } }) changed_wf = Workflow.filter_action(wf, 'e', with_dependencies=True) self.assertSetEqual(changed_wf.root, {'b', 'a', 'c'}) self.assertDictEqual( changed_wf.action, { 'a': { 'uses': 'sh', 'args': ['ls'], 'name': 'a', 'next': {'e'} }, 'b': { 'uses': 'sh', 'args': ['ls'], 'name': 'b', 'next': {'e'} }, 'c': { 'uses': 'sh', 'args': ['ls'], 'name': 'c', 'next': {'d'} }, 'd': { 'needs': ['c'], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': {'e'} }, 'e': { 'needs': ['d', 'b', 'a'], 'uses': 'sh', 'args': ['ls'], 'name': 'e', 'next': set() } }) changed_wf = Workflow.filter_action(wf, 'd', with_dependencies=True) self.assertSetEqual(changed_wf.root, {'c'}) self.assertDictEqual( changed_wf.action, { 'c': { 'uses': 'sh', 'args': ['ls'], 'name': 'c', 'next': {'d'} }, 'd': { 'needs': ['c'], 'uses': 'sh', 'args': ['ls'], 'name': 'd', 'next': set() } })
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' } })