suite-py 1.42.2__py3-none-any.whl → 1.43.0__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 CHANGED
@@ -1,2 +1,2 @@
1
1
  # -*- encoding: utf-8 -*-
2
- __version__ = "1.42.2"
2
+ __version__ = "1.43.0"
suite_py/cli.py CHANGED
@@ -49,6 +49,7 @@ from suite_py.lib.handler import git_handler as git
49
49
  from suite_py.lib.handler import prompt_utils
50
50
  from suite_py.lib.handler.captainhook_handler import CaptainHook
51
51
  from suite_py.lib.handler.okta_handler import Okta
52
+ from suite_py.lib.handler.pre_commit_handler import PreCommit
52
53
  from suite_py.lib.tokens import Tokens
53
54
 
54
55
  # pylint: enable=wrong-import-position
@@ -195,6 +196,9 @@ def main(ctx, project, timeout, verbose):
195
196
  or ctx.invoked_subcommand not in ALLOW_NO_HOME_SUBCOMMAND
196
197
  ):
197
198
  os.chdir(os.path.join(config.user["projects_home"], ctx.obj.project))
199
+ # Warn on missing pre_commit hook
200
+ if ctx.invoked_subcommand not in ALLOW_NO_GIT_SUBCOMMAND:
201
+ ctx.obj.call(PreCommit).check_and_warn()
198
202
 
199
203
 
200
204
  @main.result_callback()
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  import requests
3
3
 
4
+ from suite_py.__version__ import __version__
4
5
  from suite_py.lib.handler.github_handler import GithubHandler
5
6
  from suite_py.lib.handler.okta_handler import Okta
6
- from suite_py.__version__ import __version__
7
7
 
8
8
 
9
9
  class UnauthorizedError(Exception):
@@ -269,6 +269,45 @@ class GitHandler:
269
269
  logger.error(f"Error during git reset on {self._repo}: {e}")
270
270
  sys.exit(-1)
271
271
 
272
+ def get_git_config(self, option):
273
+ """
274
+ Get git config value.
275
+ Git configs are very versitile and allow arbitrary string KV pairs to be stored,
276
+ support per-repo, or more complex conditional and global configurations,
277
+ making it the perfect place for us to store a lot of our configs.
278
+ """
279
+ proc = subprocess.run(
280
+ ["git", "config", "get", option],
281
+ cwd=self._path,
282
+ check=False,
283
+ capture_output=True,
284
+ )
285
+ if proc.returncode == 0:
286
+ return proc.stdout.decode().strip()
287
+ return None
288
+
289
+ def hooks_path(self):
290
+ """
291
+ Get path to git-hooks
292
+ See: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks for more details
293
+ """
294
+ try:
295
+ proc = subprocess.run(
296
+ ["git", "rev-parse", "--git-path", "hooks"],
297
+ cwd=self._path,
298
+ check=True,
299
+ capture_output=True,
300
+ )
301
+ hooks = proc.stdout.decode().strip()
302
+
303
+ # Return absolute path to the hooks dir,
304
+ # since we overwrite the subprocesses cwd.
305
+ abs_path = os.path.join(self._path, hooks)
306
+ return abs_path
307
+ except CalledProcessError as e:
308
+ logger.error(f"Error getting hooks path {self._repo}: {e}")
309
+ sys.exit(-1)
310
+
272
311
 
273
312
  def get_root_folder(directory):
274
313
  return (
@@ -0,0 +1,95 @@
1
+ import os
2
+ import yaml
3
+
4
+ from suite_py.lib import logger
5
+ from suite_py.lib.config import Config
6
+ from suite_py.lib.handler.git_handler import GitHandler
7
+
8
+
9
+ class PreCommit:
10
+ """
11
+ Handler checking whether the user has the prima pre-commit hooks setup and print a warning if they are missing
12
+ """
13
+
14
+ def __init__(self, project: str, config: Config):
15
+ self._git = GitHandler(project, config)
16
+
17
+ def check_and_warn(self):
18
+ if self.is_enabled() and not self.is_pre_commit_hooks_installed():
19
+ self.warn_missing_pre_commit_hook()
20
+
21
+ def is_pre_commit_hooks_installed(self):
22
+ """
23
+ Apply some heuteristics to check whether the gitleaks pre-commit hook is installed.
24
+ This is extremely imperfect, and only supports direct calls in shell scripts.
25
+ More hooks, like husky should be added later
26
+ """
27
+ return self.is_vanilla_hook_setup() or self.is_pre_commit_py_hook_setup()
28
+
29
+ def warn_missing_pre_commit_hook(self):
30
+ logger.warning(
31
+ """
32
+ Looks like the current repo is missing the gitleaks pre-commit hook!
33
+ Please install it per the security guide:
34
+ https://www.notion.so/helloprima/Install-Gitleaks-pre-commit-hook-aaaa6beafafa4c298b537afcb52bb25a
35
+
36
+ If you have installed them already you can report the false positive to team-platform-shared-services (on Slack) and run:
37
+ git config suite-py.disable-pre-commit-warning true
38
+ to disable the check for this repo, or
39
+ git config --global suite-py.disable-pre-commit-warning true
40
+ to disable it globally
41
+ """
42
+ )
43
+
44
+ def is_vanilla_hook_setup(self):
45
+ """
46
+ Check whether the gitleaks hook is setup as a regular bash script
47
+ """
48
+ pre_commit_file = self.read_pre_commit_hook()
49
+
50
+ # Assume everything is a shell script.
51
+ # Technically you could use a binary, or even python code,
52
+ # But those are out of scope for us, and the user should just disable the warning themselves
53
+ lines = pre_commit_file.splitlines()
54
+
55
+ # Filter out lines that start with '#' since those are probably just comments.
56
+ without_comments = filter(lambda l: not l.strip().startswith("#"), lines)
57
+
58
+ return any("gitleaks" in line for line in without_comments)
59
+
60
+ def is_pre_commit_py_hook_setup(self):
61
+ """
62
+ Check whether the gitleaks hook is setup with the pre-commit python framework
63
+ """
64
+ # If the framework is not setup skip
65
+ if "pre-commit" not in self.read_pre_commit_hook():
66
+ logger.debug("pre-commit.com not installed, skipping config check")
67
+ return False
68
+
69
+ config_path = os.path.join(self._git.get_path(), ".pre-commit-config.yaml")
70
+ try:
71
+ with open(config_path, encoding="utf-8") as f:
72
+ config = yaml.safe_load(f)
73
+ except FileNotFoundError:
74
+ logger.debug("pre-commit config file(%s) not found", config_path)
75
+ return False
76
+ except yaml.YAMLError:
77
+ logger.warning(".pre-commit-config.yaml file is invalid!", exc_info=True)
78
+ return False
79
+
80
+ return any(
81
+ repo.get("repo", "") == "git@github.com:primait/security-hooks.git"
82
+ for repo in config.get("repos", [])
83
+ )
84
+
85
+ def read_pre_commit_hook(self):
86
+ pre_commit_file_path = os.path.join(self._git.hooks_path(), "pre-commit")
87
+ logger.debug("Reading pre-commit script from %s", pre_commit_file_path)
88
+ try:
89
+ with open(pre_commit_file_path, encoding="utf-8") as f:
90
+ return f.read()
91
+ except FileNotFoundError:
92
+ return ""
93
+
94
+ def is_enabled(self):
95
+ return self._git.get_git_config("suite-py.disable-pre-commit-warning") != "true"
suite_py/lib/metrics.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  import functools
3
- from suite_py.lib.config import Config
4
3
 
4
+ from suite_py.lib.config import Config
5
5
  from suite_py.lib.handler.captainhook_handler import CaptainHook
6
6
  from suite_py.lib.handler.metrics_handler import Metrics
7
7
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: suite-py
3
- Version: 1.42.2
3
+ Version: 1.43.0
4
4
  Summary:
5
5
  Author: larrywax, EugenioLaghi, michelangelomo
6
6
  Author-email: devops@prima.it
@@ -39,4 +39,4 @@ Requires-Dist: requests-toolbelt (>=0.9.1)
39
39
  Requires-Dist: rich (==13.9.2)
40
40
  Requires-Dist: semver (>=2.13.0,<3.0.0)
41
41
  Requires-Dist: termcolor (>=1.1.0)
42
- Requires-Dist: truststore (>=0.7,<0.10) ; python_version >= "3.10"
42
+ Requires-Dist: truststore (>=0.7,<0.11) ; python_version >= "3.10"
@@ -1,6 +1,6 @@
1
1
  suite_py/__init__.py,sha256=REmi3D0X2G1ZWnYpKs8Ffm3NIj-Hw6dMuvz2b9NW344,142
2
- suite_py/__version__.py,sha256=epapGv8LINFClZsTAecNa7bKBm9IBjycsyHCcdVZdlc,49
3
- suite_py/cli.py,sha256=iJDqnKEPuvbX7OBawtkW38T_37xLFktohFz1YBjPUbs,10047
2
+ suite_py/__version__.py,sha256=ieZXcKFUSr3HB9yG_7H6w0LtkWcCWwTjzJFoXitR7tQ,49
3
+ suite_py/cli.py,sha256=sgJAT5ofSw4dCSVPtiatWaPrrMJdLSstsDiVcyl2IAE,10258
4
4
  suite_py/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  suite_py/commands/ask_review.py,sha256=yN__Ac-fiZBPShjRDhyCCQZGfVlQE16KozoJk4UtiNw,3788
6
6
  suite_py/commands/bump.py,sha256=oFZU1hPfD11ujFC5G7wFyQOf2alY3xp2SO1h1ldjf3s,5406
@@ -19,18 +19,19 @@ suite_py/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  suite_py/lib/config.py,sha256=52YV0K0GK1WRbeM70IDXkpG8oZD1Zvxipn1b-XekwNA,3907
20
20
  suite_py/lib/handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  suite_py/lib/handler/aws_handler.py,sha256=dRvRDicikfRbuFtCLPbevaX-yC-fO4LwXFdyqLPJ8OI,8815
22
- suite_py/lib/handler/captainhook_handler.py,sha256=sp1dxZXO1QJaq304JhtkTrQjn8Z4971e2uFTM7Dh5wg,2983
22
+ suite_py/lib/handler/captainhook_handler.py,sha256=R30_Vvh2ck7fM5fwbpm3UV_FtlQr2xnx6RJpkG1Gn14,2983
23
23
  suite_py/lib/handler/changelog_handler.py,sha256=-ppnRl3smBA_ys8tPqXmytS4eyntlwfawC2fiXFcwlw,4818
24
24
  suite_py/lib/handler/frequent_reviewers_handler.py,sha256=EIJX5FEMWzrxuXS9A17hu1vfxgJSOHSBX_ahCEZ2FVA,2185
25
- suite_py/lib/handler/git_handler.py,sha256=boxhl9lQz6fjEJ10ib1KrDW-geCVjhA_6nKwv2ll01g,11333
25
+ suite_py/lib/handler/git_handler.py,sha256=Y2hKR5sUKBhfRfQrMNjyCScJpdyPJ7XWK9f3ykx7Lf0,12710
26
26
  suite_py/lib/handler/github_handler.py,sha256=AnFL54yOZ5GDIU91wQat4s-d1WTcmg_B_5M7-Rop3wA,2900
27
27
  suite_py/lib/handler/metrics_handler.py,sha256=-Tp62pFIiYsBkDga0nQG3lWU-gxH68wEjIIIJeU1jHk,3159
28
28
  suite_py/lib/handler/okta_handler.py,sha256=UiRcBDmFkMFi9H7Me1QaruC8yPI5fFbnLGzOf3kfxG0,2805
29
+ suite_py/lib/handler/pre_commit_handler.py,sha256=2-G67eS5LNYUK3P9JLJmhz_UbMIQr7RffsIaVZ34vy4,3739
29
30
  suite_py/lib/handler/prompt_utils.py,sha256=vgk1O7h-iYEAZv1sXtMh8xIgH1djI398rzxRIgZWZcg,2474
30
31
  suite_py/lib/handler/version_handler.py,sha256=DXTx4yCAbFVC6CdMqPJ-LiN5YM-dT2zklG8POyKTP5A,6774
31
32
  suite_py/lib/handler/youtrack_handler.py,sha256=eTGBBXjlN_ay1cawtnZ2IG6l78dDyKdMN1x6PxcvtA0,7499
32
33
  suite_py/lib/logger.py,sha256=q_qRtpg0Eh7r5tB-Rwz87dnWBwP-a2dIvggkiQikH8M,782
33
- suite_py/lib/metrics.py,sha256=CqAIwPIRm0AJR4qmCTj1rw-NCwdSL4Huj2eKhLxgLgU,1629
34
+ suite_py/lib/metrics.py,sha256=urTBVzIc1Ys6OHPOO32fLPPRcQU45tzM3XMJ7mUl5dc,1629
34
35
  suite_py/lib/oauth.py,sha256=DhXimUu7MDscQsMyt3L04_kw0ZmuqmhYG6KZTPlKqNQ,5083
35
36
  suite_py/lib/requests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
37
  suite_py/lib/requests/auth.py,sha256=wN_WtGFmDUWRFilWzOmUaRBvP2n3EPpPMqex9Zjddko,228
@@ -38,7 +39,7 @@ suite_py/lib/requests/session.py,sha256=P32H3cWnCWunu91WIj2iDM5U3HzaBglg60VN_C9J
38
39
  suite_py/lib/symbol.py,sha256=z3QYBuNIwD3qQ3zF-cLOomIr_-C3bO_u5UIDAHMiyTo,60
39
40
  suite_py/lib/tokens.py,sha256=4DbsHDFLIxs40t3mRw_ZyhmejZQ0Bht7iAL8dTCTQd4,5458
40
41
  suite_py/templates/login.html,sha256=fJLls2SB84oZTSrxTdA5q1PqfvIHcCD4fhVWfyco7Ig,861
41
- suite_py-1.42.2.dist-info/METADATA,sha256=2DH1B8DsS5SlkRpahd3ZQfGa6YLwBfP6U1PmnTxZih0,1533
42
- suite_py-1.42.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
43
- suite_py-1.42.2.dist-info/entry_points.txt,sha256=dVKLC-9Infy-dHJT_MkK6LcDjOgBCJ8lfPkURJhBjxE,46
44
- suite_py-1.42.2.dist-info/RECORD,,
42
+ suite_py-1.43.0.dist-info/METADATA,sha256=F4M9UIEhOXN7cbAYMSYRI3lV5bVA3GWKtTEghpHQwg4,1533
43
+ suite_py-1.43.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
44
+ suite_py-1.43.0.dist-info/entry_points.txt,sha256=dVKLC-9Infy-dHJT_MkK6LcDjOgBCJ8lfPkURJhBjxE,46
45
+ suite_py-1.43.0.dist-info/RECORD,,