From c4507dbeb685b6dfc6a3e3bd9f65dbf444e9c06e Mon Sep 17 00:00:00 2001 From: Tuschl Date: Wed, 12 Aug 2020 12:10:15 +0200 Subject: [PATCH 1/5] Add support using Gitlab's numerical project ID --- gitlab-manager | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gitlab-manager b/gitlab-manager index 4e56e8f..95a06a3 100755 --- a/gitlab-manager +++ b/gitlab-manager @@ -126,7 +126,10 @@ if __name__ == '__main__': print(e) exit() try: - projects = gl.projects.list(search=args.project) + if args.project.isdecimal(): + projects = [gl.projects.get(args.project)] + else: + projects = gl.projects.list(search=args.project) except exceptions.MissingSchema: log.error("Error with the URL defined") exit() From 346986f3feaa228a88536e4d0eac4defbe4b4b23 Mon Sep 17 00:00:00 2001 From: Tuschl Date: Wed, 12 Aug 2020 14:11:14 +0200 Subject: [PATCH 2/5] Disable pagination for listing MRs --- gitlab-manager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab-manager b/gitlab-manager index 95a06a3..577b242 100755 --- a/gitlab-manager +++ b/gitlab-manager @@ -21,7 +21,7 @@ class MergeRequest: def list_mrs(project, wip): print("\nHere is the list of MRs for your chosen project:\n") - mrs = project.mergerequests.list(state='opened', order_by='updated_at', wip=wip) + mrs = project.mergerequests.list(state='opened', order_by='updated_at', wip=wip, all=True) all_mr = "" for mr in mrs: current = MergeRequest(mr) From 8bdbbf4367b33872573873e05d5548bf4fc435e3 Mon Sep 17 00:00:00 2001 From: Tuschl Date: Wed, 12 Aug 2020 14:12:56 +0200 Subject: [PATCH 3/5] Add argument for printing list of MR ids only --- gitlab-manager | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/gitlab-manager b/gitlab-manager index 577b242..7c3c798 100755 --- a/gitlab-manager +++ b/gitlab-manager @@ -16,16 +16,20 @@ class MergeRequest: self.Label = "[{}]".format(mr.labels[0]) - def print_mr(self): - return "### {}: {}\n\n{}\n\n * by: {}\n\n * Merge Request ID:{}\n".format(self.Label, self.Title, self.Description, self.Author, self.Id) + def print_mr(self, ids_only=False): + if ids_only: + return f"{self.Id} " + else: + return "### {}: {}\n\n{}\n\n * by: {}\n\n * Merge Request ID:{}\n".format(self.Label, self.Title, self.Description, self.Author, self.Id) -def list_mrs(project, wip): - print("\nHere is the list of MRs for your chosen project:\n") +def list_mrs(project, wip, ids_only=False): + if not ids_only: + print("\nHere is the list of MRs for your chosen project:\n") mrs = project.mergerequests.list(state='opened', order_by='updated_at', wip=wip, all=True) all_mr = "" for mr in mrs: current = MergeRequest(mr) - all_mr = all_mr + "{}\n\n".format(current.print_mr()) + all_mr = all_mr + "{}\n\n".format(current.print_mr(ids_only)) print(all_mr) return all_mr @@ -80,6 +84,8 @@ def init_argparse(): subparsers = mr_group.add_subparsers(dest='action') ls_mr = subparsers.add_parser('ls') + ls_mr.add_argument("--ids", dest='output_ids', action='store_true', + help='print MR ids only') ls_mr.add_argument("--wip", dest='wip', action='store', type=str, help='search wip or not', choices=['yes', 'no']) update_mr = subparsers.add_parser('update') @@ -142,7 +148,7 @@ if __name__ == '__main__': project = projects[0] if args.command == "mr": if args.action == "ls": - list_mrs(project, args.wip) + list_mrs(project, args.wip, args.output_ids) if args.action == "update": update_mr(project, args.mr_id, args.label, args.tag) if args.command == "changelog": From e6ae86fdb4cda7b1d94a801f1b40a72895ec2076 Mon Sep 17 00:00:00 2001 From: Tuschl Date: Wed, 12 Aug 2020 15:18:57 +0200 Subject: [PATCH 4/5] Add support for updating multiple MRs and preserving existing labels --- gitlab-manager | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/gitlab-manager b/gitlab-manager index 7c3c798..95353e9 100755 --- a/gitlab-manager +++ b/gitlab-manager @@ -33,24 +33,26 @@ def list_mrs(project, wip, ids_only=False): print(all_mr) return all_mr -def update_mr(project, mr_id, label=None, tag=None): - mr = project.mergerequests.get(mr_id) - if label is not None: - mr.labels = [label] - - if tag is not None: - milestones = project.milestones.list(state='active', search=tag) - if len(milestones) == 1: - milestone = milestones[0] - elif len(milestones) == 0: - print("create milestone") - milestone = project.milestones.create({'title': tag}) - else: - print("please verify your tag") - exit() - mr.milestone_id = milestone.id - mr.save() - +def update_mr(project, mr_ids, label=None, tag=None, keep_existing_labels=False): + mrs = project.mergerequests.list(query_parameters={'iids[]': ','.join(mr_ids)}) + for mr in mrs: + if label is not None and label not in mr.labels: + if keep_existing_labels: + mr.labels.append(label) + else: + mr.labels = [label] + if tag is not None: + milestones = project.milestones.list(state='active', search=tag) + if len(milestones) == 1: + milestone = milestones[0] + elif len(milestones) == 0: + print("create milestone") + milestone = project.milestones.create({'title': tag}) + else: + print("please verify your tag") + exit() + mr.milestone_id = milestone.id + mr.save() def print_changelog(project, tag, push=False): print("\nYour changelog for {} on Project {}:\n".format(tag, project.name)) @@ -89,11 +91,15 @@ def init_argparse(): ls_mr.add_argument("--wip", dest='wip', action='store', type=str, help='search wip or not', choices=['yes', 'no']) update_mr = subparsers.add_parser('update') - update_mr.add_argument('mr_id') + update_mr.add_argument('mr_ids', nargs='+', + help='one or more MR ids') update_mr.add_argument("--label", dest='label', action='store', type=str, help='put a speficic label ex: Feature') update_mr.add_argument("--tag", dest='tag', action='store', type=str, help='put a speficic tag ex: 0.2.0') + update_mr.add_argument("--keep-existing-labels", dest='keep_existing_labels', + action='store_true', + help='do not replace labels') subparsers = changelog_group.add_subparsers(dest='action') print_changelog = subparsers.add_parser('print', help='print changelog') @@ -150,7 +156,7 @@ if __name__ == '__main__': if args.action == "ls": list_mrs(project, args.wip, args.output_ids) if args.action == "update": - update_mr(project, args.mr_id, args.label, args.tag) + update_mr(project, args.mr_ids, args.label, args.tag, args.keep_existing_labels) if args.command == "changelog": push = False if args.action == "push": From 8b61e53d1fc49ea0569658f2ed3bc4891414f1a1 Mon Sep 17 00:00:00 2001 From: Tuschl Date: Wed, 12 Aug 2020 15:41:29 +0200 Subject: [PATCH 5/5] Add support for using Gitlab labels for entry type For our workflow we use labels with a common prefix wit a separator (e.g. 'CL:') for specifying the type of CL entry. This commit adds support for using the label text after the separator for the changelog entry type. For this, two arguments are added for specifying the prefix and separator (with defaults `CL` and `:`). This information is passed on to the output logic. To ease this, the `args` object is now passed directly to the action functions. This avoids defining redundant function arguments. --- gitlab-manager | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/gitlab-manager b/gitlab-manager index 95353e9..cbd27fa 100755 --- a/gitlab-manager +++ b/gitlab-manager @@ -6,48 +6,54 @@ import logging as log from requests import exceptions class MergeRequest: - def __init__(self, mr): + def __init__(self, mr, label_prefix='CL', label_sep=':'): self.Id = mr.iid self.Author = mr.author['username'] self.Title = mr.title self.Description = mr.description self.Label = "info" + self.LabelPrefix = label_prefix + self.LabelSeparator = label_sep if len(mr.labels) == 1: self.Label = "[{}]".format(mr.labels[0]) - - + else: + for label in mr.labels: + if label.startswith(self.LabelPrefix+self.LabelSeparator): + self.Label = f"[{label.split(self.LabelSeparator, maxsplit=1)[-1].strip()}]" + break + def print_mr(self, ids_only=False): if ids_only: return f"{self.Id} " else: return "### {}: {}\n\n{}\n\n * by: {}\n\n * Merge Request ID:{}\n".format(self.Label, self.Title, self.Description, self.Author, self.Id) -def list_mrs(project, wip, ids_only=False): - if not ids_only: +def list_mrs(project, args): + if not args.output_ids: print("\nHere is the list of MRs for your chosen project:\n") - mrs = project.mergerequests.list(state='opened', order_by='updated_at', wip=wip, all=True) + mrs = project.mergerequests.list(state='opened', order_by='updated_at', wip=args.wip, all=True) all_mr = "" for mr in mrs: - current = MergeRequest(mr) - all_mr = all_mr + "{}\n\n".format(current.print_mr(ids_only)) + current = MergeRequest(mr, args.cl_type_label_prefix, args.cl_type_label_separator) + all_mr = all_mr + "{}\n\n".format(current.print_mr(args.output_ids)) print(all_mr) return all_mr -def update_mr(project, mr_ids, label=None, tag=None, keep_existing_labels=False): - mrs = project.mergerequests.list(query_parameters={'iids[]': ','.join(mr_ids)}) +def update_mr(project, args): + mrs = project.mergerequests.list(query_parameters={'iids[]': ','.join(args.mr_ids)}) for mr in mrs: - if label is not None and label not in mr.labels: - if keep_existing_labels: - mr.labels.append(label) + if args.label is not None and args.label not in mr.labels: + if args.keep_existing_labels: + mr.labels.append(args.label) else: - mr.labels = [label] - if tag is not None: - milestones = project.milestones.list(state='active', search=tag) + mr.labels = [args.label] + if args.tag is not None: + milestones = project.milestones.list(state='active', search=args.tag) if len(milestones) == 1: milestone = milestones[0] elif len(milestones) == 0: print("create milestone") - milestone = project.milestones.create({'title': tag}) + milestone = project.milestones.create({'title': args.tag}) else: print("please verify your tag") exit() @@ -79,6 +85,12 @@ def init_argparse(): help='Specify gitlab url ex: https://gitlab.com') optionals.add_argument("--gitlab-token", dest='gitlab_token', action='store', type=str, help='Specify private gitlab token') + optionals.add_argument("--changelog-type-label-prefix", dest='cl_type_label_prefix', + action='store', type=str, default='CL', + help='Gitlab label prefix for changelog entry types') + optionals.add_argument("--changelog-type-label-separator", dest='cl_type_label_separator', + action='store', type=str, default=':', + help='seperator token of Gitlab label prefixes for changelog entry types') subparsers = parser.add_subparsers(dest='command') mr_group = subparsers.add_parser('mr') @@ -154,9 +166,9 @@ if __name__ == '__main__': project = projects[0] if args.command == "mr": if args.action == "ls": - list_mrs(project, args.wip, args.output_ids) + list_mrs(project, args) if args.action == "update": - update_mr(project, args.mr_ids, args.label, args.tag, args.keep_existing_labels) + update_mr(project, args) if args.command == "changelog": push = False if args.action == "push":