From d5c77c049049cd024b2367aeb2ee8e4a7246d089 Mon Sep 17 00:00:00 2001 From: Andre Anjos <andre.dos.anjos@gmail.com> Date: Fri, 23 Apr 2021 10:15:02 +0200 Subject: [PATCH] [scripts.settings] New CLI to bulk edit project settings --- bob/devtools/scripts/settings.py | 157 +++++++++++++++++++++++++++++++ setup.py | 1 + 2 files changed, 158 insertions(+) create mode 100644 bob/devtools/scripts/settings.py diff --git a/bob/devtools/scripts/settings.py b/bob/devtools/scripts/settings.py new file mode 100644 index 00000000..32e1df6f --- /dev/null +++ b/bob/devtools/scripts/settings.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python + + +import os +import click +import gitlab + +from ..log import echo_warning, echo_info, echo_normal +from ..log import get_logger +from ..log import verbosity_option +from ..release import get_gitlab_instance +from . import bdt +from .runners import ( + _get_project, + _get_projects_from_file, + _get_projects_from_group, +) + +logger = get_logger(__name__) + + +def _change_settings(project, info, dry_run): + """Updates the project settings using ``info``""" + + name = f"{project.namespace['name']}/{project.name}" + echo_normal(f"Changing {name}...") + + if info.get("archive") is not None: + if info["archive"]: + echo_info(" -> archiving") + if not dry_run: + project.archive() + else: + echo_info(" -> unarchiving") + if not dry_run: + project.unarchive() + + if info.get("description") is not None: + echo_info(f" -> set description to '{info['description']}'") + if not dry_run: + project.description = info["description"] + project.save() + + if info.get("avatar") is not None: + echo_info(f" -> setting avatar to '{info['avatar']}'") + if not dry_run: + project.avatar = open(info["avatar"], "rb") + project.save() + + +@click.command( + epilog=""" +Examples: + + 1. List settings in a gitlab project (bob/bob.devtools): + + $ bdt gitlab settings bob/bob.devtools + + + 2. Simulates an update to the project description: + + $ bdt gitlab settings --description="new description" --dry-run bob/bob.devtools + +""" +) +@click.argument("projects", nargs=-1, required=True) +@click.option( + "-a", + "--avatar", + default=None, + type=click.Path(file_okay=True, dir_okay=False, exists=True), + help="Set this to update the project icon (avatar)", +) +@click.option( + "-D", + "--description", + default=None, + type=str, + help="Set this to update the project description", +) +@click.option( + "-A", + "--archive/--unarchive", + default=None, + help="Set this to archive or unarchive a project", +) +@click.option( + "-d", + "--dry-run/--no-dry-run", + default=False, + help="Only goes through the actions, but does not execute them " + "(combine with the verbosity flags - e.g. ``-vvv``) to enable " + "printing to help you understand what will be done", +) +@verbosity_option() +@bdt.raise_on_error +def settings(projects, avatar, description, archive, dry_run): + """Updates project settings""" + + # if we are in a dry-run mode, let's let it be known + if dry_run: + logger.warn("!!!! DRY RUN MODE !!!!") + logger.warn("Nothing is being changed at Gitlab") + + gl = get_gitlab_instance() + gl_projects = [] + + for target in projects: + + if "/" in target: # it is a specific project + gl_projects.append(_get_project(gl, target)) + + elif os.path.exists(target): # it is a file with project names + gl_projects += _get_projects_from_file(gl, target) + + else: # it is a group - get all projects + gl_projects += _get_projects_from_group(gl, target) + + for k in gl_projects: + + try: + + logger.info( + "Processing project %s (id=%d)", + k.attributes["path_with_namespace"], + k.id, + ) + + info_to_update = {} + + if avatar is not None: + info_to_update["avatar"] = avatar + + if archive is not None: + info_to_update["archive"] = archive + + if description is not None: + info_to_update["description"] = description + + if not info_to_update: + # list current settings + s = f"{k.namespace['name']}/{k.name}" + if k.archived: + s += f" [archived]" + s += f": {k.description}" + echo_normal(s) + + else: + _change_settings(k, info_to_update, dry_run) + + except Exception as e: + logger.error( + "Ignoring project %s (id=%d): %s", + k.attributes["path_with_namespace"], + k.id, + str(e), + ) diff --git a/setup.py b/setup.py index 5bfe0e59..c6eb6bcd 100644 --- a/setup.py +++ b/setup.py @@ -70,6 +70,7 @@ setup( "changelog = bob.devtools.scripts.changelog:changelog", "lasttag = bob.devtools.scripts.lasttag:lasttag", "runners = bob.devtools.scripts.runners:runners", + "settings = bob.devtools.scripts.settings:settings", "jobs = bob.devtools.scripts.jobs:jobs", "visibility = bob.devtools.scripts.visibility:visibility", "getpath = bob.devtools.scripts.getpath:getpath", -- GitLab