-
Notifications
You must be signed in to change notification settings - Fork 1
/
cli.py
231 lines (190 loc) · 7.14 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
"""
CLI implementation for Concierge.
"""
import click
from gitlab.exceptions import GitlabError
from requests.exceptions import RequestException
from .constants import GITLAB_DEFAULT_URI, GITLAB_PERMISSIONS
from .manager import (
GroupManager, MergeRequestManager, ProjectManager, TopicManager
)
def debug_option(*_, **kwargs):
"""
Add a ``--debug`` option to print out a stacktrace when an error occurs.
"""
def callback(ctx, _, value):
if not value or ctx.resilient_parsing:
return
abort.debug = True
kwargs.setdefault("is_flag", True)
kwargs.setdefault("expose_value", False)
kwargs.setdefault("help", "Show debug information on errors.")
kwargs["callback"] = callback
return click.decorators.option("--debug", **kwargs)
@click.group()
@click.version_option()
@debug_option()
def concierge_cli():
"""Concierge repository projects management CLI."""
@concierge_cli.group()
@click.pass_context
@click.option('--uri', envvar='CONCIERGE_GITLAB_URI',
default=GITLAB_DEFAULT_URI, show_default=True,
help='Location of the GitLab host. Alternatively, you may set'
' the CONCIERGE_GITLAB_URI environment variable, or'
' specify a host in a configuration file (see'
' https://python-gitlab.readthedocs.io > CLI usage >'
' Configuration > Files).')
@click.option('--token', envvar='CONCIERGE_GITLAB_TOKEN',
help='Optional access token (access is anonymous if none is'
' supplied). Alternatively, you may set the'
' CONCIERGE_GITLAB_TOKEN environment variable.')
@click.option('--insecure', is_flag=True, default=False,
help='Disable SSL certificate check and related warnings.')
@debug_option()
def gitlab(ctx, uri, token, insecure):
"""GitLab sub-commands."""
ctx.obj = {"uri": uri, "token": token, "insecure": insecure}
@gitlab.command()
@click.pass_context
@click.argument('group-project-filter', default='/')
@click.option('--empty/--no-empty', default=False,
help='Select projects with an empty (or non-empty) topic list.')
@click.option('--set-topic', multiple=True,
help='Use multiple times to set more than one topic.'
' Use "" to clear topics.')
@debug_option()
def topics(ctx, group_project_filter, empty, set_topic):
"""
List and manage topics on GitLab projects.
Filter syntax:
- foo/bar ... projects that have "bar" in their name,
in groups that have "foo" in their name
- foo/ ... filter for groups only, match any project
- /bar ... filter for projects only, match any group
"""
try:
group_filter, project_filter = group_project_filter.split('/')
except ValueError:
group_filter, project_filter = '', group_project_filter
topic_manager = TopicManager(
uri=ctx.obj.get('uri'),
token=ctx.obj.get('token'),
insecure=ctx.obj.get('insecure'),
group_filter=group_filter,
project_filter=project_filter,
empty=empty,
)
if set_topic:
topic_manager.set(list(set_topic))
else:
topic_manager.show()
@gitlab.command()
@click.pass_context
@click.argument('group-project-filter', default='/')
@click.option('--label', multiple=True,
help='Use multiple times to filter with more than one label.')
@click.option('--merge', default='no', show_default=True,
type=click.Choice(['yes', 'no', 'automatic']),
help='Merge all identified merge requests. With "yes", will '
'ask for confirmation interactively on each MR.')
@debug_option()
def mrs(ctx, group_project_filter, label, merge):
"""
List and manage merge requests of GitLab projects.
Filter syntax:
- foo/bar ... projects that have "bar" in their name,
in groups that have "foo" in their name
- foo/ ... filter for groups only, match any project
- /bar ... filter for projects only, match any group
"""
try:
group_filter, project_filter = group_project_filter.split('/')
except ValueError:
group_filter, project_filter = '', group_project_filter
mr_manager = MergeRequestManager(
uri=ctx.obj.get('uri'),
token=ctx.obj.get('token'),
insecure=ctx.obj.get('insecure'),
group_filter=group_filter,
project_filter=project_filter,
labels=list(label),
merge_style=merge,
)
if merge in ['yes', 'automatic']:
mr_manager.merge_all()
else:
mr_manager.show()
@gitlab.command()
@click.pass_context
@click.argument('group-project-filter', default='/')
@click.option('--topic', multiple=True,
help='Use multiple times to filter with more than one topic.')
@debug_option()
def projects(ctx, group_project_filter, topic):
"""
List projects on GitLab, optionally by topic, ignoring archived ones.
Filter syntax:
- foo/bar ... projects that have "bar" in their name,
in groups that have "foo" in their name
- foo/ ... filter for groups only, match any project
- /bar ... filter for projects only, match any group
"""
try:
group_filter, project_filter = group_project_filter.split('/')
except ValueError:
group_filter, project_filter = '', group_project_filter
project_manager = ProjectManager(
uri=ctx.obj.get('uri'),
token=ctx.obj.get('token'),
insecure=ctx.obj.get('insecure'),
group_filter=group_filter,
project_filter=project_filter,
topic_list=list(topic),
)
project_manager.show()
@gitlab.command()
@click.pass_context
@click.argument('username')
@click.option('--group-filter', default='',
help='List only groups that match or contain a specific name.')
@click.option('--member/--no-member', default=True,
help='Select groups where user is (not) a member of.')
@click.option('--set-permission',
type=click.Choice(GITLAB_PERMISSIONS.keys()),
help='Set user permission level on all matching groups.')
@debug_option()
def groups(ctx, username, group_filter, member, set_permission):
"""
Manage the access level for a user on GitLab groups.
"""
group_manager = GroupManager(
uri=ctx.obj.get('uri'),
token=ctx.obj.get('token'),
insecure=ctx.obj.get('insecure'),
group_filter=group_filter,
is_member=member,
username=username,
)
if set_permission:
group_manager.set(set_permission)
else:
group_manager.show()
def main():
"""Main entry point for the CLI."""
try:
concierge_cli()
except GitlabError as err:
abort(err, f'{err.error_message} 💣 GitLab error')
except RequestException as req:
abort(req, f'{req} 💣 Communication error')
except Exception as other: # pylint: disable=broad-except
abort(other, f'{other} 💣 Application error')
def abort(error, message):
"""Print an error and stops program execution."""
if abort.debug:
raise error
raise SystemExit(f"{message}. Aborting. (Try --debug)")
abort.debug = False
if __name__ == '__main__':
main()