suite-py 1.41.10__py3-none-any.whl → 1.42.1__py3-none-any.whl
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/__version__.py +1 -1
- suite_py/cli.py +6 -194
- suite_py/commands/check.py +0 -18
- suite_py/commands/merge_pr.py +1 -12
- suite_py/commands/open_pr.py +1 -6
- suite_py/commands/release.py +7 -251
- suite_py/lib/config.py +0 -1
- suite_py/lib/handler/captainhook_handler.py +0 -7
- suite_py/lib/handler/okta_handler.py +8 -4
- suite_py/lib/metrics.py +1 -1
- suite_py/lib/oauth.py +7 -3
- suite_py/lib/tokens.py +3 -7
- {suite_py-1.41.10.dist-info → suite_py-1.42.1.dist-info}/METADATA +4 -4
- {suite_py-1.41.10.dist-info → suite_py-1.42.1.dist-info}/RECORD +16 -26
- suite_py/commands/aggregator.py +0 -159
- suite_py/commands/batch_job.py +0 -215
- suite_py/commands/deploy.py +0 -207
- suite_py/commands/docker.py +0 -91
- suite_py/commands/generator.py +0 -238
- suite_py/commands/id.py +0 -60
- suite_py/commands/ip.py +0 -68
- suite_py/commands/secret.py +0 -204
- suite_py/lib/handler/drone_handler.py +0 -252
- suite_py/lib/handler/vault_handler.py +0 -28
- {suite_py-1.41.10.dist-info → suite_py-1.42.1.dist-info}/WHEEL +0 -0
- {suite_py-1.41.10.dist-info → suite_py-1.42.1.dist-info}/entry_points.txt +0 -0
suite_py/commands/deploy.py
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import re
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
from suite_py.commands import common
|
|
6
|
-
from suite_py.commands.release import _parse_available_countries
|
|
7
|
-
from suite_py.lib import logger, metrics
|
|
8
|
-
from suite_py.lib.handler import git_handler as git
|
|
9
|
-
from suite_py.lib.handler import prompt_utils
|
|
10
|
-
from suite_py.lib.handler.changelog_handler import ChangelogHandler
|
|
11
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
12
|
-
from suite_py.lib.handler.git_handler import GitHandler
|
|
13
|
-
from suite_py.lib.handler.github_handler import GithubHandler
|
|
14
|
-
from suite_py.lib.handler.version_handler import DEFAULT_VERSION, VersionHandler
|
|
15
|
-
from suite_py.lib.handler.youtrack_handler import YoutrackHandler
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Deploy:
|
|
19
|
-
# pylint: disable=too-many-instance-attributes
|
|
20
|
-
def __init__(self, project, captainhook, config, tokens):
|
|
21
|
-
self._project = project
|
|
22
|
-
self._config = config
|
|
23
|
-
self._youtrack = YoutrackHandler(config, tokens)
|
|
24
|
-
self._captainhook = captainhook
|
|
25
|
-
self._changelog_handler = ChangelogHandler()
|
|
26
|
-
self._github = GithubHandler(tokens)
|
|
27
|
-
self._repo = self._github.get_repo(project)
|
|
28
|
-
self._git = GitHandler(project, config)
|
|
29
|
-
self._drone = DroneHandler(config, tokens, repo=project)
|
|
30
|
-
self._countries = _parse_available_countries(self._drone)
|
|
31
|
-
self._version = VersionHandler(self._repo, self._git, self._github)
|
|
32
|
-
|
|
33
|
-
@metrics.command("deploy")
|
|
34
|
-
def run(self):
|
|
35
|
-
self._stop_if_prod_locked()
|
|
36
|
-
|
|
37
|
-
self._git.fetch()
|
|
38
|
-
|
|
39
|
-
if len(self._countries) > 0:
|
|
40
|
-
logger.error(
|
|
41
|
-
"Deploy command cannot be used on this project. Try to run `suite-py release` instead."
|
|
42
|
-
)
|
|
43
|
-
sys.exit(1)
|
|
44
|
-
|
|
45
|
-
current_version = self._version.get_latest_version()
|
|
46
|
-
|
|
47
|
-
if current_version != "":
|
|
48
|
-
logger.info(f"The current release is {current_version}")
|
|
49
|
-
commits = self._github.get_commits_since_release(
|
|
50
|
-
self._repo, current_version
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
_check_migrations_deploy(commits)
|
|
54
|
-
|
|
55
|
-
message = "\n".join(
|
|
56
|
-
[
|
|
57
|
-
"* "
|
|
58
|
-
+ c.commit.message.splitlines()[0]
|
|
59
|
-
+ " by "
|
|
60
|
-
+ c.commit.author.name
|
|
61
|
-
for c in commits
|
|
62
|
-
]
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
logger.info(f"\nCommits list:\n{message}\n")
|
|
66
|
-
|
|
67
|
-
if not prompt_utils.ask_confirm("Do you want to continue?"):
|
|
68
|
-
sys.exit()
|
|
69
|
-
|
|
70
|
-
new_version = self._version.select_new_version(
|
|
71
|
-
current_version, allow_prerelease=True, allow_custom_version=True
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
else:
|
|
75
|
-
# Se non viene trovata la release e non ci sono tag, viene saltato il check delle migrations e l'update delle card su youtrack
|
|
76
|
-
logger.warning(
|
|
77
|
-
f"No tags found, I'm about to push the tag {DEFAULT_VERSION}"
|
|
78
|
-
)
|
|
79
|
-
if not prompt_utils.ask_confirm(
|
|
80
|
-
"Are you sure you want to continue?", default=False
|
|
81
|
-
):
|
|
82
|
-
sys.exit()
|
|
83
|
-
new_version = DEFAULT_VERSION
|
|
84
|
-
message = f"First release with tag {new_version}"
|
|
85
|
-
|
|
86
|
-
if self._changelog_handler.changelog_exists():
|
|
87
|
-
(
|
|
88
|
-
latest_tag,
|
|
89
|
-
latest_entry,
|
|
90
|
-
) = self._changelog_handler.get_latest_entry_with_tag()
|
|
91
|
-
|
|
92
|
-
if latest_tag != new_version:
|
|
93
|
-
if not prompt_utils.ask_confirm(
|
|
94
|
-
"You didn't update your changelog, are you sure you want to proceed?"
|
|
95
|
-
):
|
|
96
|
-
sys.exit()
|
|
97
|
-
else:
|
|
98
|
-
message = f"{latest_entry}\n\n# Commits\n\n{message}"
|
|
99
|
-
|
|
100
|
-
message = common.ask_for_release_description(message)
|
|
101
|
-
|
|
102
|
-
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
|
-
|
|
118
|
-
def _create_release(self, new_version, message):
|
|
119
|
-
new_release = self._repo.create_git_release(
|
|
120
|
-
new_version,
|
|
121
|
-
new_version,
|
|
122
|
-
self._youtrack.replace_card_names_with_md_links(message),
|
|
123
|
-
)
|
|
124
|
-
if new_release:
|
|
125
|
-
logger.info(f"The release has been created! Link: {new_release.html_url}")
|
|
126
|
-
|
|
127
|
-
build_number = self._drone.get_build_number_from_tag(new_version)
|
|
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):
|
|
135
|
-
release_state = self._config.youtrack["release_state"]
|
|
136
|
-
|
|
137
|
-
issue_ids = self._youtrack.get_issue_ids(commits)
|
|
138
|
-
|
|
139
|
-
if len(issue_ids) > 0:
|
|
140
|
-
update_youtrack_state = prompt_utils.ask_confirm(
|
|
141
|
-
f"Do you want to move the associated cards to {release_state} state?",
|
|
142
|
-
default=False,
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
for issue_id in issue_ids:
|
|
146
|
-
try:
|
|
147
|
-
self._youtrack.comment(
|
|
148
|
-
issue_id,
|
|
149
|
-
f"Deploy in production of {self._project} done with the release {new_version}",
|
|
150
|
-
)
|
|
151
|
-
if update_youtrack_state:
|
|
152
|
-
self._youtrack.update_state(issue_id, release_state)
|
|
153
|
-
logger.info(f"{issue_id} moved to {release_state}")
|
|
154
|
-
except Exception:
|
|
155
|
-
logger.warning(
|
|
156
|
-
f"An error occurred while moving the card {issue_id} to {release_state}"
|
|
157
|
-
)
|
|
158
|
-
repos_status = self._get_repos_status_from_issue(issue_id)
|
|
159
|
-
if all(r["deployed"] for r in repos_status.values()):
|
|
160
|
-
try:
|
|
161
|
-
self._youtrack.update_deployed_field(issue_id)
|
|
162
|
-
logger.info("Custom field Deployed updated on YouTrack")
|
|
163
|
-
except Exception:
|
|
164
|
-
logger.warning(
|
|
165
|
-
"An error occurred while updating the custom field Deployed"
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
def _get_repos_status_from_issue(self, issue_id):
|
|
169
|
-
regex_pr = r"^PR .* -> https:\/\/github\.com\/primait\/(.*)\/pull\/([0-9]*)$"
|
|
170
|
-
regex_deploy = r"^Deploy in production of (.*) done with the release"
|
|
171
|
-
comments = self._youtrack.get_comments(issue_id)
|
|
172
|
-
repos_status = {}
|
|
173
|
-
|
|
174
|
-
for c in comments:
|
|
175
|
-
m = re.match(regex_pr, c["text"])
|
|
176
|
-
if m:
|
|
177
|
-
project = m.group(1)
|
|
178
|
-
pr_number = int(m.group(2))
|
|
179
|
-
repos_status[project] = {}
|
|
180
|
-
repos_status[project]["pr"] = pr_number
|
|
181
|
-
repos_status[project]["deployed"] = False
|
|
182
|
-
m = re.match(regex_deploy, c["text"])
|
|
183
|
-
if m:
|
|
184
|
-
project = m.group(1)
|
|
185
|
-
try:
|
|
186
|
-
repos_status[project]["deployed"] = True
|
|
187
|
-
except Exception:
|
|
188
|
-
pass
|
|
189
|
-
return repos_status
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
def _check_migrations_deploy(commits):
|
|
193
|
-
if not commits:
|
|
194
|
-
logger.error("ERROR: no commit found")
|
|
195
|
-
sys.exit(-1)
|
|
196
|
-
elif len(commits) == 1:
|
|
197
|
-
files_changed = git.files_changed_between_commits("--raw", f"{commits[0].sha}~")
|
|
198
|
-
else:
|
|
199
|
-
files_changed = git.files_changed_between_commits(
|
|
200
|
-
f"{commits[-1].sha}~", commits[0].sha
|
|
201
|
-
)
|
|
202
|
-
if git.migrations_found(files_changed):
|
|
203
|
-
logger.warning("WARNING: migrations detected in the code")
|
|
204
|
-
if not prompt_utils.ask_confirm(
|
|
205
|
-
"Are you sure you want to continue?", default=False
|
|
206
|
-
):
|
|
207
|
-
sys.exit()
|
suite_py/commands/docker.py
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
from halo import Halo
|
|
5
|
-
|
|
6
|
-
from suite_py.lib import logger, metrics
|
|
7
|
-
from suite_py.lib.handler import prompt_utils
|
|
8
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
9
|
-
from suite_py.lib.handler.git_handler import GitHandler
|
|
10
|
-
from suite_py.lib.handler.github_handler import GithubHandler
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Docker:
|
|
14
|
-
# pylint: disable=too-many-instance-attributes
|
|
15
|
-
def __init__(self, action, project, config, tokens, flags=None):
|
|
16
|
-
self._action = action
|
|
17
|
-
self._project = project
|
|
18
|
-
self._flags = flags
|
|
19
|
-
self._config = config
|
|
20
|
-
self._tokens = tokens
|
|
21
|
-
self._github = GithubHandler(tokens)
|
|
22
|
-
self._repo = self._github.get_repo(project)
|
|
23
|
-
self._git = GitHandler(project, config)
|
|
24
|
-
self._drone = DroneHandler(config, tokens, repo=project)
|
|
25
|
-
|
|
26
|
-
@metrics.command("docker")
|
|
27
|
-
def run(self):
|
|
28
|
-
if self._project != "docker":
|
|
29
|
-
logger.error("`suite-py docker` must run inside docker repository.")
|
|
30
|
-
sys.exit(-1)
|
|
31
|
-
|
|
32
|
-
self._git.fetch()
|
|
33
|
-
|
|
34
|
-
pipelines = self._drone.parse_yaml()
|
|
35
|
-
|
|
36
|
-
if pipelines is None:
|
|
37
|
-
logger.error("The file .drone.yml not found.")
|
|
38
|
-
sys.exit(1)
|
|
39
|
-
|
|
40
|
-
images = []
|
|
41
|
-
for pipeline in pipelines:
|
|
42
|
-
if "trigger" not in pipeline or "ref" not in pipeline["trigger"]:
|
|
43
|
-
continue
|
|
44
|
-
|
|
45
|
-
trigger_tags = pipeline["trigger"]["ref"]
|
|
46
|
-
|
|
47
|
-
for tag in trigger_tags:
|
|
48
|
-
images.append(tag.replace("refs/tags/", ""))
|
|
49
|
-
|
|
50
|
-
image = prompt_utils.ask_choices(
|
|
51
|
-
"Select an image",
|
|
52
|
-
images,
|
|
53
|
-
)
|
|
54
|
-
versions = self._get_versions(image)
|
|
55
|
-
|
|
56
|
-
if self._action == "release":
|
|
57
|
-
print_versions(versions)
|
|
58
|
-
new_version = self._ask_new_version(image)
|
|
59
|
-
self._create_new_version(new_version)
|
|
60
|
-
|
|
61
|
-
elif self._action == "versions":
|
|
62
|
-
print_versions(versions)
|
|
63
|
-
|
|
64
|
-
def _create_new_version(self, version):
|
|
65
|
-
if prompt_utils.ask_confirm(f"Tag {version} will be deployed. Confirm?"):
|
|
66
|
-
self._git.tag(version, version)
|
|
67
|
-
self._git.push(version)
|
|
68
|
-
|
|
69
|
-
def _ask_new_version(self, image):
|
|
70
|
-
new = prompt_utils.ask_questions_input(
|
|
71
|
-
"Write new version to be deployed (eg: 11.3-1):"
|
|
72
|
-
)
|
|
73
|
-
if new[0] == "v":
|
|
74
|
-
logger.error("Insert new version without `v`")
|
|
75
|
-
sys.exit(-1)
|
|
76
|
-
return f'{image.replace("*", "")}{new}'
|
|
77
|
-
|
|
78
|
-
def _get_versions(self, image):
|
|
79
|
-
versions = []
|
|
80
|
-
with Halo(text="Retrieving tags...", spinner="dots", color="magenta"):
|
|
81
|
-
tags = self._github.get_tags("docker")
|
|
82
|
-
for tag in tags:
|
|
83
|
-
if image.replace("*", "") in tag.name:
|
|
84
|
-
versions.append(tag)
|
|
85
|
-
return versions
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def print_versions(versions):
|
|
89
|
-
message = "\n".join(["* " + v.name for v in versions])
|
|
90
|
-
|
|
91
|
-
logger.info(f"\nVersions list:\n{message}\n")
|
suite_py/commands/generator.py
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import os
|
|
3
|
-
import stat
|
|
4
|
-
import subprocess
|
|
5
|
-
from datetime import datetime
|
|
6
|
-
from os import listdir
|
|
7
|
-
from os.path import isfile, join
|
|
8
|
-
|
|
9
|
-
import yaml
|
|
10
|
-
from jinja2 import DebugUndefined, Environment, FileSystemLoader
|
|
11
|
-
|
|
12
|
-
from suite_py.lib import logger, metrics
|
|
13
|
-
from suite_py.lib.handler import prompt_utils
|
|
14
|
-
from suite_py.lib.handler.drone_handler import DroneHandler
|
|
15
|
-
from suite_py.lib.handler.git_handler import GitHandler
|
|
16
|
-
from suite_py.lib.handler.github_handler import GithubHandler
|
|
17
|
-
|
|
18
|
-
NOW = datetime.now().strftime("%Y%m%d%H%M")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class Generator:
|
|
22
|
-
def __init__(self, project, config, tokens):
|
|
23
|
-
self._project = project
|
|
24
|
-
self._config = config
|
|
25
|
-
self._tokens = tokens
|
|
26
|
-
self._umami_path = os.path.join(config.user["projects_home"], "umami")
|
|
27
|
-
self._drone_values_path = f"{self._umami_path}/templates/drone/values/"
|
|
28
|
-
self._deploy_scripts_values_path = (
|
|
29
|
-
f"{self._umami_path}/templates/scripts/values/"
|
|
30
|
-
)
|
|
31
|
-
self._github = GithubHandler(tokens)
|
|
32
|
-
|
|
33
|
-
@metrics.command("generator")
|
|
34
|
-
def run(self):
|
|
35
|
-
|
|
36
|
-
logger.warning(
|
|
37
|
-
"This command requires shellcheck and shfmt, please install these tools before continuing"
|
|
38
|
-
)
|
|
39
|
-
logger.warning(
|
|
40
|
-
"see https://github.com/koalaman/shellcheck#installing and https://github.com/mvdan/sh#shfmt for installation"
|
|
41
|
-
)
|
|
42
|
-
# move to umami root directory
|
|
43
|
-
os.chdir(self._umami_path)
|
|
44
|
-
|
|
45
|
-
env = Environment(
|
|
46
|
-
loader=FileSystemLoader(self._umami_path),
|
|
47
|
-
undefined=DebugUndefined,
|
|
48
|
-
trim_blocks=True,
|
|
49
|
-
lstrip_blocks=True,
|
|
50
|
-
)
|
|
51
|
-
env.filters["to_yaml"] = to_yaml
|
|
52
|
-
env.add_extension("jinja2.ext.do")
|
|
53
|
-
|
|
54
|
-
template_type = prompt_utils.ask_choices(
|
|
55
|
-
"What files do you want to generate?", ["drone", "deploy_scripts"]
|
|
56
|
-
)
|
|
57
|
-
commit_message = f"Autogenerated update {template_type} from suite-py {NOW}"
|
|
58
|
-
|
|
59
|
-
autobranch = prompt_utils.ask_confirm(
|
|
60
|
-
"Do you want to create branch and PR automatically?", default=False
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
if autobranch:
|
|
64
|
-
autopush = True
|
|
65
|
-
else:
|
|
66
|
-
autopush = prompt_utils.ask_confirm(
|
|
67
|
-
"Do you want to push automatically?", default=False
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
choice = prompt_utils.ask_questions_input(
|
|
71
|
-
"What project do you want to work on? Enter `all` to select them all: ",
|
|
72
|
-
self._project,
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
if choice == "all":
|
|
76
|
-
projects = self._get_all_templated_projects(template_type)
|
|
77
|
-
else:
|
|
78
|
-
projects = choice.split(" ")
|
|
79
|
-
|
|
80
|
-
skipped = []
|
|
81
|
-
for project in projects:
|
|
82
|
-
logger.info(f"{project}: Checking if there are no uncommitted files")
|
|
83
|
-
git = GitHandler(project, self._config)
|
|
84
|
-
git.check_repo_cloned()
|
|
85
|
-
if git.is_dirty():
|
|
86
|
-
if not prompt_utils.ask_confirm(
|
|
87
|
-
f"{project}: There are changes already present, do you want to continue anyway?",
|
|
88
|
-
default=False,
|
|
89
|
-
):
|
|
90
|
-
logger.error(f"{project}: skipping the project")
|
|
91
|
-
skipped.append(project)
|
|
92
|
-
continue
|
|
93
|
-
|
|
94
|
-
branch_name = _configure_branch(git, template_type, autobranch, autopush)
|
|
95
|
-
|
|
96
|
-
logger.info(f"{project}: Creation in progress")
|
|
97
|
-
# launch generate
|
|
98
|
-
if template_type == "drone":
|
|
99
|
-
self._generate_drone(
|
|
100
|
-
project, f"{self._drone_values_path}{project}.yml", env
|
|
101
|
-
)
|
|
102
|
-
elif template_type == "deploy_scripts":
|
|
103
|
-
_generate_build_script(
|
|
104
|
-
git.get_path(),
|
|
105
|
-
f"{self._deploy_scripts_values_path}{project}.yml",
|
|
106
|
-
env,
|
|
107
|
-
)
|
|
108
|
-
_generate_deploy_script(
|
|
109
|
-
git.get_path(),
|
|
110
|
-
f"{self._deploy_scripts_values_path}{project}.yml",
|
|
111
|
-
env,
|
|
112
|
-
)
|
|
113
|
-
logger.info(f"{project}: Creation completed")
|
|
114
|
-
|
|
115
|
-
if autobranch or autopush:
|
|
116
|
-
# controllo che sia cambiato effettivamente qualcosa
|
|
117
|
-
if git.is_dirty(untracked=True):
|
|
118
|
-
self._git_operations(
|
|
119
|
-
git, autobranch, autopush, branch_name, commit_message
|
|
120
|
-
)
|
|
121
|
-
else:
|
|
122
|
-
logger.warning(
|
|
123
|
-
f"{project}: no git operations to do. No files modified"
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
logger.warning(f"Skipped projects: {skipped}")
|
|
127
|
-
|
|
128
|
-
def _get_all_templated_projects(self, template_type):
|
|
129
|
-
if template_type == "drone":
|
|
130
|
-
values_path = self._drone_values_path
|
|
131
|
-
elif template_type == "deploy_scripts":
|
|
132
|
-
values_path = self._deploy_scripts_values_path
|
|
133
|
-
|
|
134
|
-
return [
|
|
135
|
-
f.replace(".yml", "")
|
|
136
|
-
for f in listdir(values_path)
|
|
137
|
-
if isfile(join(values_path, f))
|
|
138
|
-
]
|
|
139
|
-
|
|
140
|
-
def _git_operations(self, git, autobranch, autopush, branch_name, message):
|
|
141
|
-
if autobranch:
|
|
142
|
-
logger.info(f"{git.get_repo()}: creating branch {branch_name}")
|
|
143
|
-
git.checkout(branch_name, new=True)
|
|
144
|
-
git.add()
|
|
145
|
-
git.commit(message)
|
|
146
|
-
git.push(branch_name)
|
|
147
|
-
pr = self._github.create_pr(git.get_repo(), branch_name, message)
|
|
148
|
-
logger.info(f"Pull request with number {pr.number} created! {pr.html_url}")
|
|
149
|
-
elif autopush:
|
|
150
|
-
if git.current_branch_name() != "master":
|
|
151
|
-
git.add()
|
|
152
|
-
git.commit(message)
|
|
153
|
-
git.push(branch_name)
|
|
154
|
-
else:
|
|
155
|
-
logger.warning(
|
|
156
|
-
f"{git.get_repo()} is on master, skipping automatic push"
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
def _generate_drone(self, project, values_file, env):
|
|
160
|
-
values = yaml.safe_load(open(values_file, encoding="utf-8"))
|
|
161
|
-
template = env.get_template(f"templates/drone/{values['template']}.j2")
|
|
162
|
-
rendered = template.render(values)
|
|
163
|
-
|
|
164
|
-
_write_on_repo(
|
|
165
|
-
os.path.join(self._config.user["projects_home"], project),
|
|
166
|
-
rendered,
|
|
167
|
-
".drone.yml",
|
|
168
|
-
)
|
|
169
|
-
drone = DroneHandler(self._config, self._tokens, repo=project)
|
|
170
|
-
drone.fmt()
|
|
171
|
-
drone.validate()
|
|
172
|
-
drone.sign()
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def _configure_branch(git, template_type, autobranch, autopush):
|
|
176
|
-
logger.info(f"{git.get_repo()}: Synchronizing the repo with the remote")
|
|
177
|
-
if autobranch:
|
|
178
|
-
git.sync() # fa anche checkout su master
|
|
179
|
-
return f"t/autogenerated_update_{template_type}_{NOW}"
|
|
180
|
-
|
|
181
|
-
current_branch = git.current_branch_name()
|
|
182
|
-
if autopush and git.remote_branch_exists(current_branch):
|
|
183
|
-
git.fetch()
|
|
184
|
-
git.pull()
|
|
185
|
-
|
|
186
|
-
return current_branch
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
def _generate_build_script(project_path, values_file, env):
|
|
190
|
-
file_name = "build"
|
|
191
|
-
values = yaml.safe_load(open(values_file, encoding="utf-8"))
|
|
192
|
-
|
|
193
|
-
val = {**values["info"], **values["build"]}
|
|
194
|
-
template = env.get_template(f"templates/scripts/build/{val['template']}")
|
|
195
|
-
rendered = template.render(val)
|
|
196
|
-
|
|
197
|
-
_write_on_repo(os.path.join(project_path, "deploy"), rendered, file_name)
|
|
198
|
-
_format_script(f"{project_path}/deploy/{file_name}")
|
|
199
|
-
_validate_script(f"{project_path}/deploy/{file_name}")
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def _generate_deploy_script(project_path, values_file, env):
|
|
203
|
-
values = yaml.safe_load(open(values_file, encoding="utf-8"))
|
|
204
|
-
|
|
205
|
-
for country, country_props in values["deploy"].items():
|
|
206
|
-
val = {**values["info"], **country_props}
|
|
207
|
-
template = env.get_template("templates/scripts/deploy/base.j2")
|
|
208
|
-
rendered = template.render(val)
|
|
209
|
-
file_name = f"deploy-{country}"
|
|
210
|
-
_write_on_repo(os.path.join(project_path, "deploy"), rendered, file_name)
|
|
211
|
-
_format_script(f"{project_path}/deploy/{file_name}")
|
|
212
|
-
_validate_script(f"{project_path}/deploy/{file_name}")
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
def _write_on_repo(path, rendered, file_name):
|
|
216
|
-
if not os.path.exists(path):
|
|
217
|
-
os.mkdir(path, mode=0o755)
|
|
218
|
-
|
|
219
|
-
with open(os.path.join(path, file_name), "w", encoding="utf-8") as fd:
|
|
220
|
-
fd.write(rendered)
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
def _format_script(filepath):
|
|
224
|
-
subprocess.run(["shfmt", "-i", "2", "-l", "-w", filepath], check=True)
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def _validate_script(filepath):
|
|
228
|
-
_make_executable(filepath)
|
|
229
|
-
subprocess.run(["shellcheck", filepath], check=True)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def _make_executable(filepath):
|
|
233
|
-
st = os.stat(filepath)
|
|
234
|
-
os.chmod(filepath, st.st_mode | stat.S_IEXEC)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def to_yaml(d, indent=10):
|
|
238
|
-
return yaml.dump(d, indent=indent)
|
suite_py/commands/id.py
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import re
|
|
3
|
-
|
|
4
|
-
from pptree import Node, print_tree
|
|
5
|
-
|
|
6
|
-
from suite_py.lib import logger, metrics
|
|
7
|
-
from suite_py.lib.handler.aws_handler import Aws
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ID:
|
|
11
|
-
def __init__(self, project, config, env):
|
|
12
|
-
self._project = project
|
|
13
|
-
self._env = env
|
|
14
|
-
self._aws = Aws(config)
|
|
15
|
-
|
|
16
|
-
@metrics.command("id")
|
|
17
|
-
def run(self):
|
|
18
|
-
|
|
19
|
-
clusters_names = self._aws.get_ecs_clusters(self._env)
|
|
20
|
-
n_services = Node("services")
|
|
21
|
-
|
|
22
|
-
projects = {"prima": ["web", "consumer-api"], "ab_normal": ["abnormal"]}
|
|
23
|
-
project_names = projects.get(self._project, [self._project])
|
|
24
|
-
|
|
25
|
-
for cluster_name in clusters_names:
|
|
26
|
-
|
|
27
|
-
services = []
|
|
28
|
-
all_services = self._aws.get_ecs_services(cluster_name)
|
|
29
|
-
|
|
30
|
-
for service in all_services:
|
|
31
|
-
if service["status"] == "ACTIVE":
|
|
32
|
-
for prj in project_names:
|
|
33
|
-
if prj in service["serviceName"]:
|
|
34
|
-
services.append(service["serviceName"])
|
|
35
|
-
|
|
36
|
-
for service in services:
|
|
37
|
-
container_instances = []
|
|
38
|
-
container_instances = (
|
|
39
|
-
self._aws.get_container_instances_arn_from_service(
|
|
40
|
-
cluster_name, service
|
|
41
|
-
)
|
|
42
|
-
)
|
|
43
|
-
if container_instances:
|
|
44
|
-
ids = self._aws.get_ids_from_container_instances(
|
|
45
|
-
cluster_name, container_instances
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
m = re.search(f"ecs-task-.*-{self._env}-ECSService(.*)-.*", service)
|
|
49
|
-
if m:
|
|
50
|
-
n_service = Node(m.group(1), n_services)
|
|
51
|
-
for _id in ids:
|
|
52
|
-
Node(_id, n_service)
|
|
53
|
-
|
|
54
|
-
if n_services.children:
|
|
55
|
-
print_tree(n_services, horizontal=True)
|
|
56
|
-
else:
|
|
57
|
-
logger.info(
|
|
58
|
-
f"No active tasks for {self._project} in environment {self._env}"
|
|
59
|
-
)
|
|
60
|
-
logger.info("Done!")
|
suite_py/commands/ip.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
import os
|
|
3
|
-
import re
|
|
4
|
-
|
|
5
|
-
from pptree import Node, print_tree
|
|
6
|
-
|
|
7
|
-
from suite_py.lib import logger, metrics
|
|
8
|
-
from suite_py.lib.handler.aws_handler import Aws
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class IP:
|
|
12
|
-
def __init__(self, project, config, env):
|
|
13
|
-
self._project = project
|
|
14
|
-
self._env = env
|
|
15
|
-
self._aws = Aws(config)
|
|
16
|
-
|
|
17
|
-
@metrics.command("ip")
|
|
18
|
-
def run(self):
|
|
19
|
-
|
|
20
|
-
clusters_names = self._aws.get_ecs_clusters(self._env)
|
|
21
|
-
n_services = Node("services")
|
|
22
|
-
|
|
23
|
-
projects = {"prima": ["web", "consumer-api"], "ab_normal": ["abnormal"]}
|
|
24
|
-
project_names = projects.get(self._project, [self._project])
|
|
25
|
-
|
|
26
|
-
for cluster_name in clusters_names:
|
|
27
|
-
|
|
28
|
-
services = []
|
|
29
|
-
all_services = self._aws.get_ecs_services(cluster_name)
|
|
30
|
-
|
|
31
|
-
for service in all_services:
|
|
32
|
-
if service["status"] == "ACTIVE":
|
|
33
|
-
for prj in project_names:
|
|
34
|
-
if prj in service["serviceName"]:
|
|
35
|
-
services.append(service["serviceName"])
|
|
36
|
-
|
|
37
|
-
for service in services:
|
|
38
|
-
container_instances = []
|
|
39
|
-
container_instances = (
|
|
40
|
-
self._aws.get_container_instances_arn_from_service(
|
|
41
|
-
cluster_name, service
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
if container_instances:
|
|
45
|
-
ips = self._aws.get_ips_from_container_instances(
|
|
46
|
-
cluster_name, container_instances
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
m = re.search(f"ecs-task-.*-{self._env}-ECSService(.*)-.*", service)
|
|
50
|
-
if m:
|
|
51
|
-
n_service = Node(m.group(1), n_services)
|
|
52
|
-
for ip in ips:
|
|
53
|
-
Node(ip, n_service)
|
|
54
|
-
|
|
55
|
-
if self._env == "staging" and os.path.isfile("./deploy/values/staging.yml"):
|
|
56
|
-
logger.info(
|
|
57
|
-
"This project has been migrated on k8s, command is no longer available."
|
|
58
|
-
)
|
|
59
|
-
logger.info(
|
|
60
|
-
"Please use k8s to open a shell to a staging pod, see: https://www.notion.so/K8s-tips-2f8b3fed72334362af0de0298845756d"
|
|
61
|
-
)
|
|
62
|
-
elif n_services.children:
|
|
63
|
-
print_tree(n_services, horizontal=True)
|
|
64
|
-
else:
|
|
65
|
-
logger.info(
|
|
66
|
-
f"No active tasks for {self._project} in environment {self._env}"
|
|
67
|
-
)
|
|
68
|
-
logger.info("Done!")
|