suite-py 1.41.2__tar.gz → 1.41.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {suite_py-1.41.2 → suite_py-1.41.4}/PKG-INFO +2 -4
  2. {suite_py-1.41.2 → suite_py-1.41.4}/pyproject.toml +2 -4
  3. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/__version__.py +1 -1
  4. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/cli.py +107 -185
  5. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/aggregator.py +3 -5
  6. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/ask_review.py +3 -5
  7. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/batch_job.py +1 -2
  8. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/bump.py +1 -2
  9. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/check.py +3 -5
  10. suite_py-1.41.4/suite_py/commands/context.py +26 -0
  11. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/create_branch.py +1 -2
  12. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/deploy.py +3 -5
  13. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/docker.py +1 -2
  14. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/generator.py +1 -2
  15. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/id.py +1 -2
  16. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/ip.py +1 -2
  17. suite_py-1.41.4/suite_py/commands/login.py +11 -0
  18. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/merge_pr.py +3 -4
  19. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/open_pr.py +4 -5
  20. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/project_lock.py +3 -5
  21. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/release.py +3 -5
  22. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/secret.py +1 -2
  23. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/set_token.py +1 -2
  24. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/status.py +3 -4
  25. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/config.py +1 -3
  26. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/captainhook_handler.py +44 -54
  27. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/metrics_handler.py +8 -6
  28. suite_py-1.41.4/suite_py/lib/handler/okta_handler.py +81 -0
  29. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/logger.py +1 -0
  30. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/metrics.py +4 -2
  31. suite_py-1.41.4/suite_py/lib/oauth.py +156 -0
  32. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/tokens.py +4 -0
  33. suite_py-1.41.2/suite_py/commands/login.py +0 -180
  34. suite_py-1.41.2/suite_py/commands/qa.py +0 -424
  35. suite_py-1.41.2/suite_py/lib/handler/qainit_handler.py +0 -259
  36. {suite_py-1.41.2 → suite_py-1.41.4}/LICENSE-APACHE +0 -0
  37. {suite_py-1.41.2 → suite_py-1.41.4}/LICENSE-MIT +0 -0
  38. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/__init__.py +0 -0
  39. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/__init__.py +0 -0
  40. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/commands/common.py +0 -0
  41. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/__init__.py +0 -0
  42. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/__init__.py +0 -0
  43. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/aws_handler.py +0 -0
  44. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/changelog_handler.py +0 -0
  45. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/drone_handler.py +0 -0
  46. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/frequent_reviewers_handler.py +0 -0
  47. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/git_handler.py +0 -0
  48. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/github_handler.py +0 -0
  49. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/prompt_utils.py +0 -0
  50. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/vault_handler.py +0 -0
  51. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/version_handler.py +0 -0
  52. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/handler/youtrack_handler.py +0 -0
  53. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/requests/__init__.py +0 -0
  54. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/requests/auth.py +0 -0
  55. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/requests/session.py +0 -0
  56. {suite_py-1.41.2 → suite_py-1.41.4}/suite_py/lib/symbol.py +0 -0
  57. {suite_py-1.41.2/suite_py/commands → suite_py-1.41.4/suite_py}/templates/login.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: suite-py
3
- Version: 1.41.2
3
+ Version: 1.41.4
4
4
  Summary:
5
5
  Author: larrywax, EugenioLaghi, michelangelomo
6
6
  Author-email: devops@prima.it
@@ -12,12 +12,10 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: Click (>=7.0)
15
- Requires-Dist: Flask (==1.1.2)
16
15
  Requires-Dist: InquirerPy (>=0.2.0)
17
16
  Requires-Dist: Jinja2 (>=2.11,<3.0.0)
18
17
  Requires-Dist: PyGithub (>=1.57)
19
18
  Requires-Dist: PyYaml (>=5.4)
20
- Requires-Dist: Werkzeug (==2.0.2)
21
19
  Requires-Dist: autoupgrade-prima (>=0.6)
22
20
  Requires-Dist: black (>=22.6,<25.0)
23
21
  Requires-Dist: boto3 (>=1.17.84)
@@ -27,7 +25,7 @@ Requires-Dist: cryptography (==42.0.5)
27
25
  Requires-Dist: halo (>=0.0.28)
28
26
  Requires-Dist: inquirer (==3.1.4)
29
27
  Requires-Dist: itsdangerous (==2.0.1)
30
- Requires-Dist: keyring (>=23.9.1,<25.0.0)
28
+ Requires-Dist: keyring (>=23.9.1,<26.0.0)
31
29
  Requires-Dist: kubernetes (==29.0.0)
32
30
  Requires-Dist: logzero (==1.7.0)
33
31
  Requires-Dist: markupsafe (==2.0.1)
@@ -2,16 +2,14 @@
2
2
  authors = ["larrywax, EugenioLaghi, michelangelomo <devops@prima.it>"]
3
3
  description = ""
4
4
  name = "suite-py"
5
- version = "1.41.2"
5
+ version = "1.41.4"
6
6
 
7
7
  [tool.poetry.dependencies]
8
8
  Click = ">=7.0"
9
- Flask = "==1.1.2"
10
9
  InquirerPy = ">=0.2.0"
11
10
  Jinja2 = ">=2.11,<3.0.0"
12
11
  PyGithub = ">=1.57"
13
12
  PyYaml = ">=5.4"
14
- Werkzeug = "==2.0.2"
15
13
  autoupgrade-prima = ">=0.6"
16
14
  black = ">=22.6,<25.0"
17
15
  boto3 = ">=1.17.84"
@@ -20,7 +18,7 @@ colorama = ">=0.4.3"
20
18
  halo = ">=0.0.28"
21
19
  inquirer = "==3.1.4"
22
20
  itsdangerous = "==2.0.1"
23
- keyring = ">=23.9.1,<25.0.0"
21
+ keyring = ">=23.9.1,<26.0.0"
24
22
  kubernetes = "==29.0.0"
25
23
  logzero = "==1.7.0"
26
24
  markupsafe = "==2.0.1"
@@ -1,2 +1,2 @@
1
1
  # -*- encoding: utf-8 -*-
2
- __version__ = "1.41.2"
2
+ __version__ = "1.41.4"
@@ -6,23 +6,27 @@
6
6
 
7
7
  import os
8
8
  import sys
9
+ from functools import wraps
9
10
  from typing import Optional
10
11
 
11
12
  import click
12
13
  import pkg_resources
13
14
  import requests
14
15
  from autoupgrade import Package
16
+ from click.exceptions import ClickException
15
17
 
16
18
  from suite_py.__version__ import __version__
17
- from suite_py.lib import logger
18
- from suite_py.lib import metrics
19
+ from suite_py.commands.context import Context
20
+ from suite_py.lib import logger, metrics
19
21
  from suite_py.lib.config import Config
20
22
  from suite_py.lib.handler import git_handler as git
21
23
  from suite_py.lib.handler import prompt_utils
24
+ from suite_py.lib.handler.captainhook_handler import CaptainHook
25
+ from suite_py.lib.handler.okta_handler import Okta
22
26
  from suite_py.lib.tokens import Tokens
23
27
 
24
- ALLOW_NO_GIT_SUBCOMMAND = ["login", "qa", "aggregator"]
25
- ALLOW_NO_HOME_SUBCOMMAND = ["login", "qa", "aggregator"]
28
+ ALLOW_NO_GIT_SUBCOMMAND = ["login", "aggregator"]
29
+ ALLOW_NO_HOME_SUBCOMMAND = ["login", "aggregator"]
26
30
 
27
31
 
28
32
  def maybe_inject_truststore() -> None:
@@ -84,6 +88,22 @@ def upgrade_suite_py_if_needed(break_on_missing_package: bool = False) -> None:
84
88
  logger.warning(f"An error occurred whilst trying to upgrade suite-py: {error}")
85
89
 
86
90
 
91
+ # Catches any exceptions thrown and turns them into a ClickException
92
+ # So they don't print a stacktrace
93
+ def catch_exceptions(func):
94
+ @wraps(func)
95
+ def wrapper(*args, **kwargs):
96
+ try:
97
+ return func(*args, **kwargs)
98
+ except ClickException as e:
99
+ raise e
100
+ except Exception as e:
101
+ logger.debug("An error occured:", exc_info=True)
102
+ raise ClickException(f"{str(e)}. rerun with -v for more details") from e
103
+
104
+ return wrapper
105
+
106
+
87
107
  @click.group()
88
108
  @click.option(
89
109
  "--project",
@@ -98,11 +118,11 @@ def upgrade_suite_py_if_needed(break_on_missing_package: bool = False) -> None:
98
118
  )
99
119
  @click.option("-v", "--verbose", count=True)
100
120
  @click.pass_context
121
+ @catch_exceptions
101
122
  def main(ctx, project, timeout, verbose):
102
123
  config = Config()
103
124
 
104
125
  logger.setup(verbose)
105
- metrics.setup(config)
106
126
 
107
127
  logger.debug(f"v{__version__}")
108
128
  maybe_inject_truststore()
@@ -114,14 +134,14 @@ def main(ctx, project, timeout, verbose):
114
134
  if ctx.invoked_subcommand not in ALLOW_NO_GIT_SUBCOMMAND and not git.is_repo(
115
135
  project
116
136
  ):
117
- print(f"the folder {project} is not a git repo")
118
- sys.exit(-1)
137
+ raise Exception(f"the folder {project} is not a git repo")
119
138
 
120
139
  if ctx.invoked_subcommand not in ALLOW_NO_HOME_SUBCOMMAND and not os.path.basename(
121
140
  project
122
141
  ) in os.listdir(config.user["projects_home"]):
123
- print(f"the folder {project} is not in {config.user['projects_home']}")
124
- sys.exit(-1)
142
+ raise Exception(
143
+ f"the folder {project} is not in {config.user['projects_home']}"
144
+ )
125
145
 
126
146
  skip_confirmation = False
127
147
  if type(config.user.get("skip_confirmation")).__name__ == "bool":
@@ -136,21 +156,31 @@ def main(ctx, project, timeout, verbose):
136
156
  if not skip_confirmation and not prompt_utils.ask_confirm(
137
157
  f"Do you want to continue on project {os.path.basename(project)}?"
138
158
  ):
139
- sys.exit()
140
-
141
- ctx.ensure_object(dict)
142
- ctx.obj["project"] = os.path.basename(project)
159
+ return
143
160
  if timeout:
144
161
  config.user["captainhook_timeout"] = timeout
145
- ctx.obj["config"] = config
146
- ctx.obj["tokens"] = Tokens()
162
+
163
+ project = os.path.basename(project)
164
+ tokens = Tokens()
165
+ okta = Okta(config, tokens)
166
+ captainhook = CaptainHook(config, okta)
167
+
168
+ ctx.obj = Context(
169
+ project=project,
170
+ tokens=tokens,
171
+ okta=okta,
172
+ config=config,
173
+ captainhook=captainhook,
174
+ )
175
+
176
+ ctx.obj.call(metrics.setup)
147
177
 
148
178
  # Skip chdir if not needed
149
179
  if (
150
180
  ctx.invoked_subcommand not in ALLOW_NO_GIT_SUBCOMMAND
151
181
  or ctx.invoked_subcommand not in ALLOW_NO_HOME_SUBCOMMAND
152
182
  ):
153
- os.chdir(os.path.join(config.user["projects_home"], ctx.obj["project"]))
183
+ os.chdir(os.path.join(config.user["projects_home"], ctx.obj.project))
154
184
 
155
185
 
156
186
  @main.result_callback()
@@ -168,12 +198,11 @@ def cleanup(_obj, _, **_kwargs):
168
198
  help="Version to apply. If not passed, you will be prompted to insert or select one from a predefined list",
169
199
  )
170
200
  @click.pass_obj
171
- def bump(obj, project: Optional[str] = None, version: Optional[str] = None):
201
+ @catch_exceptions
202
+ def bump(obj: Context, project: Optional[str] = None, version: Optional[str] = None):
172
203
  from suite_py.commands.bump import Bump
173
204
 
174
- Bump(obj["project"], obj["config"], obj["tokens"]).run(
175
- project=project, version=version
176
- )
205
+ obj.call(Bump).run(project=project, version=version)
177
206
 
178
207
 
179
208
  @main.command(
@@ -181,10 +210,11 @@ def bump(obj, project: Optional[str] = None, version: Optional[str] = None):
181
210
  )
182
211
  @click.option("--card", type=click.STRING, help="YouTrack card number (ex. PRIMA-123)")
183
212
  @click.pass_obj
213
+ @catch_exceptions
184
214
  def cli_create_branch(obj, card):
185
215
  from suite_py.commands.create_branch import CreateBranch
186
216
 
187
- CreateBranch(obj["project"], card, obj["config"], obj["tokens"]).run()
217
+ obj.call(CreateBranch, card=card).run()
188
218
 
189
219
 
190
220
  @main.command("lock", help="Lock project on staging or prod")
@@ -192,10 +222,11 @@ def cli_create_branch(obj, card):
192
222
  "environment", type=click.Choice(("staging", "production", "deploy", "merge"))
193
223
  )
194
224
  @click.pass_obj
225
+ @catch_exceptions
195
226
  def cli_lock_project(obj, environment):
196
227
  from suite_py.commands.project_lock import ProjectLock
197
228
 
198
- ProjectLock(obj["project"], environment, "lock", obj["config"], obj["tokens"]).run()
229
+ obj.call(ProjectLock, environment=environment, action="lock").run()
199
230
 
200
231
 
201
232
  @main.command("unlock", help="Unlock project on staging or prod")
@@ -203,38 +234,42 @@ def cli_lock_project(obj, environment):
203
234
  "environment", type=click.Choice(("staging", "production", "deploy", "merge"))
204
235
  )
205
236
  @click.pass_obj
237
+ @catch_exceptions
206
238
  def cli_unlock_project(obj, environment):
207
239
  from suite_py.commands.project_lock import ProjectLock
208
240
 
209
- ProjectLock(
210
- obj["project"], environment, "unlock", obj["config"], obj["tokens"]
211
- ).run()
241
+ obj.call(ProjectLock, environment=environment, action="unlock").run()
212
242
 
213
243
 
214
244
  @main.command("open-pr", help="Open a PR on GitHub")
215
245
  @click.pass_obj
246
+ @catch_exceptions
216
247
  def cli_open_pr(obj):
217
248
  from suite_py.commands.open_pr import OpenPR
249
+ from suite_py.commands.ask_review import AskReview
218
250
 
219
- OpenPR(obj["project"], obj["config"], obj["tokens"]).run()
251
+ ask_review = obj.call(AskReview)
252
+ obj.call(OpenPR, ask_review=ask_review).run()
220
253
 
221
254
 
222
255
  @main.command("ask-review", help="Requests a PR review")
223
256
  @click.pass_obj
257
+ @catch_exceptions
224
258
  def cli_ask_review(obj):
225
259
  from suite_py.commands.ask_review import AskReview
226
260
 
227
- AskReview(obj["project"], obj["config"], obj["tokens"]).run()
261
+ obj.call(AskReview).run()
228
262
 
229
263
 
230
264
  @main.command(
231
265
  "merge-pr", help="Merge the selected branch to master if all checks are OK"
232
266
  )
233
267
  @click.pass_obj
268
+ @catch_exceptions
234
269
  def cli_merge_pr(obj):
235
270
  from suite_py.commands.merge_pr import MergePR
236
271
 
237
- MergePR(obj["project"], obj["config"], obj["tokens"]).run()
272
+ obj.call(MergePR).run()
238
273
 
239
274
 
240
275
  @main.group("release", help="Manage releases")
@@ -251,40 +286,38 @@ def release():
251
286
  help="Trigger deploy with Drone CI after release creation (Github Actions based microservices will be automatically deployed on production)",
252
287
  )
253
288
  @click.pass_obj
289
+ @catch_exceptions
254
290
  def cli_release_create(obj, deploy):
255
291
  from suite_py.commands.release import Release
256
292
 
257
- Release(
258
- "create",
259
- obj["project"],
260
- obj["config"],
261
- obj["tokens"],
262
- flags={"deploy": deploy},
263
- ).run()
293
+ obj.call(Release, action="create", flags={"deploy": deploy}).run()
264
294
 
265
295
 
266
296
  @release.command("deploy", help="Deploy a github release with Drone CI")
267
297
  @click.pass_obj
298
+ @catch_exceptions
268
299
  def cli_release_deploy(obj):
269
300
  from suite_py.commands.release import Release
270
301
 
271
- Release("deploy", obj["project"], obj["config"], obj["tokens"]).run()
302
+ obj.call(Release, action="deploy").run()
272
303
 
273
304
 
274
305
  @release.command("rollback", help="Rollback a deployment")
275
306
  @click.pass_obj
307
+ @catch_exceptions
276
308
  def cli_release_rollback(obj):
277
309
  from suite_py.commands.release import Release
278
310
 
279
- Release("rollback", obj["project"], obj["config"], obj["tokens"]).run()
311
+ obj.call(Release, "rollback").run()
280
312
 
281
313
 
282
314
  @main.command("deploy", help="Deploy master branch in production")
283
315
  @click.pass_obj
316
+ @catch_exceptions
284
317
  def cli_deploy(obj):
285
318
  from suite_py.commands.deploy import Deploy
286
319
 
287
- Deploy(obj["project"], obj["config"], obj["tokens"]).run()
320
+ obj.call(Deploy).run()
288
321
 
289
322
 
290
323
  @main.group("docker", help="Manage docker images")
@@ -294,60 +327,67 @@ def docker():
294
327
 
295
328
  @docker.command("release", help="Release new docker image")
296
329
  @click.pass_obj
330
+ @catch_exceptions
297
331
  def cli_docker_release(obj):
298
332
  from suite_py.commands.docker import Docker
299
333
 
300
- Docker("release", obj["project"], obj["config"], obj["tokens"]).run()
334
+ obj.call(Docker, action="release").run()
301
335
 
302
336
 
303
337
  @docker.command("versions", help="List all available versions of specific image")
304
338
  @click.pass_obj
339
+ @catch_exceptions
305
340
  def cli_docker_versions(obj):
306
341
  from suite_py.commands.docker import Docker
307
342
 
308
- Docker("versions", obj["project"], obj["config"], obj["tokens"]).run()
343
+ obj.call(Docker, action="versions").run()
309
344
 
310
345
 
311
346
  @main.command("status", help="Current status of a project")
312
347
  @click.pass_obj
348
+ @catch_exceptions
313
349
  def cli_status(obj):
314
350
  from suite_py.commands.status import Status
315
351
 
316
- Status(obj["project"], obj["config"]).run()
352
+ obj.call(Status, action="versions").run()
317
353
 
318
354
 
319
355
  @main.command("check", help="Verify authorisations for third party services")
320
356
  @click.pass_obj
357
+ @catch_exceptions
321
358
  def cli_check(obj):
322
359
  from suite_py.commands.check import Check
323
360
 
324
- Check(obj["config"], obj["tokens"]).run()
361
+ obj.call(Check).run()
325
362
 
326
363
 
327
364
  @main.command("id", help="Get the ID of the hosts where the task is running")
328
365
  @click.argument("environment", type=click.Choice(("staging", "production")))
329
366
  @click.pass_obj
367
+ @catch_exceptions
330
368
  def cli_id(obj, environment):
331
369
  from suite_py.commands.id import ID
332
370
 
333
- ID(obj["project"], obj["config"], environment).run()
371
+ obj.call(ID, environment=environment).run()
334
372
 
335
373
 
336
374
  @main.command("ip", help="Get the IP addresses of the hosts where the task is running")
337
375
  @click.argument("environment", type=click.Choice(("staging", "production")))
338
376
  @click.pass_obj
377
+ @catch_exceptions
339
378
  def cli_ip(obj, environment):
340
379
  from suite_py.commands.ip import IP
341
380
 
342
- IP(obj["project"], obj["config"], environment).run()
381
+ obj.call(IP, environment=environment).run()
343
382
 
344
383
 
345
384
  @main.command("generator", help="Generate different files from templates")
346
385
  @click.pass_obj
386
+ @catch_exceptions
347
387
  def cli_generator(obj):
348
388
  from suite_py.commands.generator import Generator
349
389
 
350
- Generator(obj["project"], obj["config"], obj["tokens"]).run()
390
+ obj.call(Generator).run()
351
391
 
352
392
 
353
393
  @main.group(
@@ -374,153 +414,29 @@ def aggregator(ctx, show_list, change):
374
414
 
375
415
  @aggregator.command("list", help="List all aggregators with the current record")
376
416
  @click.pass_obj
417
+ @catch_exceptions
377
418
  def cli_aggregator_list(obj):
378
419
  from suite_py.commands.aggregator import Aggregator
379
420
 
380
- Aggregator(obj["config"], "list").run()
421
+ obj.call(Aggregator, action="list").run()
381
422
 
382
423
 
383
424
  @aggregator.command("change", help="Change aggregator record")
384
425
  @click.pass_obj
426
+ @catch_exceptions
385
427
  def cli_aggregator_change(obj):
386
428
  from suite_py.commands.aggregator import Aggregator
387
429
 
388
- Aggregator(obj["config"], "change").run()
430
+ obj.call(Aggregator, action="list").run()
389
431
 
390
432
 
391
433
  @main.command("login", help="manage login against Auth0")
392
434
  @click.pass_obj
435
+ @catch_exceptions
393
436
  def login(obj):
394
437
  from suite_py.commands.login import Login
395
438
 
396
- Login(obj["config"]).run()
397
-
398
-
399
- @main.group("qa", help="Manage QA envs")
400
- def qa():
401
- pass
402
-
403
-
404
- @qa.command("update-quota", help="Update quota in QA for a user")
405
- @click.pass_obj
406
- def cli_qa_update_quota(obj):
407
- from suite_py.commands.qa import QA
408
-
409
- QA("update-quota", obj["project"], obj["config"], obj["tokens"]).run()
410
-
411
-
412
- @qa.command("list", help="List QA envs for user: all to show qa of all users.")
413
- @click.option("-u", "--user", "user", required=False)
414
- @click.option("-s", "--status", "status", multiple=True, type=str)
415
- @click.option("-c", "--card", "card", type=str)
416
- @click.pass_obj
417
- def cli_qa_list(obj, user, status, card):
418
- from suite_py.commands.qa import QA
419
-
420
- QA(
421
- "list",
422
- obj["project"],
423
- obj["config"],
424
- obj["tokens"],
425
- {"user": user, "status": status, "card": card},
426
- ).run()
427
-
428
-
429
- @qa.command("create", help="Create QA env")
430
- @click.argument("microservices", nargs=-1, required=True)
431
- @click.pass_obj
432
- def cli_qa_create(obj, microservices):
433
- from suite_py.commands.qa import QA
434
-
435
- QA(
436
- "create",
437
- obj["project"],
438
- obj["config"],
439
- obj["tokens"],
440
- {"services": microservices},
441
- ).run()
442
-
443
-
444
- @qa.command("update", help="Update QA env")
445
- @click.argument("qa_hash", required=True)
446
- @click.argument("microservices", nargs=-1, required=True)
447
- @click.pass_obj
448
- def cli_qa_update(obj, qa_hash, microservices):
449
- from suite_py.commands.qa import QA
450
-
451
- QA(
452
- "update",
453
- obj["project"],
454
- obj["config"],
455
- obj["tokens"],
456
- {"hash": qa_hash, "services": microservices},
457
- ).run()
458
-
459
-
460
- @qa.command("delete", help="Delete QA env")
461
- @click.argument("qa_hashes", nargs=-1, required=True)
462
- @click.option("--force", is_flag=True, default=False, help="Force QA deletion")
463
- @click.pass_obj
464
- def cli_qa_delete(obj, qa_hashes, force):
465
- from suite_py.commands.qa import QA
466
-
467
- QA(
468
- "delete",
469
- obj["project"],
470
- obj["config"],
471
- obj["tokens"],
472
- {"hashes": qa_hashes, "force": force},
473
- ).run()
474
-
475
-
476
- @qa.command("freeze", help="Freeze QA env")
477
- @click.argument("qa_hash", required=True)
478
- @click.pass_obj
479
- def cli_qa_freeze(obj, qa_hash):
480
- from suite_py.commands.qa import QA
481
-
482
- QA("freeze", obj["project"], obj["config"], obj["tokens"], {"hash": qa_hash}).run()
483
-
484
-
485
- @qa.command("unfreeze", help="Unfreeze QA env")
486
- @click.argument("qa_hash", required=True)
487
- @click.pass_obj
488
- def cli_qa_unfreeze(obj, qa_hash):
489
- from suite_py.commands.qa import QA
490
-
491
- QA(
492
- "unfreeze", obj["project"], obj["config"], obj["tokens"], {"hash": qa_hash}
493
- ).run()
494
-
495
-
496
- @qa.command("check", help="Check QA conf")
497
- @click.pass_obj
498
- def cli_qa_check(obj):
499
- from suite_py.commands.qa import QA
500
-
501
- QA("check", obj["project"], obj["config"], obj["tokens"]).run()
502
-
503
-
504
- @qa.command("describe", help="Describe QA environment")
505
- @click.argument("qa_hash", required=True)
506
- @click.option("--json", is_flag=True, default=False, help="Get response as JSON")
507
- @click.pass_obj
508
- def cli_qa_describe(obj, qa_hash, json):
509
- from suite_py.commands.qa import QA
510
-
511
- flags = {"hash": qa_hash, "json": json}
512
- QA("describe", obj["project"], obj["config"], obj["tokens"], flags).run()
513
-
514
-
515
- @qa.command(
516
- "toggle-maintenance",
517
- help="Toggle maintenance mode (requires 'manage:maintenance' permission)",
518
- )
519
- @click.pass_obj
520
- def cli_qa_toggle_maintenance(obj):
521
- from suite_py.commands.qa import QA
522
-
523
- QA("toggle-maintenance", obj["project"], obj["config"], obj["tokens"]).run()
439
+ obj.call(Login).run()
524
440
 
525
441
 
526
442
  @main.group(
@@ -534,20 +450,26 @@ def secret():
534
450
  @click.option("-b", "--base-profile", "base_profile", required=False)
535
451
  @click.option("-f", "--secret-file", "secret_file", required=False)
536
452
  @click.pass_obj
453
+ @catch_exceptions
537
454
  def cli_secret_create(obj, base_profile, secret_file):
538
455
  from suite_py.commands.secret import Secret
539
456
 
540
- Secret(obj["project"], obj["config"], "create", base_profile, secret_file).run()
457
+ obj.call(
458
+ Secret, action="create", base_profile=base_profile, secret_file=secret_file
459
+ ).run()
541
460
 
542
461
 
543
462
  @secret.command("grant", help="Grant permissions to an existing secret")
544
463
  @click.option("-b", "--base-profile", "base_profile", required=False)
545
464
  @click.option("-f", "--secret-file", "secret_file", required=False)
546
465
  @click.pass_obj
466
+ @catch_exceptions
547
467
  def cli_secret_grant(obj, base_profile, secret_file):
548
468
  from suite_py.commands.secret import Secret
549
469
 
550
- Secret(obj["project"], obj["config"], "grant", base_profile, secret_file).run()
470
+ obj.call(
471
+ Secret, action="grant", base_profile=base_profile, secret_file=secret_file
472
+ ).run()
551
473
 
552
474
 
553
475
  @main.command("batch-job", help="Run batch job on kube")
@@ -569,22 +491,22 @@ def cli_secret_grant(obj, base_profile, secret_file):
569
491
  help="Mebibytes or gibibyte format. E.g: 256Mi or 1Gi",
570
492
  )
571
493
  @click.pass_obj
494
+ @catch_exceptions
572
495
  def cli_run_batch_job(obj, environment, cpu_request, memory_request):
573
496
  from suite_py.commands.batch_job import BatchJob
574
497
 
575
- BatchJob(
576
- obj["project"],
577
- obj["config"],
578
- obj["tokens"],
579
- environment,
580
- cpu_request,
581
- memory_request,
498
+ obj.call(
499
+ BatchJob,
500
+ environment=environment,
501
+ cpu_request=cpu_request,
502
+ memory_request=memory_request,
582
503
  ).run()
583
504
 
584
505
 
585
506
  @main.command("set-token", help="Create or update a service token")
586
507
  @click.pass_obj
508
+ @catch_exceptions
587
509
  def cli_set_token(obj):
588
510
  from suite_py.commands.set_token import SetToken
589
511
 
590
- SetToken(obj["tokens"]).run()
512
+ obj.call(SetToken).run()
@@ -7,15 +7,13 @@ from kubernetes import client, config
7
7
  from rich.console import Console
8
8
  from rich.table import Table
9
9
 
10
- from suite_py.lib import logger
11
- from suite_py.lib import metrics
10
+ from suite_py.lib import logger, metrics
12
11
  from suite_py.lib.handler import prompt_utils
13
- from suite_py.lib.handler.captainhook_handler import CaptainHook
14
12
 
15
13
 
16
14
  class Aggregator:
17
- def __init__(self, config, command):
18
- self._captainhook = CaptainHook(config)
15
+ def __init__(self, captainhook, command):
16
+ self._captainhook = captainhook
19
17
  self._command = command
20
18
 
21
19
  @metrics.command("aggregator")
@@ -1,9 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import sys
3
3
 
4
- from suite_py.lib import logger
5
- from suite_py.lib import metrics
6
- from suite_py.lib.handler.captainhook_handler import CaptainHook
4
+ from suite_py.lib import logger, metrics
7
5
  from suite_py.lib.handler.frequent_reviewers_handler import FrequentReviewersHandler
8
6
  from suite_py.lib.handler.git_handler import GitHandler
9
7
  from suite_py.lib.handler.github_handler import GithubHandler
@@ -12,11 +10,11 @@ from suite_py.lib.handler.youtrack_handler import YoutrackHandler
12
10
 
13
11
 
14
12
  class AskReview:
15
- def __init__(self, project, config, tokens):
13
+ def __init__(self, project, captainhook, config, tokens):
16
14
  self._project = project
17
15
  self._config = config
18
16
  self._youtrack = YoutrackHandler(config, tokens)
19
- self._captainhook = CaptainHook(config)
17
+ self._captainhook = captainhook
20
18
  self._git = GitHandler(project, config)
21
19
  self._github = GithubHandler(tokens)
22
20
  self._frequent_reviewers = FrequentReviewersHandler(config)
@@ -5,8 +5,7 @@ import textwrap
5
5
 
6
6
  import semver
7
7
 
8
- from suite_py.lib import logger
9
- from suite_py.lib import metrics
8
+ from suite_py.lib import logger, metrics
10
9
  from suite_py.lib.handler import prompt_utils
11
10
  from suite_py.lib.handler.drone_handler import DroneHandler
12
11
  from suite_py.lib.handler.git_handler import GitHandler
@@ -8,8 +8,7 @@ from typing import Any, Dict, List, Optional, cast
8
8
 
9
9
  from yaml import safe_load
10
10
 
11
- from suite_py.lib import logger
12
- from suite_py.lib import metrics
11
+ from suite_py.lib import logger, metrics
13
12
  from suite_py.lib.handler.changelog_handler import ChangelogHandler
14
13
  from suite_py.lib.handler.git_handler import GitHandler
15
14
  from suite_py.lib.handler.github_handler import GithubHandler