Пример #1
0
    def host_prepare(self):
        """Prepare the commands and environment to start execution.

        Returns:
            str: The command to execute.
        """
        root = scm.get_git_root_folder()
        if self.action['uses'] == 'sh':
            cmd = self.action.get('runs', [])
            if cmd:
                cmd[0] = os.path.join(root, cmd[0])
            cmd.extend(self.action.get('args', []))

            if not self.dry_run:
                os.chdir(root)
        else:
            cmd = self.action.get('runs', ['entrypoint.sh'])
            cmd[0] = os.path.join('./', cmd[0])
            cmd.extend(self.action.get('args', []))

            if not self.dry_run:
                if 'repo_dir' in self.action:
                    os.chdir(self.action['repo_dir'])
                    cmd[0] = os.path.join(self.action['repo_dir'], cmd[0])
                else:
                    os.chdir(os.path.join(root, self.action['uses']))
                    cmd[0] = os.path.join(root, self.action['uses'], cmd[0])

        return cmd
Пример #2
0
    def instantiate_runners(runtime, wf, workspace, dry_run, skip_pull, wid):
        """Factory of ActionRunner instances, one for each action.

        Note:
            If the `uses` attribute startswith a './' and does not have
            a `Dockerfile` in the referenced directory, we assume that
            it is meant to be run on the Host machine and ignore the
            runtime argument.
            Same is the case when the `uses` attribute is equal to 'sh'.
        """
        env = WorkflowRunner.get_workflow_env(wf, workspace)
        for _, a in wf.action.items():

            if a['uses'] == 'sh':
                a['runner'] = HostRunner(
                    a, workspace, env, dry_run, skip_pull, wid)
                continue

            if a['uses'].startswith('./'):
                if not os.path.isfile(
                    os.path.join(scm.get_git_root_folder(), a['uses'],
                                 'Dockerfile')):

                    a['runner'] = HostRunner(
                        a, workspace, env, dry_run, skip_pull, wid)
                    continue

            if runtime == 'docker':
                a['runner'] = DockerRunner(
                    a, workspace, env, dry_run, skip_pull, wid)

            elif runtime == 'singularity':
                a['runner'] = SingularityRunner(
                    a, workspace, env, dry_run, skip_pull, wid)
Пример #3
0
    def get_build_resources(self):
        """Parse the `uses` attribute and get the build
        resources from them.

        Args:
            (bool, str, str): pull/build, image ref, the build source.
        """
        build = True
        image = None
        build_source = None

        if 'docker://' in self.action['uses']:
            image = self.action['uses']
            build = False

        elif './' in self.action['uses']:
            image = 'action/' + self.action['uses']
            build_source = os.path.join(
                scm.get_git_root_folder(), self.action['uses'])

        else:
            image = self.action['uses']
            build_source = os.path.join(
                self.action['repo_dir'], self.action['action_dir'])

        return (build, image, build_source)
Пример #4
0
def cli(ctx, service):
    """Generates configuration files for distinct CI services. This command
    needs to be executed on the root of your Git repository folder.
    """
    if service not in ci_files:
        log.fail("Unrecognized service " + service)

    project_root = scm.get_git_root_folder()

    if project_root != os.getcwd():
        log.fail('This command needs to be executed on the root of your '
                 'Git project folder (where the .git/ folder is located).')

    for ci_file, ci_file_content in pu.get_items(ci_files[service]):
        ci_file_content = ci_file_content
        ci_file = os.path.join(project_root, ci_file)
        # create parent folder
        if not os.path.isdir(os.path.dirname(ci_file)):
            os.makedirs(os.path.dirname(ci_file))

        # write content
        with open(ci_file, 'w') as f:
            f.write(ci_file_content)

    log.info('Wrote {} configuration successfully.'.format(service))
Пример #5
0
def cli(ctx, service, install):
    """Generates configuration files for distinct CI services. This command
    needs to be executed on the root of your Git repository folder.
    """
    project_root = scm.get_git_root_folder()

    if project_root != os.getcwd():
        log.fail(
            'This command needs to be executed on the root of your '
            'Git project folder (where the .git/ folder is located).')

    for ci_file, ci_file_content in pu.get_items(ci_files[service]):

        # Prepare and write the CI config file.
        ci_file = os.path.join(project_root, ci_file)
        if not os.path.isdir(os.path.dirname(ci_file)):
            os.makedirs(os.path.dirname(ci_file))

        install_script_cmd = ''
        if install:
            if service == 'jenkins' or service == 'gitlab':
                log.fail(
                    'Scaffolding of custom install scripts is not '
                    'supported for Jenkins and Gitlab CI. Include it '
                    'manually depending upon the CI\'s OS.')

            elif service == 'travis':
                install_script_cmd = ('before_install: scripts/'
                                      'install_scripts.sh')

            elif service == 'circle':
                install_script_cmd = 'bash scripts/install_scripts.sh'

            elif service == 'brigade':
                install_script_cmd = '"bash scripts/install_scripts.sh",'

        with open(ci_file, 'w') as f:
            f.write(reformat(ci_file_content.safe_substitute(
                {'install_scripts': install_script_cmd})))

        # Prepare and Write the install scripts.
        if install:
            install = set(install)
            install_script_file = os.path.join(
                project_root, 'scripts', 'install_scripts.sh')
            script_content = base_script_content
            for runtime in install:
                script_content += install_scripts_content[runtime]

            if not os.path.isdir(os.path.dirname(install_script_file)):
                os.makedirs(os.path.dirname(install_script_file))

            with open(install_script_file, 'w') as f:
                f.write(script_content)

            st = os.stat(install_script_file)
            os.chmod(install_script_file, st.st_mode | stat.S_IEXEC)

    log.info('Wrote {} configuration successfully.'.format(service))
Пример #6
0
    def instantiate_runners(engine, wf, workspace, dry_run, skip_pull, wid):
        """Factory of ActionRunner instances, one for each action.

        Note:
            If the `uses` attribute startswith a './' and does not have
            a `Dockerfile` in the referenced directory, we assume that
            it is meant to be run on the Host machine and ignore the
            engine argument.
            Same is the case when the `uses` attribute is equal to 'sh'.

        Args:
          engine(str): Identifier of the workflow being executed.
          wf(popper.parser.workflow): Instance of the Workflow class.
          workspace(str): Location of the workspace.
          dry_run(bool): True if workflow flag is being dry-run.
          skip_pull(bool): True if pulling action has to be skipped.
          wid(str):

        Returns:
            None
        """
        env = WorkflowRunner.get_workflow_env(wf, workspace)
        for _, a in wf.action.items():

            if a['uses'] == 'sh':
                a['runner'] = HostRunner(a, workspace, env, dry_run, skip_pull,
                                         wid)
                continue

            if a['uses'].startswith('./'):
                if not os.path.isfile(
                        os.path.join(scm.get_git_root_folder(), a['uses'],
                                     'Dockerfile')):

                    a['runner'] = HostRunner(a, workspace, env, dry_run,
                                             skip_pull, wid)
                    continue

            if engine == 'docker':
                a['runner'] = DockerRunner(a, workspace, env, dry_run,
                                           skip_pull, wid)

            elif engine == 'singularity':
                a['runner'] = SingularityRunner(a, workspace, env, dry_run,
                                                skip_pull, wid)

            elif engine == 'vagrant':
                a['runner'] = VagrantRunner(a, workspace, env, dry_run,
                                            skip_pull, wid)
Пример #7
0
def cli(ctx, service, with_singularity):
    """Generates configuration files for distinct CI services. This command
    needs to be executed on the root of your Git repository folder.
    """
    if service not in ci_files:
        log.fail("Unrecognized service " + service)

    project_root = scm.get_git_root_folder()

    if project_root != os.getcwd():
        log.fail('This command needs to be executed on the root of your '
                 'Git project folder (where the .git/ folder is located).')

    for ci_file, ci_file_content in pu.get_items(ci_files[service]):
        ci_file_content = ci_file_content
        ci_file = os.path.join(project_root, ci_file)
        # Create parent folder
        if not os.path.isdir(os.path.dirname(ci_file)):
            os.makedirs(os.path.dirname(ci_file))

        # Customize content
        scripts = []
        if with_singularity:
            if service in ['jenkins', 'gitlab']:
                log.fail('Scaffolding of Singularity install script is not '
                         'supported for Jenkins and Gitlab CI. Include it '
                         'manually depending upon the CI\'s OS.')
            scripts.append(install_scripts['singularity'])

        if scripts:
            scripts = ' && '.join(scripts)
            if service == 'travis':
                scripts = '- ' + scripts
            if service == 'brigade':
                scripts = '"' + scripts + '",'
        else:
            scripts = ''

        # Write content
        with open(ci_file, 'w') as f:
            f.write(
                reformat(
                    ci_file_content.safe_substitute(
                        {'install_scripts': scripts})))

    log.info('Wrote {} configuration successfully.'.format(service))
Пример #8
0
    def get_build_resources(self):
        """Parse the `uses` attribute and get the build resources from them.

        Args:
            None

        Returns:
          bool: pull/build, image ref, the build source
        """
        build = True
        image = None
        build_source = None

        if 'docker://' in self.action['uses']:
            image = self.action['uses'].replace('docker://', '')
            if ':' not in image:
                image += ":latest"
            build = False

        elif './' in self.action['uses']:
            action_dir = os.path.basename(self.action['uses'].replace(
                './', ''))

            if self.env['GITHUB_REPOSITORY'] == 'unknown':
                repo_id = ''
            else:
                repo_id = self.env['GITHUB_REPOSITORY']

                if action_dir:
                    repo_id += '/'

            image = repo_id + action_dir + ':' + self.env['GITHUB_SHA']

            build_source = os.path.join(scm.get_git_root_folder(),
                                        self.action['uses'])
        else:
            _, _, user, repo, _, version = scm.parse(self.action['uses'])
            image = '{}/{}:{}'.format(user, repo, version)
            build_source = os.path.join(self.action['repo_dir'],
                                        self.action['action_dir'])

        image = image.lower()
        return (build, image, build_source)
Пример #9
0
 def test_get_git_root_folder(self):
     root_folder = scm.get_git_root_folder()
     self.assertEqual(root_folder, '/tmp/test_folder/github-actions-demo')
Пример #10
0
    def run(self, reuse=False):
        root = scm.get_git_root_folder()
        if self.action['uses'] == 'sh':
            cmd = self.action.get('runs', [])
            if cmd:
                cmd[0] = os.path.join(root, cmd[0])
            cmd.extend(self.action.get('args', []))

            if not self.dry_run:
                os.chdir(root)
        else:
            cmd = self.action.get('runs', ['entrypoint.sh'])
            cmd[0] = os.path.join('./', cmd[0])
            cmd.extend(self.action.get('args', []))

            if not self.dry_run:
                if 'repo_dir' in self.action:
                    os.chdir(self.action['repo_dir'])
                    cmd[0] = os.path.join(self.action['repo_dir'], cmd[0])
                else:
                    os.chdir(os.path.join(root, self.action['uses']))
                    cmd[0] = os.path.join(root, self.action['uses'], cmd[0])

        os.environ.update(self.action.get('env', {}))

        log.info('{}[{}] {}'.format(self.msg_prefix, self.action['name'],
                                    ' '.join(cmd)))

        if self.dry_run:
            return

        ecode = 0

        try:
            log.debug('Executing: {}'.format(' '.join(cmd)))
            p = Popen(' '.join(cmd),
                      stdout=PIPE,
                      stderr=STDOUT,
                      shell=True,
                      universal_newlines=True,
                      preexec_fn=os.setsid)

            popper.cli.process_list.append(p.pid)

            log.debug('Reading process output')

            for line in iter(p.stdout.readline, ''):
                line_decoded = pu.decode(line)
                log.info(line_decoded[:-1])

            p.wait()
            ecode = p.poll()
            log.debug('Code returned by process: {}'.format(ecode))

        except CalledProcessError as ex:
            msg = "Command '{}' failed: {}".format(cmd, ex)
            ecode = ex.returncode
            log.info(msg)
        finally:
            log.info()

        # remove variables that we added to the environment
        for i in self.action.get('env', {}):
            os.environ.pop(i)

        os.chdir(self.cwd)

        if ecode != 0:
            log.fail("Action '{}' failed.".format(self.action['name']))