c2cciutils 1.7.0.dev326__py3-none-any.whl → 1.7.0.dev338__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.
Potentially problematic release.
This version of c2cciutils might be problematic. Click here for more details.
- c2cciutils/__init__.py +0 -212
- c2cciutils/configuration.py +28 -466
- c2cciutils/lib/oidc.py +4 -3
- c2cciutils/publish.py +3 -3
- c2cciutils/schema.json +0 -217
- c2cciutils/scripts/k8s/wait.py +2 -2
- c2cciutils/scripts/main.py +0 -5
- c2cciutils/scripts/publish.py +1 -1
- {c2cciutils-1.7.0.dev326.dist-info → c2cciutils-1.7.0.dev338.dist-info}/METADATA +3 -24
- {c2cciutils-1.7.0.dev326.dist-info → c2cciutils-1.7.0.dev338.dist-info}/RECORD +13 -17
- {c2cciutils-1.7.0.dev326.dist-info → c2cciutils-1.7.0.dev338.dist-info}/entry_points.txt +0 -2
- c2cciutils/audit.py +0 -175
- c2cciutils/pr_checks.py +0 -286
- c2cciutils/scripts/audit.py +0 -41
- c2cciutils/scripts/pr_checks.py +0 -78
- {c2cciutils-1.7.0.dev326.dist-info → c2cciutils-1.7.0.dev338.dist-info}/LICENSE +0 -0
- {c2cciutils-1.7.0.dev326.dist-info → c2cciutils-1.7.0.dev338.dist-info}/WHEEL +0 -0
c2cciutils/pr_checks.py
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The pull request checking functions.
|
|
3
|
-
|
|
4
|
-
Commits, messages and labels.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import os
|
|
8
|
-
import re
|
|
9
|
-
import subprocess # nosec
|
|
10
|
-
from tempfile import NamedTemporaryFile
|
|
11
|
-
from typing import Any, Optional
|
|
12
|
-
|
|
13
|
-
import requests
|
|
14
|
-
import yaml
|
|
15
|
-
|
|
16
|
-
import c2cciutils.configuration
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def _commit_intro(need_separator: bool, commit: dict[str, Any]) -> bool:
|
|
20
|
-
head = commit["commit"]["message"].split("\n")[0]
|
|
21
|
-
if need_separator:
|
|
22
|
-
print("-" * 30)
|
|
23
|
-
print(f'{commit["commit"]["tree"]["sha"]}: {head}')
|
|
24
|
-
return True
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def print_event(github_event: dict[str, Any], **kwargs: Any) -> bool:
|
|
28
|
-
"""
|
|
29
|
-
Print the github object.
|
|
30
|
-
"""
|
|
31
|
-
del kwargs
|
|
32
|
-
print(yaml.dump(github_event, default_flow_style=False, Dumper=yaml.SafeDumper))
|
|
33
|
-
return True
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def commits_messages(
|
|
37
|
-
config: c2cciutils.configuration.PullRequestChecksCommitsMessagesConfiguration,
|
|
38
|
-
commits: list[dict[str, Any]],
|
|
39
|
-
**kwargs: Any,
|
|
40
|
-
) -> bool:
|
|
41
|
-
"""
|
|
42
|
-
Check the commits messages.
|
|
43
|
-
|
|
44
|
-
- They should start with a capital letter.
|
|
45
|
-
- They should not be too short.
|
|
46
|
-
- They should not be a squash or fixup commit.
|
|
47
|
-
- They should not be a merge commit.
|
|
48
|
-
- They should not be a revert commit.
|
|
49
|
-
"""
|
|
50
|
-
del kwargs
|
|
51
|
-
|
|
52
|
-
need_separator = False
|
|
53
|
-
success = True
|
|
54
|
-
first_capital = re.compile(r"^[^a-z]")
|
|
55
|
-
commit_hash = set()
|
|
56
|
-
for commit in commits:
|
|
57
|
-
need_head = True
|
|
58
|
-
commit_hash.add(commit["sha"])
|
|
59
|
-
message_lines = commit["commit"]["message"].split("\n")
|
|
60
|
-
head = message_lines[0]
|
|
61
|
-
if config.get(
|
|
62
|
-
"check_fixup", c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_FIXUP_DEFAULT
|
|
63
|
-
) and head.startswith("fixup! "):
|
|
64
|
-
if need_head:
|
|
65
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
66
|
-
need_head = False
|
|
67
|
-
print("::error::Fixup message not allowed")
|
|
68
|
-
success = False
|
|
69
|
-
if config.get(
|
|
70
|
-
"check_squash", c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_SQUASH_DEFAULT
|
|
71
|
-
) and head.startswith("squash! "):
|
|
72
|
-
if need_head:
|
|
73
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
74
|
-
need_head = False
|
|
75
|
-
print("::error::Squash message not allowed")
|
|
76
|
-
success = False
|
|
77
|
-
if (
|
|
78
|
-
config.get(
|
|
79
|
-
"check_first_capital",
|
|
80
|
-
c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_FIRST_CAPITAL_DEFAULT,
|
|
81
|
-
)
|
|
82
|
-
and first_capital.match(head) is None
|
|
83
|
-
):
|
|
84
|
-
if need_head:
|
|
85
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
86
|
-
need_head = False
|
|
87
|
-
print("::error::The first letter of message head should be a capital")
|
|
88
|
-
success = False
|
|
89
|
-
min_length = config.get(
|
|
90
|
-
"min_head_length",
|
|
91
|
-
c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_MIN_HEAD_LENGTH_DEFAULT,
|
|
92
|
-
)
|
|
93
|
-
if min_length > 0 and len(head) < min_length:
|
|
94
|
-
if need_head:
|
|
95
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
96
|
-
need_head = False
|
|
97
|
-
print(f"The message head should be at least {min_length} characters long")
|
|
98
|
-
success = False
|
|
99
|
-
if (
|
|
100
|
-
config.get(
|
|
101
|
-
"check_no_merge_commits",
|
|
102
|
-
c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_NO_MERGE_COMMITS_DEFAULT,
|
|
103
|
-
)
|
|
104
|
-
and len(commit["parents"]) != 1
|
|
105
|
-
):
|
|
106
|
-
if need_head:
|
|
107
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
108
|
-
need_head = False
|
|
109
|
-
print("::error::The merge commit are not allowed")
|
|
110
|
-
success = False
|
|
111
|
-
if config.get(
|
|
112
|
-
"check_no_own_revert",
|
|
113
|
-
c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_NO_OWN_REVERT_DEFAULT,
|
|
114
|
-
) and (
|
|
115
|
-
head.startswith("Revert ")
|
|
116
|
-
and len(message_lines) == 3
|
|
117
|
-
and message_lines[2].startswith("This reverts commit ")
|
|
118
|
-
):
|
|
119
|
-
revert_commit_hash = message_lines[2][len("This reverts commit ") : -1]
|
|
120
|
-
if revert_commit_hash in commit_hash:
|
|
121
|
-
if need_head:
|
|
122
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
123
|
-
need_head = False
|
|
124
|
-
print(f"Revert own commits is not allowed ({revert_commit_hash})")
|
|
125
|
-
success = False
|
|
126
|
-
continue
|
|
127
|
-
return success
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def commits_spell(
|
|
131
|
-
config: c2cciutils.configuration.PullRequestChecksCommitsSpellingConfiguration,
|
|
132
|
-
full_config: c2cciutils.configuration.Configuration,
|
|
133
|
-
commits: list[dict[str, Any]],
|
|
134
|
-
**kwargs: Any,
|
|
135
|
-
) -> bool:
|
|
136
|
-
"""Check the spelling of the commits body."""
|
|
137
|
-
del kwargs
|
|
138
|
-
|
|
139
|
-
spellcheck_cmd = c2cciutils.get_codespell_command(full_config)
|
|
140
|
-
|
|
141
|
-
success = True
|
|
142
|
-
need_separator = False
|
|
143
|
-
for commit in commits:
|
|
144
|
-
with NamedTemporaryFile("w+t", encoding="utf-8", suffix=".yaml") as temp_file:
|
|
145
|
-
if config.get(
|
|
146
|
-
"only_head", c2cciutils.configuration.PULL_REQUEST_CHECKS_COMMITS_MESSAGES_ONLY_HEAD_DEFAULT
|
|
147
|
-
):
|
|
148
|
-
head = commit["commit"]["message"].split("\n")[0]
|
|
149
|
-
temp_file.write(head)
|
|
150
|
-
else:
|
|
151
|
-
temp_file.write(commit["commit"]["message"])
|
|
152
|
-
temp_file.flush()
|
|
153
|
-
spell = subprocess.run( # nosec # pylint: disable=subprocess-run-check
|
|
154
|
-
spellcheck_cmd + [temp_file.name], capture_output=True
|
|
155
|
-
)
|
|
156
|
-
if spell.returncode != 0:
|
|
157
|
-
need_separator = _commit_intro(need_separator, commit)
|
|
158
|
-
print("::error::Code spell error")
|
|
159
|
-
print(spell.stderr)
|
|
160
|
-
print(spell.stdout)
|
|
161
|
-
success = False
|
|
162
|
-
return success
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def pull_request_spell(
|
|
166
|
-
config: c2cciutils.configuration.PullRequestChecksPullRequestSpellingConfiguration,
|
|
167
|
-
full_config: c2cciutils.configuration.Configuration,
|
|
168
|
-
github_event: dict[str, Any],
|
|
169
|
-
**kwargs: Any,
|
|
170
|
-
) -> bool:
|
|
171
|
-
"""Check the spelling of the pull request title and message."""
|
|
172
|
-
del kwargs
|
|
173
|
-
|
|
174
|
-
spellcheck_cmd = c2cciutils.get_codespell_command(full_config)
|
|
175
|
-
|
|
176
|
-
with NamedTemporaryFile("w+t") as temp_file:
|
|
177
|
-
temp_file.write(github_event["event"]["pull_request"]["title"])
|
|
178
|
-
temp_file.write("\n")
|
|
179
|
-
if not config.get(
|
|
180
|
-
"only_head", c2cciutils.configuration.PULL_REQUEST_CHECKS_ONLY_HEAD_DEFAULT
|
|
181
|
-
) and github_event["event"]["pull_request"].get("body"):
|
|
182
|
-
temp_file.write("\n")
|
|
183
|
-
temp_file.write(github_event["event"]["pull_request"]["body"])
|
|
184
|
-
temp_file.write("\n")
|
|
185
|
-
temp_file.flush()
|
|
186
|
-
spell = subprocess.run( # nosec # pylint: disable=subprocess-run-check
|
|
187
|
-
spellcheck_cmd + [temp_file.name], capture_output=True
|
|
188
|
-
)
|
|
189
|
-
if spell.returncode != 0:
|
|
190
|
-
print("::error::Code spell error in pull request")
|
|
191
|
-
print(spell.stderr)
|
|
192
|
-
print(spell.stdout)
|
|
193
|
-
return False
|
|
194
|
-
return True
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
def pull_request_labels(github_event: dict[str, Any], **kwargs: Any) -> bool:
|
|
198
|
-
"""Check it the label are set correctly for the changelog generation."""
|
|
199
|
-
del kwargs
|
|
200
|
-
|
|
201
|
-
if github_event["actor"] == "renovate[bot]":
|
|
202
|
-
return True
|
|
203
|
-
|
|
204
|
-
if not os.path.exists(".github/changelog-config.yaml"):
|
|
205
|
-
return True
|
|
206
|
-
|
|
207
|
-
required_labels = []
|
|
208
|
-
with open(".github/changelog-config.yaml", encoding="utf-8") as changelog_config_file:
|
|
209
|
-
changelog_config = yaml.load(changelog_config_file, Loader=yaml.SafeLoader)
|
|
210
|
-
for section in changelog_config.values():
|
|
211
|
-
if "labels" in section:
|
|
212
|
-
required_labels.extend(section["labels"])
|
|
213
|
-
|
|
214
|
-
print(f"Required one onf the following labels: {', '.join(required_labels)}")
|
|
215
|
-
|
|
216
|
-
if required_labels:
|
|
217
|
-
labels = [
|
|
218
|
-
label["name"]
|
|
219
|
-
for label in github_event["event"]["pull_request"]["labels"]
|
|
220
|
-
if label["name"] in required_labels
|
|
221
|
-
]
|
|
222
|
-
if len(labels) == 0:
|
|
223
|
-
print(f"::error::No required label found: {', '.join(required_labels)}")
|
|
224
|
-
return False
|
|
225
|
-
if len(labels) > 1:
|
|
226
|
-
print(f"::error::Too many required labels found: {', '.join(labels)}")
|
|
227
|
-
return False
|
|
228
|
-
return True
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
GET_ISSUE_RE = [
|
|
232
|
-
re.compile(r"^([A-Z]{3,6}-[0-9]+)-.*$"),
|
|
233
|
-
re.compile(r"^([a-z]{3,6}-[0-9]+)-.*$"),
|
|
234
|
-
re.compile(r"^.*-([A-Z]{3,6}-[0-9]+)$"),
|
|
235
|
-
re.compile(r"^.*-([a-z]{3,6}-[0-9]+)$"),
|
|
236
|
-
]
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def _get_issue_number(name: str) -> Optional[str]:
|
|
240
|
-
for re_ in GET_ISSUE_RE:
|
|
241
|
-
match = re_.match(name)
|
|
242
|
-
if match is not None:
|
|
243
|
-
return match.group(1)
|
|
244
|
-
return None
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def add_issue_link(github_event: dict[str, Any], **kwargs: Any) -> bool:
|
|
248
|
-
"""Add a comment with the link to Jira if needed."""
|
|
249
|
-
del kwargs
|
|
250
|
-
|
|
251
|
-
issue_number = _get_issue_number(github_event["event"]["pull_request"]["head"]["ref"])
|
|
252
|
-
|
|
253
|
-
if issue_number is None:
|
|
254
|
-
return True
|
|
255
|
-
|
|
256
|
-
issue_number = issue_number.upper()
|
|
257
|
-
|
|
258
|
-
body = github_event["event"]["pull_request"].get("body") or ""
|
|
259
|
-
if issue_number in body.upper():
|
|
260
|
-
return True
|
|
261
|
-
|
|
262
|
-
comments_response = requests.get(
|
|
263
|
-
github_event["event"]["pull_request"]["_links"]["comments"]["href"],
|
|
264
|
-
timeout=int(os.environ.get("C2CCIUTILS_TIMEOUT", "30")),
|
|
265
|
-
headers=c2cciutils.add_authorization_header({}),
|
|
266
|
-
)
|
|
267
|
-
c2cciutils.check_response(comments_response)
|
|
268
|
-
comments = comments_response.json()
|
|
269
|
-
|
|
270
|
-
for comment in comments:
|
|
271
|
-
if issue_number in comment.get("body", "").upper():
|
|
272
|
-
return True
|
|
273
|
-
|
|
274
|
-
response = requests.post(
|
|
275
|
-
github_event["event"]["pull_request"]["_links"]["comments"]["href"],
|
|
276
|
-
headers={
|
|
277
|
-
"Accept": "application/vnd.github+json",
|
|
278
|
-
"Authorization": f"Bearer {github_event['token']}",
|
|
279
|
-
},
|
|
280
|
-
json={"body": f"See also: [{issue_number}](https://jira.camptocamp.com/browse/{issue_number})"},
|
|
281
|
-
timeout=int(os.environ.get("C2CCIUTILS_TIMEOUT", "30")),
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
if not response.ok:
|
|
285
|
-
print(f"Unable to add the comment: {response.text}")
|
|
286
|
-
return response.ok
|
c2cciutils/scripts/audit.py
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
The audit main function.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import argparse
|
|
8
|
-
import os
|
|
9
|
-
import sys
|
|
10
|
-
|
|
11
|
-
import c2cciutils.audit
|
|
12
|
-
import c2cciutils.env
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def main() -> None:
|
|
16
|
-
"""
|
|
17
|
-
Run the audit.
|
|
18
|
-
"""
|
|
19
|
-
parser = argparse.ArgumentParser(description="Run the audit of c2cciutils.")
|
|
20
|
-
parser.add_argument("--branch", help="The branch to audit, not defined means autodetect")
|
|
21
|
-
parser.add_argument("--check", help="Runs only the specified check")
|
|
22
|
-
parser.add_argument("--fix", action="store_true", help="Fix issues")
|
|
23
|
-
|
|
24
|
-
args = parser.parse_args()
|
|
25
|
-
|
|
26
|
-
full_config = c2cciutils.get_config()
|
|
27
|
-
c2cciutils.env.print_environment(full_config)
|
|
28
|
-
|
|
29
|
-
config = full_config.get("audit", {})
|
|
30
|
-
success = True
|
|
31
|
-
for key, conf in config.items():
|
|
32
|
-
if conf is not False and (args.check is None or args.check == key):
|
|
33
|
-
audit = getattr(c2cciutils.audit, key)
|
|
34
|
-
print(f"Run audit {key}")
|
|
35
|
-
success &= audit({} if conf is True else conf, full_config, args)
|
|
36
|
-
if not success and os.environ.get("TEST") != "TRUE":
|
|
37
|
-
sys.exit(1)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if __name__ == "__main__":
|
|
41
|
-
main()
|
c2cciutils/scripts/pr_checks.py
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""
|
|
4
|
-
The pull request checker main function.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import argparse
|
|
8
|
-
import json
|
|
9
|
-
import os
|
|
10
|
-
import sys
|
|
11
|
-
import traceback
|
|
12
|
-
|
|
13
|
-
import requests
|
|
14
|
-
|
|
15
|
-
import c2cciutils
|
|
16
|
-
import c2cciutils.env
|
|
17
|
-
import c2cciutils.pr_checks
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def main() -> None:
|
|
21
|
-
"""
|
|
22
|
-
Run the checks.
|
|
23
|
-
"""
|
|
24
|
-
parser = argparse.ArgumentParser(description="Run the pull request checks of c2cciutils.")
|
|
25
|
-
parser.add_argument("--stop", action="store_true", help="stop on first error")
|
|
26
|
-
parser.add_argument("--check", help="runs only the specified check")
|
|
27
|
-
|
|
28
|
-
args = parser.parse_args()
|
|
29
|
-
|
|
30
|
-
full_config = c2cciutils.get_config()
|
|
31
|
-
c2cciutils.env.print_environment(full_config)
|
|
32
|
-
|
|
33
|
-
github_event = json.loads(os.environ["GITHUB_EVENT"])
|
|
34
|
-
|
|
35
|
-
commits_response = requests.get(
|
|
36
|
-
github_event["event"]["pull_request"]["_links"]["commits"]["href"],
|
|
37
|
-
timeout=int(os.environ.get("C2CCIUTILS_TIMEOUT", "30")),
|
|
38
|
-
headers=c2cciutils.add_authorization_header({}),
|
|
39
|
-
)
|
|
40
|
-
c2cciutils.check_response(commits_response)
|
|
41
|
-
commits = commits_response.json()
|
|
42
|
-
|
|
43
|
-
config = full_config["pr-checks"]
|
|
44
|
-
|
|
45
|
-
check_args = {
|
|
46
|
-
"args": args,
|
|
47
|
-
"full_config": full_config,
|
|
48
|
-
"commits": commits,
|
|
49
|
-
"github_event": github_event,
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
success = True
|
|
53
|
-
for key, conf in config.items():
|
|
54
|
-
if conf is not False and (args.check is None or args.check == key):
|
|
55
|
-
check = getattr(c2cciutils.pr_checks, key)
|
|
56
|
-
print(f"::group::Run check {key}")
|
|
57
|
-
try:
|
|
58
|
-
if not check(config={} if conf is True else conf, **check_args):
|
|
59
|
-
success = False
|
|
60
|
-
print("::endgroup::")
|
|
61
|
-
if args.stop:
|
|
62
|
-
sys.exit(1)
|
|
63
|
-
print("::error::With error")
|
|
64
|
-
else:
|
|
65
|
-
print("::endgroup::")
|
|
66
|
-
except Exception: # pylint: disable=broad-except
|
|
67
|
-
traceback.print_exc()
|
|
68
|
-
success = False
|
|
69
|
-
print("::endgroup::")
|
|
70
|
-
if args.stop:
|
|
71
|
-
sys.exit(1)
|
|
72
|
-
print("::error::With exception")
|
|
73
|
-
if not success:
|
|
74
|
-
sys.exit(1)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if __name__ == "__main__":
|
|
78
|
-
main()
|
|
File without changes
|
|
File without changes
|