suite-py 1.41.9__tar.gz → 1.42.0__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.
- {suite_py-1.41.9 → suite_py-1.42.0}/PKG-INFO +4 -4
- {suite_py-1.41.9 → suite_py-1.42.0}/pyproject.toml +4 -4
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/__version__.py +1 -1
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/cli.py +36 -210
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/check.py +0 -18
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/merge_pr.py +1 -12
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/open_pr.py +1 -6
- suite_py-1.41.9/suite_py/commands/deploy.py → suite_py-1.42.0/suite_py/commands/release.py +41 -45
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/config.py +0 -1
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/captainhook_handler.py +0 -7
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/okta_handler.py +8 -4
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/metrics.py +1 -1
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/oauth.py +7 -3
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/tokens.py +3 -7
- suite_py-1.41.9/suite_py/commands/aggregator.py +0 -159
- suite_py-1.41.9/suite_py/commands/batch_job.py +0 -215
- suite_py-1.41.9/suite_py/commands/docker.py +0 -91
- suite_py-1.41.9/suite_py/commands/generator.py +0 -238
- suite_py-1.41.9/suite_py/commands/id.py +0 -60
- suite_py-1.41.9/suite_py/commands/ip.py +0 -68
- suite_py-1.41.9/suite_py/commands/release.py +0 -449
- suite_py-1.41.9/suite_py/commands/secret.py +0 -204
- suite_py-1.41.9/suite_py/lib/handler/drone_handler.py +0 -252
- suite_py-1.41.9/suite_py/lib/handler/vault_handler.py +0 -28
- {suite_py-1.41.9 → suite_py-1.42.0}/LICENSE-APACHE +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/LICENSE-MIT +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/__init__.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/__init__.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/ask_review.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/bump.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/common.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/context.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/create_branch.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/login.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/project_lock.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/set_token.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/commands/status.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/__init__.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/__init__.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/aws_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/changelog_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/frequent_reviewers_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/git_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/github_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/metrics_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/prompt_utils.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/version_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/handler/youtrack_handler.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/logger.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/requests/__init__.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/requests/auth.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/requests/session.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/suite_py/lib/symbol.py +0 -0
- {suite_py-1.41.9 → suite_py-1.42.0}/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.
|
|
3
|
+
Version: 1.42.0
|
|
4
4
|
Summary:
|
|
5
5
|
Author: larrywax, EugenioLaghi, michelangelomo
|
|
6
6
|
Author-email: devops@prima.it
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Requires-Dist: Click (>=7.0)
|
|
15
15
|
Requires-Dist: InquirerPy (>=0.2.0)
|
|
16
|
-
Requires-Dist: Jinja2 (>=
|
|
16
|
+
Requires-Dist: Jinja2 (>=3.1.4,<4.0.0)
|
|
17
17
|
Requires-Dist: PyGithub (>=1.57)
|
|
18
18
|
Requires-Dist: PyYaml (>=5.4)
|
|
19
19
|
Requires-Dist: autoupgrade-prima (>=0.6)
|
|
@@ -21,12 +21,12 @@ Requires-Dist: black (>=22.6,<25.0)
|
|
|
21
21
|
Requires-Dist: boto3 (>=1.17.84)
|
|
22
22
|
Requires-Dist: cement (>=3.0)
|
|
23
23
|
Requires-Dist: colorama (>=0.4.3)
|
|
24
|
-
Requires-Dist: cryptography (==
|
|
24
|
+
Requires-Dist: cryptography (==43.0.0)
|
|
25
25
|
Requires-Dist: halo (>=0.0.28)
|
|
26
26
|
Requires-Dist: inquirer (==3.1.4)
|
|
27
27
|
Requires-Dist: itsdangerous (==2.2.0)
|
|
28
28
|
Requires-Dist: keyring (>=23.9.1,<26.0.0)
|
|
29
|
-
Requires-Dist: kubernetes (==
|
|
29
|
+
Requires-Dist: kubernetes (==30.1.0)
|
|
30
30
|
Requires-Dist: logzero (==1.7.0)
|
|
31
31
|
Requires-Dist: markupsafe (==2.0.1)
|
|
32
32
|
Requires-Dist: pptree (==3.1)
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
authors = ["larrywax, EugenioLaghi, michelangelomo <devops@prima.it>"]
|
|
3
3
|
description = ""
|
|
4
4
|
name = "suite-py"
|
|
5
|
-
version = "1.
|
|
5
|
+
version = "1.42.0"
|
|
6
6
|
|
|
7
7
|
[tool.poetry.dependencies]
|
|
8
8
|
Click = ">=7.0"
|
|
9
9
|
InquirerPy = ">=0.2.0"
|
|
10
|
-
Jinja2 = ">=
|
|
10
|
+
Jinja2 = ">=3.1.4,<4.0.0"
|
|
11
11
|
PyGithub = ">=1.57"
|
|
12
12
|
PyYaml = ">=5.4"
|
|
13
13
|
autoupgrade-prima = ">=0.6"
|
|
@@ -19,7 +19,7 @@ halo = ">=0.0.28"
|
|
|
19
19
|
inquirer = "==3.1.4"
|
|
20
20
|
itsdangerous = "==2.2.0"
|
|
21
21
|
keyring = ">=23.9.1,<26.0.0"
|
|
22
|
-
kubernetes = "==
|
|
22
|
+
kubernetes = "==30.1.0"
|
|
23
23
|
logzero = "==1.7.0"
|
|
24
24
|
markupsafe = "==2.0.1"
|
|
25
25
|
pptree = "==3.1"
|
|
@@ -34,7 +34,7 @@ rich = "==13.7.1"
|
|
|
34
34
|
semver = "^2.13.0"
|
|
35
35
|
termcolor = ">=1.1.0"
|
|
36
36
|
truststore = {version = ">=0.7,<0.10", python = ">=3.10"}
|
|
37
|
-
cryptography = "
|
|
37
|
+
cryptography = "43.0.0"
|
|
38
38
|
|
|
39
39
|
[tool.poetry.dev-dependencies]
|
|
40
40
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
__version__ = "1.
|
|
2
|
+
__version__ = "1.42.0"
|
|
@@ -4,12 +4,38 @@
|
|
|
4
4
|
# for performance reasons, so turn off the lint warning
|
|
5
5
|
# pylint: disable=import-outside-toplevel
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# We need to inject truststore code before we do any libraries
|
|
8
|
+
# that might end up creating an ssl.SSlContext object
|
|
9
|
+
# pylint: disable=wrong-import-position
|
|
10
|
+
|
|
8
11
|
import sys
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def maybe_inject_truststore() -> None:
|
|
15
|
+
"""
|
|
16
|
+
Injects the truststore package into the system ssl store, to fix verficiation certificate issues when using warp.
|
|
17
|
+
"""
|
|
18
|
+
if sys.version_info >= (3, 10):
|
|
19
|
+
import truststore
|
|
20
|
+
|
|
21
|
+
truststore.inject_into_ssl()
|
|
22
|
+
else:
|
|
23
|
+
# pylint: disable-next=reimported
|
|
24
|
+
from suite_py.lib import logger
|
|
25
|
+
|
|
26
|
+
logger.warning(
|
|
27
|
+
"Your python version is older than 3.10 and doesn't support the truststore package. You might experience issues with certificate verification when connected to the warp VPN.\nPlease update to python 3.10 or newer"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Needs to be done before any other imports
|
|
32
|
+
maybe_inject_truststore()
|
|
33
|
+
|
|
34
|
+
import os
|
|
9
35
|
from functools import wraps
|
|
36
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
10
37
|
from typing import Optional
|
|
11
38
|
|
|
12
|
-
from importlib.metadata import version, PackageNotFoundError
|
|
13
39
|
import click
|
|
14
40
|
import requests
|
|
15
41
|
from autoupgrade import Package
|
|
@@ -25,22 +51,10 @@ from suite_py.lib.handler.captainhook_handler import CaptainHook
|
|
|
25
51
|
from suite_py.lib.handler.okta_handler import Okta
|
|
26
52
|
from suite_py.lib.tokens import Tokens
|
|
27
53
|
|
|
28
|
-
|
|
29
|
-
ALLOW_NO_HOME_SUBCOMMAND = ["login", "aggregator"]
|
|
54
|
+
# pylint: enable=wrong-import-position
|
|
30
55
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"""
|
|
34
|
-
Injects the truststore package into the system ssl store, to fix verficiation certificate issues when using warp.
|
|
35
|
-
"""
|
|
36
|
-
if sys.version_info >= (3, 10):
|
|
37
|
-
import truststore
|
|
38
|
-
|
|
39
|
-
truststore.inject_into_ssl()
|
|
40
|
-
else:
|
|
41
|
-
logger.warning(
|
|
42
|
-
"Your python version is older than 3.10 and doesn't support the truststore package. You might experience issues with certificate verification when connected to the warp VPN.\nPlease update to python 3.10 or newer"
|
|
43
|
-
)
|
|
56
|
+
ALLOW_NO_GIT_SUBCOMMAND = ["check", "set-token", "login"]
|
|
57
|
+
ALLOW_NO_HOME_SUBCOMMAND = ["check", "set-token", "login"]
|
|
44
58
|
|
|
45
59
|
|
|
46
60
|
def fetch_latest_version() -> Optional[str]:
|
|
@@ -132,12 +146,12 @@ def main(ctx, project, timeout, verbose):
|
|
|
132
146
|
if ctx.invoked_subcommand not in ALLOW_NO_GIT_SUBCOMMAND and not git.is_repo(
|
|
133
147
|
project
|
|
134
148
|
):
|
|
135
|
-
raise
|
|
149
|
+
raise ClickException(f"the folder {project} is not a git repo")
|
|
136
150
|
|
|
137
151
|
if ctx.invoked_subcommand not in ALLOW_NO_HOME_SUBCOMMAND and not os.path.basename(
|
|
138
152
|
project
|
|
139
153
|
) in os.listdir(config.user["projects_home"]):
|
|
140
|
-
raise
|
|
154
|
+
raise ClickException(
|
|
141
155
|
f"the folder {project} is not in {config.user['projects_home']}"
|
|
142
156
|
)
|
|
143
157
|
|
|
@@ -243,8 +257,8 @@ def cli_unlock_project(obj, environment):
|
|
|
243
257
|
@click.pass_obj
|
|
244
258
|
@catch_exceptions
|
|
245
259
|
def cli_open_pr(obj):
|
|
246
|
-
from suite_py.commands.open_pr import OpenPR
|
|
247
260
|
from suite_py.commands.ask_review import AskReview
|
|
261
|
+
from suite_py.commands.open_pr import OpenPR
|
|
248
262
|
|
|
249
263
|
ask_review = obj.call(AskReview)
|
|
250
264
|
obj.call(OpenPR, ask_review=ask_review).run()
|
|
@@ -278,67 +292,12 @@ def release():
|
|
|
278
292
|
@release.command(
|
|
279
293
|
"create", help="Create a github release (and deploy it if GHA are used)"
|
|
280
294
|
)
|
|
281
|
-
@click.option(
|
|
282
|
-
"--deploy",
|
|
283
|
-
is_flag=True,
|
|
284
|
-
help="Trigger deploy with Drone CI after release creation (Github Actions based microservices will be automatically deployed on production)",
|
|
285
|
-
)
|
|
286
|
-
@click.pass_obj
|
|
287
|
-
@catch_exceptions
|
|
288
|
-
def cli_release_create(obj, deploy):
|
|
289
|
-
from suite_py.commands.release import Release
|
|
290
|
-
|
|
291
|
-
obj.call(Release, action="create", flags={"deploy": deploy}).run()
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
@release.command("deploy", help="Deploy a github release with Drone CI")
|
|
295
295
|
@click.pass_obj
|
|
296
296
|
@catch_exceptions
|
|
297
|
-
def
|
|
297
|
+
def cli_release_create(obj):
|
|
298
298
|
from suite_py.commands.release import Release
|
|
299
299
|
|
|
300
|
-
obj.call(Release, action="
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
@release.command("rollback", help="Rollback a deployment")
|
|
304
|
-
@click.pass_obj
|
|
305
|
-
@catch_exceptions
|
|
306
|
-
def cli_release_rollback(obj):
|
|
307
|
-
from suite_py.commands.release import Release
|
|
308
|
-
|
|
309
|
-
obj.call(Release, "rollback").run()
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
@main.command("deploy", help="Deploy master branch in production")
|
|
313
|
-
@click.pass_obj
|
|
314
|
-
@catch_exceptions
|
|
315
|
-
def cli_deploy(obj):
|
|
316
|
-
from suite_py.commands.deploy import Deploy
|
|
317
|
-
|
|
318
|
-
obj.call(Deploy).run()
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
@main.group("docker", help="Manage docker images")
|
|
322
|
-
def docker():
|
|
323
|
-
pass
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
@docker.command("release", help="Release new docker image")
|
|
327
|
-
@click.pass_obj
|
|
328
|
-
@catch_exceptions
|
|
329
|
-
def cli_docker_release(obj):
|
|
330
|
-
from suite_py.commands.docker import Docker
|
|
331
|
-
|
|
332
|
-
obj.call(Docker, action="release").run()
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
@docker.command("versions", help="List all available versions of specific image")
|
|
336
|
-
@click.pass_obj
|
|
337
|
-
@catch_exceptions
|
|
338
|
-
def cli_docker_versions(obj):
|
|
339
|
-
from suite_py.commands.docker import Docker
|
|
340
|
-
|
|
341
|
-
obj.call(Docker, action="versions").run()
|
|
300
|
+
obj.call(Release, action="create").run()
|
|
342
301
|
|
|
343
302
|
|
|
344
303
|
@main.command("status", help="Current status of a project")
|
|
@@ -359,75 +318,6 @@ def cli_check(obj):
|
|
|
359
318
|
obj.call(Check).run()
|
|
360
319
|
|
|
361
320
|
|
|
362
|
-
@main.command("id", help="Get the ID of the hosts where the task is running")
|
|
363
|
-
@click.argument("environment", type=click.Choice(("staging", "production")))
|
|
364
|
-
@click.pass_obj
|
|
365
|
-
@catch_exceptions
|
|
366
|
-
def cli_id(obj, environment):
|
|
367
|
-
from suite_py.commands.id import ID
|
|
368
|
-
|
|
369
|
-
obj.call(ID, environment=environment).run()
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
@main.command("ip", help="Get the IP addresses of the hosts where the task is running")
|
|
373
|
-
@click.argument("environment", type=click.Choice(("staging", "production")))
|
|
374
|
-
@click.pass_obj
|
|
375
|
-
@catch_exceptions
|
|
376
|
-
def cli_ip(obj, environment):
|
|
377
|
-
from suite_py.commands.ip import IP
|
|
378
|
-
|
|
379
|
-
obj.call(IP, environment=environment).run()
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
@main.command("generator", help="Generate different files from templates")
|
|
383
|
-
@click.pass_obj
|
|
384
|
-
@catch_exceptions
|
|
385
|
-
def cli_generator(obj):
|
|
386
|
-
from suite_py.commands.generator import Generator
|
|
387
|
-
|
|
388
|
-
obj.call(Generator).run()
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
@main.group(
|
|
392
|
-
"aggregator",
|
|
393
|
-
help="Manage CNAMEs of aggregators in QA envs",
|
|
394
|
-
invoke_without_command=True,
|
|
395
|
-
)
|
|
396
|
-
@click.option(
|
|
397
|
-
"-l", "--list", "show_list", help="deprecated", required=False, count=True
|
|
398
|
-
)
|
|
399
|
-
@click.option("-c", "--change", "change", help="deprecated", required=False, count=True)
|
|
400
|
-
@click.pass_context
|
|
401
|
-
def aggregator(ctx, show_list, change):
|
|
402
|
-
if show_list == 1 or change == 1:
|
|
403
|
-
logger.error(
|
|
404
|
-
"suite-py aggregator [-c|-l] has been hard-deprecated. Use suite-py aggregator [list|change] instead."
|
|
405
|
-
)
|
|
406
|
-
sys.exit(0)
|
|
407
|
-
|
|
408
|
-
if ctx.invoked_subcommand is None:
|
|
409
|
-
logger.error("Missing command. Try suite-py aggregator --help for help.")
|
|
410
|
-
sys.exit(0)
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
@aggregator.command("list", help="List all aggregators with the current record")
|
|
414
|
-
@click.pass_obj
|
|
415
|
-
@catch_exceptions
|
|
416
|
-
def cli_aggregator_list(obj):
|
|
417
|
-
from suite_py.commands.aggregator import Aggregator
|
|
418
|
-
|
|
419
|
-
obj.call(Aggregator, action="list").run()
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
@aggregator.command("change", help="Change aggregator record")
|
|
423
|
-
@click.pass_obj
|
|
424
|
-
@catch_exceptions
|
|
425
|
-
def cli_aggregator_change(obj):
|
|
426
|
-
from suite_py.commands.aggregator import Aggregator
|
|
427
|
-
|
|
428
|
-
obj.call(Aggregator, action="list").run()
|
|
429
|
-
|
|
430
|
-
|
|
431
321
|
@main.command("login", help="manage login against Auth0")
|
|
432
322
|
@click.pass_obj
|
|
433
323
|
@catch_exceptions
|
|
@@ -437,70 +327,6 @@ def login(obj):
|
|
|
437
327
|
obj.call(Login).run()
|
|
438
328
|
|
|
439
329
|
|
|
440
|
-
@main.group(
|
|
441
|
-
"secret", help="Manage secrets grants in multiple countries (aws-vault needed)"
|
|
442
|
-
)
|
|
443
|
-
def secret():
|
|
444
|
-
pass
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
@secret.command("create", help="Create a new secret")
|
|
448
|
-
@click.option("-b", "--base-profile", "base_profile", required=False)
|
|
449
|
-
@click.option("-f", "--secret-file", "secret_file", required=False)
|
|
450
|
-
@click.pass_obj
|
|
451
|
-
@catch_exceptions
|
|
452
|
-
def cli_secret_create(obj, base_profile, secret_file):
|
|
453
|
-
from suite_py.commands.secret import Secret
|
|
454
|
-
|
|
455
|
-
obj.call(
|
|
456
|
-
Secret, action="create", base_profile=base_profile, secret_file=secret_file
|
|
457
|
-
).run()
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
@secret.command("grant", help="Grant permissions to an existing secret")
|
|
461
|
-
@click.option("-b", "--base-profile", "base_profile", required=False)
|
|
462
|
-
@click.option("-f", "--secret-file", "secret_file", required=False)
|
|
463
|
-
@click.pass_obj
|
|
464
|
-
@catch_exceptions
|
|
465
|
-
def cli_secret_grant(obj, base_profile, secret_file):
|
|
466
|
-
from suite_py.commands.secret import Secret
|
|
467
|
-
|
|
468
|
-
obj.call(
|
|
469
|
-
Secret, action="grant", base_profile=base_profile, secret_file=secret_file
|
|
470
|
-
).run()
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
@main.command("batch-job", help="Run batch job on kube")
|
|
474
|
-
@click.argument("environment", type=click.Choice(("staging", "production")))
|
|
475
|
-
@click.option(
|
|
476
|
-
"-c",
|
|
477
|
-
"--cpu",
|
|
478
|
-
"cpu_request",
|
|
479
|
-
required=True,
|
|
480
|
-
type=str,
|
|
481
|
-
help="Millicpu format. E.g: 1000m (=1CPU)",
|
|
482
|
-
)
|
|
483
|
-
@click.option(
|
|
484
|
-
"-m",
|
|
485
|
-
"--memory",
|
|
486
|
-
"memory_request",
|
|
487
|
-
required=True,
|
|
488
|
-
type=str,
|
|
489
|
-
help="Mebibytes or gibibyte format. E.g: 256Mi or 1Gi",
|
|
490
|
-
)
|
|
491
|
-
@click.pass_obj
|
|
492
|
-
@catch_exceptions
|
|
493
|
-
def cli_run_batch_job(obj, environment, cpu_request, memory_request):
|
|
494
|
-
from suite_py.commands.batch_job import BatchJob
|
|
495
|
-
|
|
496
|
-
obj.call(
|
|
497
|
-
BatchJob,
|
|
498
|
-
environment=environment,
|
|
499
|
-
cpu_request=cpu_request,
|
|
500
|
-
memory_request=memory_request,
|
|
501
|
-
).run()
|
|
502
|
-
|
|
503
|
-
|
|
504
330
|
@main.command("set-token", help="Create or update a service token")
|
|
505
331
|
@click.pass_obj
|
|
506
332
|
@catch_exceptions
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from suite_py.lib import logger, metrics
|
|
4
4
|
from suite_py.lib.handler import prompt_utils
|
|
5
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
6
5
|
from suite_py.lib.handler.github_handler import GithubHandler
|
|
7
6
|
from suite_py.lib.handler.youtrack_handler import YoutrackHandler
|
|
8
7
|
from suite_py.lib.symbol import CHECKMARK, CROSSMARK
|
|
@@ -16,11 +15,9 @@ class Check:
|
|
|
16
15
|
self._youtrack = YoutrackHandler(config, tokens)
|
|
17
16
|
self._github = GithubHandler(tokens)
|
|
18
17
|
self._captainhook = captainhook
|
|
19
|
-
self._drone = DroneHandler(config, tokens)
|
|
20
18
|
|
|
21
19
|
self._checks = [
|
|
22
20
|
("Github", self._check_github),
|
|
23
|
-
("Drone", self._check_drone),
|
|
24
21
|
("Youtrack", self._check_youtrack),
|
|
25
22
|
("CaptainHook", self._check_captainhook),
|
|
26
23
|
("AWS", self._check_aws),
|
|
@@ -52,21 +49,6 @@ class Check:
|
|
|
52
49
|
self._invalid_or_missing_tokens.append("github")
|
|
53
50
|
return "missing_token"
|
|
54
51
|
|
|
55
|
-
def _check_drone(self):
|
|
56
|
-
if self._tokens.drone:
|
|
57
|
-
try:
|
|
58
|
-
drone_user = self._drone.get_user()
|
|
59
|
-
if "message" in drone_user and drone_user["message"] == "Unauthorized":
|
|
60
|
-
self._invalid_or_missing_tokens.append("drone")
|
|
61
|
-
return "invalid_token"
|
|
62
|
-
return "ok"
|
|
63
|
-
except Exception:
|
|
64
|
-
logger.debug("Error connecting to drone", exc_info=True)
|
|
65
|
-
return "unreachable"
|
|
66
|
-
else:
|
|
67
|
-
self._invalid_or_missing_tokens.append("drone")
|
|
68
|
-
return "missing_token"
|
|
69
|
-
|
|
70
52
|
def _check_youtrack(self):
|
|
71
53
|
if self._tokens.youtrack:
|
|
72
54
|
try:
|
|
@@ -7,7 +7,6 @@ from suite_py.lib import logger, metrics
|
|
|
7
7
|
from suite_py.lib.handler import git_handler as git
|
|
8
8
|
from suite_py.lib.handler import prompt_utils
|
|
9
9
|
from suite_py.lib.handler.captainhook_handler import CaptainHook
|
|
10
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
11
10
|
from suite_py.lib.handler.git_handler import GitHandler
|
|
12
11
|
from suite_py.lib.handler.github_handler import GithubHandler
|
|
13
12
|
from suite_py.lib.handler.youtrack_handler import YoutrackHandler
|
|
@@ -22,7 +21,6 @@ class MergePR:
|
|
|
22
21
|
self._captainhook = captainhook
|
|
23
22
|
self._git = GitHandler(project, config)
|
|
24
23
|
self._github = GithubHandler(tokens)
|
|
25
|
-
self._drone = DroneHandler(config, tokens, repo=project)
|
|
26
24
|
|
|
27
25
|
@metrics.command("merge-pr")
|
|
28
26
|
def run(self):
|
|
@@ -56,13 +54,6 @@ class MergePR:
|
|
|
56
54
|
|
|
57
55
|
logger.info("Pull request merged on master!")
|
|
58
56
|
|
|
59
|
-
if self._drone.parse_yaml():
|
|
60
|
-
drone_build_number = self._drone.get_pr_build_number(merge_status.sha)
|
|
61
|
-
drone_build_url = self._drone.get_build_url(drone_build_number)
|
|
62
|
-
|
|
63
|
-
if drone_build_url:
|
|
64
|
-
logger.info(f"You can follow the build status at {drone_build_url}")
|
|
65
|
-
|
|
66
57
|
self._git.fetch()
|
|
67
58
|
if self._git.remote_branch_exists(branch_name):
|
|
68
59
|
self._git.delete_remote_branch(branch_name)
|
|
@@ -84,9 +75,7 @@ class MergePR:
|
|
|
84
75
|
logger.warning(
|
|
85
76
|
"There is no YouTrack issue in the branch name or the selected issue does not exist."
|
|
86
77
|
)
|
|
87
|
-
logger.warning(
|
|
88
|
-
"No card updated on YouTrack and no QA turned off automatically"
|
|
89
|
-
)
|
|
78
|
+
logger.warning("No card updated on YouTrack")
|
|
90
79
|
|
|
91
80
|
logger.info("All done!")
|
|
92
81
|
sys.exit()
|
|
@@ -15,7 +15,6 @@ class OpenPR:
|
|
|
15
15
|
self._ask_review = ask_review
|
|
16
16
|
self._project = project
|
|
17
17
|
self._config = config
|
|
18
|
-
self._tokens = tokens
|
|
19
18
|
self._youtrack = YoutrackHandler(config, tokens)
|
|
20
19
|
self._git = GitHandler(project, config)
|
|
21
20
|
self._branch_name = self._git.current_branch_name()
|
|
@@ -25,11 +24,7 @@ class OpenPR:
|
|
|
25
24
|
def run(self):
|
|
26
25
|
if not self._git.remote_branch_exists(self._branch_name):
|
|
27
26
|
logger.warning(f"No branch named {self._branch_name} found on GitHub")
|
|
28
|
-
if prompt_utils.ask_confirm(
|
|
29
|
-
"Do you want to commit all the files and push them?"
|
|
30
|
-
):
|
|
31
|
-
self._git.add()
|
|
32
|
-
self._git.commit("Initial commit")
|
|
27
|
+
if prompt_utils.ask_confirm("Do you want to push your commits to github?"):
|
|
33
28
|
self._git.push(self._branch_name)
|
|
34
29
|
else:
|
|
35
30
|
logger.error("Please, run 'git push' manually")
|
|
@@ -3,52 +3,58 @@ import re
|
|
|
3
3
|
import sys
|
|
4
4
|
|
|
5
5
|
from suite_py.commands import common
|
|
6
|
-
from suite_py.commands.release import _parse_available_countries
|
|
7
6
|
from suite_py.lib import logger, metrics
|
|
8
7
|
from suite_py.lib.handler import git_handler as git
|
|
9
8
|
from suite_py.lib.handler import prompt_utils
|
|
10
9
|
from suite_py.lib.handler.changelog_handler import ChangelogHandler
|
|
11
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
12
10
|
from suite_py.lib.handler.git_handler import GitHandler
|
|
13
11
|
from suite_py.lib.handler.github_handler import GithubHandler
|
|
14
12
|
from suite_py.lib.handler.version_handler import DEFAULT_VERSION, VersionHandler
|
|
15
13
|
from suite_py.lib.handler.youtrack_handler import YoutrackHandler
|
|
16
14
|
|
|
17
15
|
|
|
18
|
-
class
|
|
16
|
+
class Release:
|
|
19
17
|
# pylint: disable=too-many-instance-attributes
|
|
20
|
-
def __init__(self, project, captainhook, config, tokens):
|
|
18
|
+
def __init__(self, action, project, captainhook, config, tokens):
|
|
19
|
+
self._action = action
|
|
21
20
|
self._project = project
|
|
22
21
|
self._config = config
|
|
22
|
+
self._tokens = tokens
|
|
23
|
+
self._changelog_handler = ChangelogHandler()
|
|
23
24
|
self._youtrack = YoutrackHandler(config, tokens)
|
|
24
25
|
self._captainhook = captainhook
|
|
25
|
-
self._changelog_handler = ChangelogHandler()
|
|
26
26
|
self._github = GithubHandler(tokens)
|
|
27
27
|
self._repo = self._github.get_repo(project)
|
|
28
28
|
self._git = GitHandler(project, config)
|
|
29
|
-
self._drone = DroneHandler(config, tokens, repo=project)
|
|
30
|
-
self._countries = _parse_available_countries(self._drone)
|
|
31
29
|
self._version = VersionHandler(self._repo, self._git, self._github)
|
|
32
30
|
|
|
33
|
-
@metrics.command("
|
|
31
|
+
@metrics.command("release")
|
|
34
32
|
def run(self):
|
|
35
33
|
self._stop_if_prod_locked()
|
|
36
|
-
|
|
37
34
|
self._git.fetch()
|
|
38
35
|
|
|
39
|
-
if
|
|
36
|
+
if self._action == "create":
|
|
37
|
+
self._create()
|
|
38
|
+
|
|
39
|
+
def _stop_if_prod_locked(self):
|
|
40
|
+
request = self._captainhook.status(self._project, "production")
|
|
41
|
+
if request.status_code != 200:
|
|
42
|
+
logger.error("Unable to determine lock status on master.")
|
|
43
|
+
sys.exit(-1)
|
|
44
|
+
|
|
45
|
+
request_object = request.json()
|
|
46
|
+
if request_object["locked"]:
|
|
40
47
|
logger.error(
|
|
41
|
-
"
|
|
48
|
+
f"The project is locked in production by {request_object['by']}. Unable to continue."
|
|
42
49
|
)
|
|
43
|
-
sys.exit(1)
|
|
50
|
+
sys.exit(-1)
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
def _create(self):
|
|
53
|
+
latest = self._version.get_latest_version()
|
|
46
54
|
|
|
47
|
-
if
|
|
48
|
-
logger.info(f"The current release is {
|
|
49
|
-
commits = self._github.get_commits_since_release(
|
|
50
|
-
self._repo, current_version
|
|
51
|
-
)
|
|
55
|
+
if latest != "":
|
|
56
|
+
logger.info(f"The current release is {latest}")
|
|
57
|
+
commits = self._github.get_commits_since_release(self._repo, latest)
|
|
52
58
|
|
|
53
59
|
_check_migrations_deploy(commits)
|
|
54
60
|
|
|
@@ -65,10 +71,10 @@ class Deploy:
|
|
|
65
71
|
logger.info(f"\nCommits list:\n{message}\n")
|
|
66
72
|
|
|
67
73
|
if not prompt_utils.ask_confirm("Do you want to continue?"):
|
|
68
|
-
|
|
74
|
+
return
|
|
69
75
|
|
|
70
76
|
new_version = self._version.select_new_version(
|
|
71
|
-
|
|
77
|
+
latest, allow_prerelease=True
|
|
72
78
|
)
|
|
73
79
|
|
|
74
80
|
else:
|
|
@@ -100,20 +106,6 @@ class Deploy:
|
|
|
100
106
|
message = common.ask_for_release_description(message)
|
|
101
107
|
|
|
102
108
|
self._create_release(new_version, message)
|
|
103
|
-
self._manage_youtrack_card(commits, new_version)
|
|
104
|
-
|
|
105
|
-
def _stop_if_prod_locked(self):
|
|
106
|
-
request = self._captainhook.status(self._project, "production")
|
|
107
|
-
if request.status_code != 200:
|
|
108
|
-
logger.error("Unable to determine lock status on master.")
|
|
109
|
-
sys.exit(-1)
|
|
110
|
-
|
|
111
|
-
request_object = request.json()
|
|
112
|
-
if request_object["locked"]:
|
|
113
|
-
logger.error(
|
|
114
|
-
f"The project is locked in production by {request_object['by']}. Unable to continue."
|
|
115
|
-
)
|
|
116
|
-
sys.exit(-1)
|
|
117
109
|
|
|
118
110
|
def _create_release(self, new_version, message):
|
|
119
111
|
new_release = self._repo.create_git_release(
|
|
@@ -124,17 +116,12 @@ class Deploy:
|
|
|
124
116
|
if new_release:
|
|
125
117
|
logger.info(f"The release has been created! Link: {new_release.html_url}")
|
|
126
118
|
|
|
127
|
-
|
|
128
|
-
if build_number:
|
|
129
|
-
drone_url = self._drone.get_build_url(build_number)
|
|
130
|
-
logger.info(
|
|
131
|
-
f"You can follow the deployment in production here: {drone_url}"
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
def _manage_youtrack_card(self, commits, new_version):
|
|
119
|
+
def _manage_youtrack_card(self, version, countries):
|
|
135
120
|
release_state = self._config.youtrack["release_state"]
|
|
136
121
|
|
|
137
|
-
|
|
122
|
+
release_body = self._repo.get_release(version).body
|
|
123
|
+
|
|
124
|
+
issue_ids = self._youtrack.get_ids_from_release_body(release_body)
|
|
138
125
|
|
|
139
126
|
if len(issue_ids) > 0:
|
|
140
127
|
update_youtrack_state = prompt_utils.ask_confirm(
|
|
@@ -146,7 +133,7 @@ class Deploy:
|
|
|
146
133
|
try:
|
|
147
134
|
self._youtrack.comment(
|
|
148
135
|
issue_id,
|
|
149
|
-
f"Deploy in production of {self._project} done with the release {
|
|
136
|
+
f"Deploy in production of {self._project} in countries {countries} done with the release {version}",
|
|
150
137
|
)
|
|
151
138
|
if update_youtrack_state:
|
|
152
139
|
self._youtrack.update_state(issue_id, release_state)
|
|
@@ -167,7 +154,7 @@ class Deploy:
|
|
|
167
154
|
|
|
168
155
|
def _get_repos_status_from_issue(self, issue_id):
|
|
169
156
|
regex_pr = r"^PR .* -> https:\/\/github\.com\/primait\/(.*)\/pull\/([0-9]*)$"
|
|
170
|
-
regex_deploy = r"^Deploy in production of (.*)
|
|
157
|
+
regex_deploy = r"^Deploy in production of (.*) in countries"
|
|
171
158
|
comments = self._youtrack.get_comments(issue_id)
|
|
172
159
|
repos_status = {}
|
|
173
160
|
|
|
@@ -188,6 +175,15 @@ class Deploy:
|
|
|
188
175
|
pass
|
|
189
176
|
return repos_status
|
|
190
177
|
|
|
178
|
+
def _tags_drifted(self, versions):
|
|
179
|
+
for country, version in versions.items():
|
|
180
|
+
for c, v in versions.items():
|
|
181
|
+
if country == c:
|
|
182
|
+
continue
|
|
183
|
+
if version is None or v is None or version.compare(v) != 0:
|
|
184
|
+
return True
|
|
185
|
+
return False
|
|
186
|
+
|
|
191
187
|
|
|
192
188
|
def _check_migrations_deploy(commits):
|
|
193
189
|
if not commits:
|
|
@@ -40,7 +40,6 @@ class Config:
|
|
|
40
40
|
conf["user"].setdefault("captainhook_timeout", 30)
|
|
41
41
|
conf["user"].setdefault("captainhook_url", "https://captainhook.prima.it")
|
|
42
42
|
conf["user"].setdefault("use_commits_in_pr_body", False)
|
|
43
|
-
conf["user"].setdefault("delete_qa_after_merge", True)
|
|
44
43
|
conf["user"].setdefault("frequent_reviewers_max_number", 5)
|
|
45
44
|
|
|
46
45
|
conf["youtrack"].setdefault("add_reviewers_tags", True)
|
|
@@ -52,13 +52,6 @@ class CaptainHook:
|
|
|
52
52
|
def get_users_list(self):
|
|
53
53
|
return self.send_get_request("/users/all")
|
|
54
54
|
|
|
55
|
-
def aggregators(self):
|
|
56
|
-
return self.send_get_request("/cloudflare/aggregators/available")
|
|
57
|
-
|
|
58
|
-
def change_aggregator(self, aggregator, qa_address):
|
|
59
|
-
data = {"aggregator": aggregator, "qa_address": qa_address}
|
|
60
|
-
return self.send_put_request("/cloudflare/aggregators", data)
|
|
61
|
-
|
|
62
55
|
def send_metrics(self, metrics):
|
|
63
56
|
self.send_post_request("/suite_py/metrics/", json=metrics).raise_for_status()
|
|
64
57
|
|