Skip to content
Snippets Groups Projects
gitlab-ci-vars-updater.py 4.04 KiB
import argparse

import gitlab
import yaml


def load_file(file_path):
    try:
        with open(file_path, mode="rt", encoding="utf-8") as file:
            return yaml.safe_load(file)
    except FileNotFoundError:
        print(f"Error: Configuration file '{file_path}' not found.")
        exit(1)


# Function to create or update a GitLab CI/CD variable
def create_or_update_variable(project, var_dict):
    key = var_dict.get("key")
    scope = var_dict.get("environment_scope", "*")
    p_variable = None

    DEFAULTS = {
        "variable_type": "env_var",
        "hidden": False,
        "protected": False,
        "masked": False,
        "environment_scope": "*",
        "raw": False,
        "description": None,
    }

    # Merge defaults with var_dict
    var_dict = {**DEFAULTS, **var_dict}

    # Fetch a variable with matching key and scope
    try:
        all_vars = project.variables.list(get_all=True)
        for var in all_vars:
            if var.key == key and var.environment_scope == scope:
                p_variable = var
                break
    except gitlab.exceptions.GitlabGetError:
        print("Variable not found")
        exit(1)

    # Check if the variable exists and same as input
    if p_variable is not None:
        if p_variable.asdict() != var_dict:
            # if not same update the project variable
            print(f"Updating {p_variable.attributes['key']}")
            p_variable.delete()
            return project.variables.create(var_dict)
        else:
            print(f"variable {var_dict["key"]} already exists")
    # Create variable if it doesn't exist in the project
    else:
        print(f"Creating variable {var_dict["key"]}")
        return project.variables.create(var_dict)


def get_pipeline_vars_by_key(sched_pipeline, key_name):
    p_vars = sched_pipeline.attributes["variables"]
    for p_variable in p_vars:
        if p_variable.get("key") == key_name:
            return p_variable


# Function to create or update a schedule pipeline variable
def create_or_update_sched_vars(sched_pipeline, var_dict):
    # Check if the variable exists in the sched pipeline
    p_variable = get_pipeline_vars_by_key(sched_pipeline, var_dict["key"])
    if p_variable:
        # Check if the attributes are the same
        if p_variable != var_dict:
            # If not update the value in the project
            sched_pipeline.variables.delete(p_variable["key"])
            sched_pipeline.variables.create(var_dict)
        else:
            print(f"variable {var_dict["key"]} already exists")
    # Create variable if it doesn't exist in the project
    else:
        print(f"Creating variable {var_dict["key"]}")
        return sched_pipeline.variables.create(var_dict)


def main():
    # Setup argument parser
    parser = argparse.ArgumentParser(description="GitLab CI/CD Variables Updater")
    parser.add_argument(
        "--config_file",
        type=str,
        default="gitlab.ini",
        required=True,
        help="Path to the configuration file (default: gitlab.ini)",
    )
    parser.add_argument(
        "--var_file",
        type=str,
        default="ci-variables.yaml",
        help="Path to the CI vars file (default: ci-variables.yaml)",
    )
    parser.add_argument(
        "--project_name",
        type=str,
        required=True,
        help="Gitlab project name with namespace",
    )
    parser.add_argument(
        "--sched_pipeline_id",
        type=int,
        help="Gitlab project scheduled pipeline ID",
    )

    # Parse the arguments
    args = parser.parse_args()

    gl = gitlab.Gitlab.from_config("uabrc", [args.config_file])
    project = gl.projects.get(args.project_name)

    # Load the CI vars file
    var_list = load_file(args.var_file)

    # Create or update all variables
    for var_dict in var_list:
        if not args.sched_pipeline_id:
            create_or_update_variable(project, var_dict)
        else:
            sched_pipeline = project.pipelineschedules.get(args.sched_pipeline_id)
            create_or_update_sched_vars(sched_pipeline, var_dict)


if __name__ == "__main__":
    main()