Beispiel #1
0
class BranchesProcessor(AbstractProcessor):
    def __init__(self, gitlab: GitLab, strict: bool):
        super().__init__("branches")
        self.__branch_protector = BranchProtector(gitlab, strict)

    def _process_configuration(self, project_and_group: str, configuration: dict):
        for branch in sorted(configuration["branches"]):
            self.__branch_protector.protect_branch(
                project_and_group, configuration, branch
            )
Beispiel #2
0
 def __init__(self, gitlab: GitLab, config: Configuration, strict: bool):
     super().__init__("files")
     self.gitlab = gitlab
     self.config = config
     self.strict = strict
     self.branch_protector = BranchProtector(gitlab, strict)
Beispiel #3
0
class FilesProcessor(AbstractProcessor):
    def __init__(self, gitlab: GitLab, config: Configuration, strict: bool):
        super().__init__("files")
        self.gitlab = gitlab
        self.config = config
        self.strict = strict
        self.branch_protector = BranchProtector(gitlab, strict)

    def _process_configuration(self, project_and_group: str,
                               configuration: dict):
        for file in sorted(configuration["files"]):
            logging.debug("Processing file '%s'...", file)

            if configuration.get("files|" + file + "|skip"):
                logging.debug("Skipping file '%s'", file)
                continue

            all_branches = self.gitlab.get_branches(project_and_group)
            if configuration["files"][file]["branches"] == "all":
                branches = sorted(all_branches)
            elif configuration["files"][file]["branches"] == "protected":
                protected_branches = self.gitlab.get_protected_branches(
                    project_and_group)
                branches = sorted(protected_branches)
            else:
                branches = []
                for branch in configuration["files"][file]["branches"]:
                    if branch in all_branches:
                        branches.append(branch)
                    else:
                        message = f"! Branch '{branch}' not found, not processing file '{file}' in it"
                        if self.strict:
                            cli_ui.error(message)
                            sys.exit(EXIT_INVALID_INPUT)
                        else:
                            cli_ui.warning(message)

            for branch in branches:
                cli_ui.debug(f"Processing file '{file}' in branch '{branch}'")

                # unprotect protected branch temporarily for operations below
                if configuration.get("branches|" + branch + "|protected"):
                    logging.debug(
                        "> Temporarily unprotecting the branch for managing files in it..."
                    )
                    self.gitlab.unprotect_branch(project_and_group, branch)

                if configuration.get("files|" + file + "|delete"):
                    try:
                        self.gitlab.get_file(project_and_group, branch, file)
                        logging.debug("Deleting file '%s' in branch '%s'",
                                      file, branch)
                        self.gitlab.delete_file(
                            project_and_group,
                            branch,
                            file,
                            self.get_commit_message_for_file_change(
                                "delete",
                                configuration.get("files|" + file +
                                                  "|skip_ci"),
                            ),
                        )
                    except NotFoundException:
                        logging.debug(
                            "Not deleting file '%s' in branch '%s' (already doesn't exist)",
                            file,
                            branch,
                        )
                else:
                    # change or create file

                    if configuration.get("files|" + file +
                                         "|content") and configuration.get(
                                             "files|" + file + "|file"):
                        cli_ui.error(
                            f"File '{file}' in '{project_and_group}' has both `content` and `file` set - "
                            "use only one of these keys.")
                        sys.exit(EXIT_INVALID_INPUT)
                    elif configuration.get("files|" + file + "|content"):
                        new_content = configuration.get("files|" + file +
                                                        "|content")
                    else:
                        path_in_config = Path(
                            configuration.get("files|" + file + "|file"))
                        if path_in_config.is_absolute():
                            path = path_in_config.read_text()
                        else:
                            # relative paths are relative to config file location
                            path = Path(
                                os.path.join(self.config.config_dir,
                                             str(path_in_config)))
                        new_content = path.read_text()

                    if configuration.get("files|" + file + "|template", True):
                        new_content = self.get_file_content_as_template(
                            new_content,
                            project_and_group,
                            **configuration.get("files|" + file + "|jinja_env",
                                                dict()),
                        )

                    try:
                        current_content = self.gitlab.get_file(
                            project_and_group, branch, file)
                        if current_content != new_content:
                            if configuration.get("files|" + file +
                                                 "|overwrite"):
                                logging.debug(
                                    "Changing file '%s' in branch '%s'", file,
                                    branch)
                                self.gitlab.set_file(
                                    project_and_group,
                                    branch,
                                    file,
                                    new_content,
                                    self.get_commit_message_for_file_change(
                                        "change",
                                        configuration.get("files|" + file +
                                                          "|skip_ci"),
                                    ),
                                )
                            else:
                                logging.debug(
                                    "Not changing file '%s' in branch '%s' "
                                    "(overwrite flag not set)",
                                    file,
                                    branch,
                                )
                        else:
                            logging.debug(
                                "Not changing file '%s' in branch '%s' (it's content is already"
                                " as provided)",
                                file,
                                branch,
                            )
                    except NotFoundException:
                        logging.debug("Creating file '%s' in branch '%s'",
                                      file, branch)
                        self.gitlab.add_file(
                            project_and_group,
                            branch,
                            file,
                            new_content,
                            self.get_commit_message_for_file_change(
                                "add",
                                configuration.get("files|" + file +
                                                  "|skip_ci")),
                        )

                # protect branch back after above operations
                if configuration.get("branches|" + branch + "|protected"):
                    logging.debug("> Protecting the branch again.")
                    self.branch_protector.protect_branch(
                        project_and_group, configuration, branch)
                if configuration.get("files|" + file + "|only_first_branch"):
                    cli_ui.debug(
                        "Skipping other branches for this file, as configured."
                    )
                    break

    def get_file_content_as_template(self, template, project_and_group,
                                     **kwargs):
        # Use jinja with variables project and group
        rtemplate = Environment(loader=FileSystemLoader("."),
                                autoescape=True).from_string(template)
        return rtemplate.render(
            project=self.get_project(project_and_group),
            group=self.get_group(project_and_group),
            **kwargs,
        )

    @staticmethod
    def get_commit_message_for_file_change(operation, skip_build):

        # add '[skip ci]' to commit message to skip CI job, as documented at
        # https://docs.gitlab.com/ee/ci/yaml/README.html#skipping-jobs
        skip_build_str = " [skip ci]" if skip_build else ""

        return "Automated %s made by gitlabform%s" % (operation,
                                                      skip_build_str)

    @staticmethod
    def get_group(project_and_group):
        return re.match("(.*)/.*", project_and_group).group(1)

    @staticmethod
    def get_project(project_and_group):
        return re.match(".*/(.*)", project_and_group).group(1)
Beispiel #4
0
 def __init__(self, gitlab: GitLab, strict: bool):
     super().__init__("branches")
     self.__branch_protector = BranchProtector(gitlab, strict)