Beispiel #1
0
def docker_pull(image_tag):
    assert image_tag
    assert isinstance(image_tag, str)

    # Exit early if the image already exists locally.
    if _image_exists_locally(image_tag):
        return True

    image_location = _image_location(image_tag)
    command = 'sudo docker pull {}'.format(image_location)
    _, _, returncode = ShellWrapper.run_commands(command, shell=True)
    if returncode != 0:
        log.error('Could not download the image', image_location, 'from Docker Hub.')
    else:
        log.info('Downloaded the image', image_location + '.')
    return returncode == 0
Beispiel #2
0
def gen_script(utils, job, dependence_solver):
    """
    Invoke travis-build to generate the build script.
    """
    build_sh = os.path.join('reproduce_tmp', job.job_id + '.sh')
    reproducing_dir = utils.get_reproducing_repo_dir(job)

    if dependence_solver:
        from bugswarm.dependency_solver.dependency_solver import fix_dict
        pip_patch_result = os.path.join(utils.get_jobpair_dir(job),
                                        '{}-pip-patch.json'.format(job.job_id))
        commit_time = job.build.commit_time

        if not commit_time:
            github_wrapper = GitHubWrapper(GITHUB_TOKENS)
            _, commit_json = github_wrapper.get(
                'https://api.github.com/repos/{}/git/commits/{}'.format(
                    job.repo, job.travis_merge_sha))
            commit_time = commit_json['committer']['date']

        yaml_path = os.path.join(reproducing_dir, '.travis.yml')
        yaml_dict = job.config
        fixed_yaml_dict, pip_patch, apt_patch = fix_dict(
            reproducing_dir, yaml_dict, commit_time)
        with open(yaml_path, "w+") as f:
            yaml.dump(fixed_yaml_dict, f)

        if pip_patch:
            write_json(pip_patch_result, pip_patch)
        # update travis compile path based on https://github.com/travis-ci/travis-build/pull/1137
        travis_command = '~/.travis/travis-build/bin/travis compile > {}'.format(
            build_sh)
    else:
        # default travis compile should include build number and job number to resolve the matrix
        travis_command = '~/.travis/travis-build/bin/travis compile {} > {}'.format(
            job.build_job, build_sh)
    cd_command = 'cd {}'.format(reproducing_dir)
    _, stderr, returncode = ShellWrapper.run_commands(cd_command,
                                                      travis_command,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.PIPE,
                                                      shell=True)

    if returncode != 0:
        raise ReproduceError(
            'Encountered an error while generating the build script with travis-build: {}.'
            .format(stderr))
Beispiel #3
0
 def get_pr_commit_base(repo: str, commit: str, base_branch: str,
                        trigger_commit_timestamp: str) -> Optional[str]:
     # Change into the repo directory and then find the latest commit before the commit date.
     repo_path = Utils._canonical_repo_path(repo)
     cd_command = 'cd {}'.format(repo_path)
     # # Super hack.
     # commit_date = self.github.get_commit_date(repo, commit)
     # if commit_date is None:
     #     return None
     # git_command = 'git rev-list -n 1 --skip 1 --before="{}" --branches="{}"'.format(trigger_commit_timestamp,
     #                                                                                 base_branch)
     git_command = 'git rev-list -n 1 --skip 1 --before="{}" {}'.format(
         trigger_commit_timestamp, base_branch)
     result, _, _ = ShellWrapper.run_commands(cd_command,
                                              git_command,
                                              stdout=subprocess.PIPE,
                                              shell=True)
     return result
Beispiel #4
0
def gen_script(build_sh_path, job_number, reproducing_dir):
    """
    Invoke travis-build to generate the build script.
    """
    # travis_command = '/home/anandsaw/.travis/travis-build/bin/travis compile {} > {}'.format(job_number, build_sh_path)
    travis_command = '/Users/anandsaw/.travis/travis-build/bin/travis compile {} > {}'.format(
        job_number, build_sh_path)
    print("Creating travis build script with command: " + travis_command)
    cd_command = 'cd {}'.format(reproducing_dir)
    _, stderr, returncode = ShellWrapper.run_commands(cd_command,
                                                      travis_command,
                                                      stdout=subprocess.PIPE,
                                                      stderr=subprocess.PIPE,
                                                      shell=True)
    if returncode != 0:
        raise ValueError(
            'Encountered an error while generating the build script with travis-build: {}.'
            .format(stderr))
Beispiel #5
0
    def clone_repo(repo: str) -> bool:
        # We use the git clone exit code to determine if the clone succeeded. But we need to distinguish between fatal
        # errors (repository not found) and circumstances that prevent cloning (clone destination directory already
        # exists and is not empty). But git returns the same exit code for both errors and unexpected events. So, in
        # order to make the distinction, we manually check for cases like the preexistence of the clone destination.
        repo_path = Utils._canonical_repo_path(repo)
        if os.path.isdir(repo_path) and os.listdir(repo_path):
            # The clone destination directory already exists, so we can return early and indicate to the caller that the
            # clone succeeded.
            log.info('Clone of', repo, 'seems to already exist.')
            return True

        clone_command = 'git clone https://github.com/{}.git {} > /dev/null 2>&1'.format(
            repo, repo_path)
        log.info('Cloning', repo, 'into', repo_path)
        _, _, returncode = ShellWrapper.run_commands(clone_command,
                                                     stdout=subprocess.PIPE,
                                                     shell=True)
        return returncode == 0
Beispiel #6
0
 def get_latest_commit_for_repo(repo: str) -> str:
     repo_path = Utils._canonical_repo_path(repo)
     cd_command = 'cd {}'.format(repo_path)
     git_command = 'git rev-parse HEAD'
     result, _, _ = ShellWrapper.run_commands(cd_command, git_command, stdout=subprocess.PIPE, shell=True)
     return result
Beispiel #7
0
 def get_parents_of_commit(repo: str, commit: str, base_branch: str) -> Optional[str]:
     repo_path = Utils._canonical_repo_path(repo)
     cd_command = 'cd {}'.format(repo_path)
     git_command = 'git rev-list {}..master --first-parent --reverse'.format(commit)
     result, _, _ = ShellWrapper.run_commands(cd_command, git_command, stdout=subprocess.PIPE, shell=True)
     return result
Beispiel #8
0
 def remove_current_task_dir(self):
     command = 'rm -rf {}'.format(self.config.current_task_dir)
     log.debug(command)
     ShellWrapper.run_commands(command, shell=True)
Beispiel #9
0
 def remove_workspace_dir(self):
     log.info('Removing workspace directory.')
     command = 'rm -rf {} 2> /dev/null'.format(self.config.workspace_dir)
     ShellWrapper.run_commands(command, shell=True)
Beispiel #10
0
 def clean_workspace_job_dir(self, job):
     log.info('cleaning workspace job directory.')
     command = 'rm -rf {}'.format(self.get_workspace_sha_dir(job))
     ShellWrapper.run_commands(command, shell=True)
Beispiel #11
0
 def remove_project_repos_dir(self):
     log.info('Removing project_repos directory.')
     command = 'rm -rf {} 2> /dev/null'.format(self.config.stored_repos_dir)
     ShellWrapper.run_commands(command, shell=True)
Beispiel #12
0
 def travis_show(repo: str, build_num: str) -> str:
     show_command = ' '.join(['travis show --repo', repo, build_num])
     result, _, _ = ShellWrapper.run_commands(show_command,
                                              stdout=subprocess.PIPE,
                                              shell=True)
     return result
Beispiel #13
0
def docker_run(image_tag, use_sandbox, use_pipe_stdin, use_rm):
    assert isinstance(image_tag, str) and not image_tag.isspace()
    assert isinstance(use_sandbox, bool)
    assert isinstance(use_pipe_stdin, bool)
    assert isinstance(use_rm, bool)

    # First, try to pull the image.
    ok, image_location = docker_pull(image_tag)
    if not ok:
        return False

    # Communicate progress to the user.
    host_sandbox = _default_host_sandbox()
    container_sandbox = CONTAINER_SANDBOX_DEFAULT
    if use_sandbox:
        if not os.path.exists(host_sandbox):
            log.info('Creating', host_sandbox, 'as the host sandbox.')
            os.makedirs(host_sandbox, exist_ok=True)
        log.info('Binding host sandbox', host_sandbox,
                 'to container directory', container_sandbox)

    # Communicate progress to the user.
    if use_pipe_stdin:
        log.info(
            'Entering the container and executing the contents of stdin inside the container.'
        )
    else:
        log.info('Entering the container.')

    if use_rm:
        log.info('The container will be cleaned up after use.')

    # Prepare the arguments for the docker run command.
    volume_args = ['-v', '{}:{}'.format(host_sandbox, container_sandbox)
                   ] if use_sandbox else []
    # The -t option must not be used in order to use a heredoc.
    input_args = ['-i'] if use_pipe_stdin else ['-i', '-t']
    subprocess_input = sys.stdin.read() if use_pipe_stdin else None
    subprocess_universal_newlines = use_pipe_stdin
    rm_args = ['--rm'] if use_rm else []
    # If we're using a shared directory, we need to modify the start script to change the permissions of the shared
    # directory on the container side. However, this will also change the permissions on the host side.
    script_args = [SCRIPT_DEFAULT]
    if use_sandbox:
        start_command = '"sudo chmod -R 777 {} && cd {} && umask 000 && cd .. && {}"'.format(
            container_sandbox, container_sandbox, SCRIPT_DEFAULT)
        # These arguments represent a command of the following form:
        # /bin/bash -c "sudo chmod 777 <container_sandbox> && cd <container_sandbox> && umask 000 && /bin/bash"
        # So bash will execute chmod and umask and then start a new bash shell. From the user's perspective, the chmod
        # and umask commands happen transparently. That is, the user only sees the final new bash shell.
        script_args = [SCRIPT_DEFAULT, '-c', start_command]

    # Try to run the image.
    # The tail arguments must be at the end of the command.
    tail_args = [image_location] + script_args
    args = ['sudo', 'docker', 'run', '--privileged'
            ] + rm_args + volume_args + input_args + tail_args
    command = ' '.join(args)
    print(command)
    _, _, returncode = ShellWrapper.run_commands(
        command,
        input=subprocess_input,
        universal_newlines=subprocess_universal_newlines,
        shell=True)
    return returncode == 0
Beispiel #14
0
 def fetch_pr_data(self, job):
     owner, project_name = job.repo.split('/')
     # owner_dir = self.get_repo_owner_dir(owner)
     command = 'cd {} ;'.format(self.get_stored_repo_path(job))
     command += 'git fetch origin refs/pull/*/head:refs/remotes/origin/pr/* ;'
     ShellWrapper.run_commands(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
Beispiel #15
0
 def is_travis_installed():
     command = 'travis'
     result, _, _ = ShellWrapper.run_commands(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
     return 'Usage: travis COMMAND' in result
Beispiel #16
0
 def remove_image_in_shell(full_image_name):
     log.info('Removing a Docker image.')
     command = 'docker rmi -f {}'.format(full_image_name)
     _, _, returncode = ShellWrapper.run_commands(command, shell=True)
     return returncode
Beispiel #17
0
 def remove_all_images():
     log.info('Removing all containers and Docker images (except Travis images).')
     command = 'docker rm $(docker ps -a -q); docker rmi -f $(docker images -a | grep -v "travis")'
     ShellWrapper.run_commands(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True)
Beispiel #18
0
 def travis_history(repo: str, history_file_path: str):
     history_command = ' '.join(
         ['travis history --all --date -r', repo, '>', history_file_path])
     ShellWrapper.run_commands(history_command,
                               stdout=subprocess.PIPE,
                               shell=True)