suite-py 1.52.0__tar.gz → 1.53.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.
Files changed (48) hide show
  1. {suite_py-1.52.0 → suite_py-1.53.0}/PKG-INFO +1 -1
  2. {suite_py-1.52.0 → suite_py-1.53.0}/pyproject.toml +1 -1
  3. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/__version__.py +1 -1
  4. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/ask_review.py +4 -6
  5. suite_py-1.53.0/suite_py/lib/handler/backstage_handler.py +167 -0
  6. suite_py-1.52.0/suite_py/lib/handler/backstage_handler.py +0 -82
  7. {suite_py-1.52.0 → suite_py-1.53.0}/LICENSE-APACHE +0 -0
  8. {suite_py-1.52.0 → suite_py-1.53.0}/LICENSE-MIT +0 -0
  9. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/__init__.py +0 -0
  10. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/cli.py +0 -0
  11. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/__init__.py +0 -0
  12. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/bump.py +0 -0
  13. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/check.py +0 -0
  14. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/common.py +0 -0
  15. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/context.py +0 -0
  16. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/create_branch.py +0 -0
  17. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/estimate_cone.py +0 -0
  18. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/login.py +0 -0
  19. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/merge_pr.py +0 -0
  20. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/open_pr.py +0 -0
  21. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/project_lock.py +0 -0
  22. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/release.py +0 -0
  23. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/set_token.py +0 -0
  24. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/commands/status.py +0 -0
  25. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/__init__.py +0 -0
  26. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/config.py +0 -0
  27. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/__init__.py +0 -0
  28. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/aws_handler.py +0 -0
  29. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/captainhook_handler.py +0 -0
  30. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/changelog_handler.py +0 -0
  31. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/frequent_reviewers_handler.py +0 -0
  32. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/git_handler.py +0 -0
  33. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/github_handler.py +0 -0
  34. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/metrics_handler.py +0 -0
  35. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/okta_handler.py +0 -0
  36. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/pre_commit_handler.py +0 -0
  37. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/prompt_utils.py +0 -0
  38. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/version_handler.py +0 -0
  39. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/handler/youtrack_handler.py +0 -0
  40. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/logger.py +0 -0
  41. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/metrics.py +0 -0
  42. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/oauth.py +0 -0
  43. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/requests/__init__.py +0 -0
  44. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/requests/auth.py +0 -0
  45. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/requests/session.py +0 -0
  46. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/symbol.py +0 -0
  47. {suite_py-1.52.0 → suite_py-1.53.0}/suite_py/lib/tokens.py +0 -0
  48. {suite_py-1.52.0 → suite_py-1.53.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.52.0
3
+ Version: 1.53.0
4
4
  Summary:
5
5
  Author: larrywax, EugenioLaghi, michelangelomo
6
6
  Author-email: devops@prima.it
@@ -2,7 +2,7 @@
2
2
  authors = ["larrywax, EugenioLaghi, michelangelomo <devops@prima.it>"]
3
3
  description = ""
4
4
  name = "suite-py"
5
- version = "1.52.0"
5
+ version = "1.53.0"
6
6
 
7
7
  [tool.poetry.dependencies]
8
8
  Click = ">=7.0"
@@ -1,2 +1,2 @@
1
1
  # -*- encoding: utf-8 -*-
2
- __version__ = "1.52.0"
2
+ __version__ = "1.53.0"
@@ -10,11 +10,11 @@ from suite_py.lib.handler.youtrack_handler import YoutrackHandler
10
10
 
11
11
 
12
12
  class AskReview:
13
- def __init__(self, project, captainhook, config, tokens):
13
+ def __init__(self, project, backstage, config, tokens):
14
14
  self._project = project
15
15
  self._config = config
16
16
  self._youtrack = YoutrackHandler(config, tokens)
17
- self._captainhook = captainhook
17
+ self._backstage = backstage
18
18
  self._git = GitHandler(project, config)
19
19
  self._github = GithubHandler(tokens)
20
20
  self._frequent_reviewers = FrequentReviewersHandler(config)
@@ -32,13 +32,11 @@ class AskReview:
32
32
 
33
33
  def _maybe_get_users_list(self):
34
34
  try:
35
- users = self._captainhook.get_users_list().json()
35
+ users = self._backstage.get_users_list()
36
36
  self._config.put_cache("users", users)
37
37
  return users
38
38
  except Exception:
39
- logger.warning(
40
- "Can't get users list from Captainhook. Using cached version."
41
- )
39
+ logger.warning("Can't get users list from Backstage. Using cached version.")
42
40
  return self._config.get_cache("users")
43
41
 
44
42
  def _get_pr(self):
@@ -0,0 +1,167 @@
1
+ # -*- encoding: utf-8 -*-
2
+ import ssl
3
+ from urllib.parse import urlparse
4
+
5
+ import requests
6
+ from suite_py.__version__ import __version__
7
+ from suite_py.lib.handler.github_handler import GithubHandler
8
+ from suite_py.lib.handler.okta_handler import Okta
9
+ from suite_py.lib import logger
10
+
11
+
12
+ class BackstageError(Exception): ...
13
+
14
+
15
+ class Backstage:
16
+ _okta: Okta
17
+ _github: GithubHandler
18
+
19
+ def __init__(self, config, okta: Okta, tokens=None):
20
+ self._backstage_url = config.user["backstage_url"]
21
+ self._timeout = config.user["backstage_timeout"]
22
+ self._backstage_identity_token = None
23
+
24
+ # Under mise cacert are loaded from ~/.local/share/mise
25
+ # so we need to force system defaults to make warp happy
26
+ self._verify = ssl.get_default_verify_paths().capath
27
+ self._okta = okta
28
+
29
+ if tokens is not None:
30
+ self._github = GithubHandler(tokens)
31
+
32
+ def lock_project(self, project, env):
33
+ return self._request(
34
+ method="post",
35
+ url=self._entity_locking_endpoint("/projects/manage-lock"),
36
+ headers=self._okta_headers(),
37
+ raise_for_status=True,
38
+ json={
39
+ "project": project,
40
+ "status": "locked",
41
+ "user": self._get_user(),
42
+ "environment": env,
43
+ },
44
+ )
45
+
46
+ def unlock_project(self, project, env):
47
+ return self._request(
48
+ method="post",
49
+ url=self._entity_locking_endpoint("/projects/manage-lock"),
50
+ headers=self._okta_headers(),
51
+ raise_for_status=True,
52
+ json={
53
+ "project": project,
54
+ "status": "unlocked",
55
+ "user": self._get_user(),
56
+ "environment": env,
57
+ },
58
+ )
59
+
60
+ def status(self, project, env):
61
+ return self._request(
62
+ method="get",
63
+ url=self._entity_locking_endpoint(
64
+ f"/projects/check?project={project}&environment={env}"
65
+ ),
66
+ raise_for_status=True,
67
+ )
68
+
69
+ def check(self):
70
+ response = self._request(
71
+ method="get",
72
+ url=self._entity_locking_endpoint("/ping"),
73
+ headers=self._okta_headers(),
74
+ timeout=(2, self._timeout),
75
+ raise_for_status=True,
76
+ )
77
+
78
+ assert response.text == "pong"
79
+
80
+ def get_users_list(self):
81
+ response = self._fetch_users()
82
+
83
+ if response.status_code == 401:
84
+ self._refresh_backstage_identity_token()
85
+ response = self._fetch_users()
86
+
87
+ response.raise_for_status()
88
+
89
+ return [
90
+ {"name": u.pop("displayName"), **u}
91
+ for u in (item["spec"]["profile"] for item in response.json()["items"])
92
+ if "github" in u and "youtrack" in u and "displayName" in u
93
+ ]
94
+
95
+ def _request(self, method, url, **kwargs):
96
+ timeout = kwargs.pop("timeout", self._timeout)
97
+ verify = kwargs.pop("verify", self._verify)
98
+ allow_redirects = kwargs.pop("allow_redirects", False)
99
+ raise_for_status = kwargs.pop("raise_for_status", False)
100
+
101
+ response = requests.request(
102
+ method=method,
103
+ url=url,
104
+ timeout=timeout,
105
+ verify=verify,
106
+ allow_redirects=allow_redirects,
107
+ **kwargs,
108
+ )
109
+
110
+ redirect = (
111
+ urlparse(response.headers["Location"])
112
+ if response.status_code == 302
113
+ else None
114
+ )
115
+
116
+ if redirect is not None and redirect.netloc == "prima.cloudflareaccess.com":
117
+ logger.error(
118
+ "It looks like Cloudflare WARP is not active, please enable it and try again"
119
+ )
120
+
121
+ raise BackstageError("Cloudflare Access authentication redirect")
122
+
123
+ if raise_for_status:
124
+ response.raise_for_status()
125
+
126
+ return response
127
+
128
+ def _entity_locking_endpoint(self, path):
129
+ return f"{self._backstage_url}{path}"
130
+
131
+ def _get_user(self):
132
+ return self._github.get_user().login
133
+
134
+ def _okta_headers(self):
135
+ return {
136
+ "User-Agent": f"suite-py/{__version__}",
137
+ "Authorization": f"Bearer {self._okta.get_id_token()}",
138
+ }
139
+
140
+ def _backstage_headers(self):
141
+ if self._backstage_identity_token is None:
142
+ self._refresh_backstage_identity_token()
143
+
144
+ return {
145
+ "User-Agent": f"suite-py/{__version__}",
146
+ "Authorization": f"Bearer {self._backstage_identity_token}",
147
+ }
148
+
149
+ def _fetch_users(self):
150
+ fields = ",".join(
151
+ f"spec.profile.{f}" for f in ("displayName", "youtrack", "slack", "github")
152
+ )
153
+
154
+ return self._request(
155
+ method="GET",
156
+ url=f"{self._backstage_url}/api/catalog/entities/by-query?filter=kind=user&fields={fields}&limit=500",
157
+ headers=self._backstage_headers(),
158
+ )
159
+
160
+ def _refresh_backstage_identity_token(self):
161
+ response = self._request(
162
+ method="GET",
163
+ url=f"{self._backstage_url}/api/auth/cfaccess/refresh",
164
+ raise_for_status=True,
165
+ )
166
+
167
+ self._backstage_identity_token = response.json()["backstageIdentity"]["token"]
@@ -1,82 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- import requests
3
-
4
- from suite_py.__version__ import __version__
5
- from suite_py.lib.handler.github_handler import GithubHandler
6
- from suite_py.lib.handler.okta_handler import Okta
7
-
8
-
9
- class BackstageResponseError(Exception): ...
10
-
11
-
12
- class Backstage:
13
- _okta: Okta
14
- _github: GithubHandler
15
-
16
- def __init__(self, config, okta: Okta, tokens=None):
17
- backstage_url = config.user["backstage_url"]
18
- self._baseurl = f"{backstage_url}/api/entity-locking"
19
- self._timeout = config.user["backstage_timeout"]
20
- self._okta = okta
21
-
22
- if tokens is not None:
23
- self._github = GithubHandler(tokens)
24
-
25
- def lock_project(self, project, env):
26
- return self.send_request(
27
- "post",
28
- "/projects/manage-lock",
29
- json={
30
- "project": project,
31
- "status": "locked",
32
- "user": self._get_user(),
33
- "environment": env,
34
- },
35
- )
36
-
37
- def unlock_project(self, project, env):
38
- return self.send_request(
39
- "post",
40
- "/projects/manage-lock",
41
- json={
42
- "project": project,
43
- "status": "unlocked",
44
- "user": self._get_user(),
45
- "environment": env,
46
- },
47
- )
48
-
49
- def status(self, project, env):
50
- return self.send_request(
51
- "get", f"/projects/check?project={project}&environment={env}"
52
- )
53
-
54
- def check(self):
55
- response = self.send_request("get", "/ping", timeout=(2, self._timeout))
56
- assert response.text == "pong"
57
-
58
- def send_request(self, method, endpoint, data=None, json=None, timeout=None):
59
- response = requests.request(
60
- method,
61
- f"{self._baseurl}{endpoint}",
62
- headers=self._headers(),
63
- data=data,
64
- json=json,
65
- timeout=(timeout or self._timeout),
66
- )
67
-
68
- if response.status_code == 200:
69
- return response
70
-
71
- raise BackstageResponseError(
72
- f"Got unexpected status code from Backstage: {response.status_code}"
73
- )
74
-
75
- def _get_user(self):
76
- return self._github.get_user().login
77
-
78
- def _headers(self):
79
- return {
80
- "User-Agent": f"suite-py/{__version__}",
81
- "Authorization": f"Bearer {self._okta.get_id_token()}",
82
- }
File without changes
File without changes
File without changes