c2cciutils 1.7.0.dev173__py3-none-any.whl → 1.7.3.dev2__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/publish.py CHANGED
@@ -10,11 +10,11 @@ import pickle # nosec
10
10
  import re
11
11
  import subprocess # nosec
12
12
  import sys
13
+ import tomllib
13
14
  import uuid
14
15
  from typing import Optional
15
16
 
16
17
  import ruamel.yaml
17
- import tomlkit
18
18
  from google.auth.transport.requests import Request
19
19
  from google.oauth2.credentials import Credentials
20
20
  from google_auth_oauthlib.flow import InstalledAppFlow
@@ -61,7 +61,7 @@ class GoogleCalendar:
61
61
  self._update_creds()
62
62
  self.service = build("calendar", "v3", credentials=self.creds)
63
63
 
64
- def init_calendar_service(self) -> Credentials:
64
+ def init_calendar_service(self) -> Credentials: # type: ignore
65
65
  """
66
66
  Initialize the calendar service.
67
67
  """
@@ -72,12 +72,12 @@ class GoogleCalendar:
72
72
  with open(self.credentials_pickle_file, "rb") as token:
73
73
  creds = pickle.load(token) # nosec
74
74
  # If there are no (valid) credentials available, let the user log in.
75
- if not creds or not creds.valid:
75
+ if not creds or not creds.valid: # pylint: disable=possibly-used-before-assignment
76
76
  if creds and creds.expired and creds.refresh_token:
77
- creds.refresh(Request())
77
+ creds.refresh(Request()) # type: ignore
78
78
  else:
79
79
  if self.token:
80
- creds = Credentials(
80
+ creds = Credentials( # type: ignore
81
81
  self.token,
82
82
  refresh_token=self.refresh_token,
83
83
  token_uri=self.token_uri,
@@ -177,13 +177,6 @@ class GoogleCalendar:
177
177
  event_result = self.service.events().insert(calendarId=self.calendar_id, body=body).execute()
178
178
  print(f"Created event with id: {event_result['id']}")
179
179
 
180
- def _print_credentials(self) -> None:
181
- """
182
- Print the credentials.
183
- """
184
- # UNSAFE: DO NEVER PRINT CREDENTIALS IN CI ENVIRONMENT, DEBUG ONLY!!!!
185
- print(self.creds.to_json())
186
-
187
180
  def save_credentials_to_gopass(self) -> None:
188
181
  """
189
182
  Save the calendar credentials to gopass.
@@ -201,6 +194,9 @@ class GoogleCalendar:
201
194
  c2cciutils.gopass_put(secret, key)
202
195
 
203
196
  def __del__(self) -> None:
197
+ """
198
+ Delete the credentials file.
199
+ """
204
200
  if os.path.exists(self.credentials_pickle_file):
205
201
  os.remove(self.credentials_pickle_file)
206
202
 
@@ -235,7 +231,9 @@ def main_calendar() -> None:
235
231
  parser.print_help()
236
232
 
237
233
  if args.show_events_since:
238
- google_calendar.print_latest_events(args.show_events_since)
234
+ google_calendar.print_latest_events( # pylint: disable=possibly-used-before-assignment
235
+ args.show_events_since
236
+ )
239
237
 
240
238
  if args.refresh_gopass_credentials:
241
239
  google_calendar.save_credentials_to_gopass()
@@ -257,7 +255,6 @@ def pip(
257
255
  publish: If False only check the package
258
256
  package: The package configuration
259
257
  """
260
-
261
258
  print(f"::group::{'Publishing' if publish else 'Checking'} '{package.get('path')}' to pypi")
262
259
  sys.stdout.flush()
263
260
  sys.stderr.flush()
@@ -292,8 +289,8 @@ def pip(
292
289
  if os.path.exists(os.path.join(cwd, "pyproject.toml")):
293
290
  use_poetry = False
294
291
  if "build_command" not in package:
295
- with open(os.path.join(cwd, "pyproject.toml"), encoding="utf-8") as project_file:
296
- pyproject = tomlkit.load(project_file)
292
+ with open(os.path.join(cwd, "pyproject.toml"), "rb") as project_file:
293
+ pyproject = tomllib.load(project_file)
297
294
  re_splitter = re.compile(r"[<>=]+")
298
295
  for requirement in pyproject.get("build-system", {}).get("requires", []):
299
296
  requirement_split = re_splitter.split(requirement)
@@ -356,7 +353,6 @@ def docker(
356
353
  dst_tags: Publish using the provided tags
357
354
  images_full: The list of published images (with tag), used to build the dispatch event
358
355
  """
359
-
360
356
  print(
361
357
  f"::group::Publishing {image_config['name']} to the server {name} using the tags {', '.join(dst_tags)}"
362
358
  )
@@ -416,7 +412,6 @@ def helm(folder: str, version: str, owner: str, repo: str, commit_sha: str, toke
416
412
  commit_sha: The sha of the current commit
417
413
  token: The GitHub token
418
414
  """
419
-
420
415
  print(f"::group::Publishing Helm chart from '{folder}' to GitHub release")
421
416
  sys.stdout.flush()
422
417
  sys.stderr.flush()
c2cciutils/schema.json CHANGED
@@ -6,197 +6,6 @@
6
6
  "description": "C2C CI utils configuration file",
7
7
  "additionalProperties": false,
8
8
  "definitions": {
9
- "audit_outdated_versions": {
10
- "title": "Audit outdated versions",
11
- "description": "Audit of outdated version",
12
- "type": "boolean"
13
- },
14
- "audit_snyk": {
15
- "title": "Audit with Snyk",
16
- "description": "The audit Snyk configuration",
17
- "oneOf": [
18
- {
19
- "title": "Audit Snyk config",
20
- "description": "The audit Pipfile configuration",
21
- "type": "object",
22
- "properties": {
23
- "test_arguments": {
24
- "description": "The Snyk test arguments",
25
- "title": "audit snyk test arguments",
26
- "default": ["--all-projects", "--fail-on=all", "--severity-threshold=medium"],
27
- "type": "array",
28
- "items": { "type": "string" }
29
- },
30
- "monitor_arguments": {
31
- "description": "The Snyk monitor arguments",
32
- "title": "audit snyk monitor arguments",
33
- "default": ["--all-projects"],
34
- "type": "array",
35
- "items": { "type": "string" }
36
- },
37
- "fix_arguments": {
38
- "description": "The Snyk fix arguments",
39
- "title": "audit snyk fix arguments",
40
- "default": ["--all-projects"],
41
- "type": "array",
42
- "items": { "type": "string" }
43
- },
44
- "fix_github_create_pull_request_arguments": {
45
- "description": "The Snyk fix pull request extra arguments",
46
- "title": "audit snyk fix pull request arguments",
47
- "default": ["--fill", "--label=dependencies"],
48
- "type": "array",
49
- "items": { "type": "string" }
50
- },
51
- "pip_install_arguments": {
52
- "description": "The Snyk pip install arguments",
53
- "title": "audit snyk pip install arguments",
54
- "default": ["--user"],
55
- "type": "array",
56
- "items": { "type": "string" }
57
- },
58
- "pipenv_sync_arguments": {
59
- "description": "The Snyk pipenv sync arguments",
60
- "title": "audit snyk pipenv sync arguments",
61
- "default": [],
62
- "type": "array",
63
- "items": { "type": "string" }
64
- },
65
- "files_no_install": {
66
- "description": "The list of files to not install",
67
- "title": "audit snyk files no install",
68
- "default": [],
69
- "type": "array",
70
- "items": { "type": "string" }
71
- }
72
- }
73
- },
74
- { "type": "boolean" }
75
- ]
76
- },
77
- "codespell": {
78
- "title": "Codespell",
79
- "description": "The codespell check configuration",
80
- "type": "object",
81
- "properties": {
82
- "internal_dictionaries": {
83
- "title": "codespell dictionaries",
84
- "description": "List of argument that will be added to the codespell command",
85
- "default": ["clear", "rare", "informal", "code", "names", "en-GB_to_en-US"],
86
- "type": "array",
87
- "items": { "type": "string" }
88
- },
89
- "arguments": {
90
- "title": "codespell arguments",
91
- "description": "List of argument that will be added to the codespell command",
92
- "default": ["--quiet-level=2", "--check-filenames", "--ignore-words-list=ro"],
93
- "type": "array",
94
- "items": { "type": "string" }
95
- },
96
- "ignore_re": {
97
- "title": "codespell ignore regular expression",
98
- "description": "List of regular expression that should be ignored",
99
- "default": ["(.*/)?poetry\\.lock", "(.*/)?package-lock\\.json"],
100
- "type": "array",
101
- "items": { "type": "string" }
102
- }
103
- }
104
- },
105
- "pr_checks_commits_messages": {
106
- "title": "pull request checks commits messages",
107
- "description": "Check the pull request commits messages",
108
- "oneOf": [
109
- {
110
- "title": "pull request checks commits messages configuration",
111
- "description": "The commit message check configuration",
112
- "type": "object",
113
- "properties": {
114
- "check_fixup": {
115
- "title": "pull request checks commits messages fixup",
116
- "description": "Check that we don't have one fixup commit in the pull request",
117
- "default": true,
118
- "type": "boolean"
119
- },
120
- "check_squash": {
121
- "title": "pull request checks commits messages squash",
122
- "description": "Check that we don't have one squash commit in the pull request",
123
- "default": true,
124
- "type": "boolean"
125
- },
126
- "check_first_capital": {
127
- "title": "pull request checks commits messages first capital",
128
- "description": "Check that the all the commits message starts with a capital letter",
129
- "default": true,
130
- "type": "boolean"
131
- },
132
- "min_head_length": {
133
- "title": "pull request checks commits messages min head length",
134
- "description": "Check that the commits message head is at least this long, use 0 to disable",
135
- "default": 5,
136
- "type": "integer"
137
- },
138
- "check_no_merge_commits": {
139
- "title": "pull request checks commits messages no merge commits",
140
- "description": "Check that we don't have merge commits in the pull request",
141
- "default": true,
142
- "type": "boolean"
143
- },
144
- "check_no_own_revert": {
145
- "title": "pull request checks commits messages no own revert",
146
- "description": "Check that we don't have reverted one of our commits in the pull request",
147
- "default": true,
148
- "type": "boolean"
149
- }
150
- }
151
- },
152
- { "type": "boolean" }
153
- ]
154
- },
155
- "pr_checks_commits_spell": {
156
- "title": "pull request checks commits spelling",
157
- "oneOf": [
158
- {
159
- "title": "pull request checks commits spelling configuration",
160
- "description": "Configuration used to check the spelling of the commits",
161
- "type": "object",
162
- "properties": {
163
- "only_head": {
164
- "title": "pull request checks commits messages only head",
165
- "default": true,
166
- "type": "boolean"
167
- }
168
- }
169
- },
170
- { "type": "boolean" }
171
- ]
172
- },
173
- "pr_checks_pull_request_spell": {
174
- "title": "pull request checks pull request spelling",
175
- "oneOf": [
176
- {
177
- "title": "pull request checks pull request spelling configuration",
178
- "description": "Configuration used to check the spelling of the title and body of the pull request",
179
- "type": "object",
180
- "properties": {
181
- "only_head": {
182
- "title": "pull request checks only head",
183
- "default": true,
184
- "type": "boolean"
185
- }
186
- }
187
- },
188
- { "type": "boolean" }
189
- ]
190
- },
191
- "pr_checks_pull_request_labels": {
192
- "title": "pull request checks request labels",
193
- "description": "According the create changelog configuration",
194
- "type": "boolean"
195
- },
196
- "pr_checks_add_issue_link": {
197
- "title": "pull request checks add issue link",
198
- "type": "boolean"
199
- },
200
9
  "publish_docker": {
201
10
  "title": "Publish Docker",
202
11
  "description": "The configuration used to publish on Docker",
@@ -451,18 +260,15 @@
451
260
  "title": "Print versions versions",
452
261
  "type": "array",
453
262
  "default": [
454
- { "name": "c2cciutils", "cmd": ["c2cciutils", "--version"] },
455
263
  { "name": "python", "cmd": ["python3", "--version"] },
456
264
  { "name": "pip", "cmd": ["python3", "-m", "pip", "--version"] },
457
- { "name": "twine", "cmd": ["twine", "--version"] },
458
265
  { "name": "node", "prefix": "node ", "cmd": ["node", "--version"] },
459
266
  { "name": "npm", "prefix": "npm ", "cmd": ["npm", "--version"] },
460
- { "name": "make", "cmd": ["make", "--version"], "prefix": "make " },
267
+ { "name": "make", "cmd": ["make", "--version"] },
461
268
  { "name": "docker", "cmd": ["docker", "--version"] },
462
- { "name": "docker-compose", "cmd": ["docker-compose", "--version"] },
269
+ { "name": "docker compose", "cmd": ["docker", "compose", "version"] },
463
270
  { "name": "java", "cmd": ["java", "-version"] },
464
- { "name": "kubectl", "cmd": ["kubectl", "version"] },
465
- { "name": "helm", "cmd": ["helm", "version"] }
271
+ { "name": "helm", "cmd": ["helm", "version"], "prefix": "HELM: " }
466
272
  ],
467
273
  "items": {
468
274
  "type": "object",
@@ -506,39 +312,6 @@
506
312
  },
507
313
  "properties": {
508
314
  "print_versions": { "$ref": "#/definitions/print_versions" },
509
- "codespell": { "$ref": "#/definitions/codespell" },
510
- "audit": {
511
- "title": "Audit",
512
- "description": "The audit configuration",
513
- "type": "object",
514
- "default": {
515
- "snyk": true,
516
- "outdated_versions": true
517
- },
518
- "properties": {
519
- "outdated_versions": { "$ref": "#/definitions/audit_outdated_versions" },
520
- "snyk": { "$ref": "#/definitions/audit_snyk" }
521
- }
522
- },
523
- "pr-checks": {
524
- "title": "Pull request checks",
525
- "description": "The PR check configuration",
526
- "type": "object",
527
- "default": {
528
- "commits_messages": true,
529
- "commits_spell": true,
530
- "pull_request_spell": true,
531
- "pull_request_labels": true,
532
- "add_issue_link": true
533
- },
534
- "properties": {
535
- "commits_messages": { "$ref": "#/definitions/pr_checks_commits_messages" },
536
- "commits_spell": { "$ref": "#/definitions/pr_checks_commits_spell" },
537
- "pull_request_spell": { "$ref": "#/definitions/pr_checks_pull_request_spell" },
538
- "pull_request_labels": { "$ref": "#/definitions/pr_checks_pull_request_labels" },
539
- "add_issue_link": { "$ref": "#/definitions/pr_checks_add_issue_link" }
540
- }
541
- },
542
315
  "publish": {
543
316
  "title": "Publish",
544
317
  "description": "The publishing configurations",
@@ -25,7 +25,6 @@ def clean(image: str, tag: str, token: str) -> None:
25
25
  tag: The tag that should be deleted
26
26
  token: The token used to be authenticated on Docker hub
27
27
  """
28
-
29
28
  print(f"Delete image '{image}:{tag}'.")
30
29
 
31
30
  response = requests.head(
@@ -21,7 +21,7 @@ def main() -> None:
21
21
 
22
22
  if os.path.exists("docker-compose.yaml"):
23
23
  _print("::group::Docker Compose ps")
24
- subprocess.run(["docker-compose", "ps"], check=False)
24
+ subprocess.run(["docker", "compose", "ps"], check=False)
25
25
  _print("::endgroup::")
26
26
 
27
27
  _print("::group::Docker ps")
@@ -7,7 +7,6 @@ import c2cciutils.lib.docker
7
7
 
8
8
  def main() -> None:
9
9
  """Dump the actual versions of packages in image to file ci/dpkg-versions.yaml."""
10
-
11
10
  argparser = argparse.ArgumentParser(
12
11
  description="Dump the actual versions of packages in image to file ci/dpkg-versions.yaml."
13
12
  )
@@ -17,7 +17,6 @@ from c2cciutils import applications_definition
17
17
 
18
18
  def main() -> None:
19
19
  """Download applications from GitHub releases or any other URLs to the ~/.local/bin folder."""
20
-
21
20
  argparser = argparse.ArgumentParser(
22
21
  description="""Download applications from GitHub releases or any other URLs to the ~/.local/bin folder.
23
22
  Based on tow files, the first contains the information about from where to download the applications,
@@ -60,7 +59,6 @@ def download_applications(
60
59
  applications: applications_definition.ApplicationsConfiguration, versions: dict[str, str]
61
60
  ) -> None:
62
61
  """Download the versions of applications specified in the configuration."""
63
-
64
62
  bin_path = os.path.join(os.environ["HOME"], ".local", "bin")
65
63
  if not os.path.exists(bin_path):
66
64
  os.makedirs(bin_path)
@@ -54,7 +54,7 @@ def _check_container_status(pod: Any, status: Any, is_init: bool = False) -> boo
54
54
  status_message = status_message.strip()
55
55
  if status_message == "Completed":
56
56
  return True
57
- print(f'::group::Container not ready in {pod["metadata"]["name"]}: {status_message}')
57
+ print(f'::group::Container not ready in {pod["metadata"]["name"]}: {status_message}') # noqa: E713
58
58
  if status_message_long != status_message:
59
59
  print(status_message_long)
60
60
  print(json.dumps(status, indent=4))
@@ -68,7 +68,7 @@ def _check_pod_status(pods: Any) -> bool:
68
68
  for condition in pod["status"].get("conditions", []):
69
69
  if not condition["status"]:
70
70
  print(
71
- f'::group::Pod not ready in {pod["metadata"]["name"]}: {condition.get("message", condition["type"])}'
71
+ f'::group::Pod not ready in {pod["metadata"]["name"]}: {condition.get("message", condition["type"])}' # noqa: E713
72
72
  )
73
73
  print(json.dumps(condition, indent=4))
74
74
  print("::endgroup::")
@@ -19,7 +19,6 @@ def main() -> None:
19
19
  parser = argparse.ArgumentParser(description="Some utils of c2cciutils.")
20
20
  parser.add_argument("--get-config", action="store_true", help="display the current config")
21
21
  parser.add_argument("--version", action="store_true", help="display the current version")
22
- parser.add_argument("--ls-files-mime", help="List all the files with the specified mime type")
23
22
 
24
23
  args = parser.parse_args()
25
24
 
@@ -27,15 +26,8 @@ def main() -> None:
27
26
  print(yaml.dump(c2cciutils.get_config(), default_flow_style=False, Dumper=yaml.SafeDumper))
28
27
 
29
28
  if args.version:
30
- for pkg in ("c2cciutils", "black", "isort"):
31
- try:
32
- print(f"{pkg} {pkg_resources.get_distribution(pkg).version}")
33
- except pkg_resources.DistributionNotFound:
34
- print(f"{pkg} missing")
35
-
36
- if args.ls_files_mime:
37
- for file_name in c2cciutils.get_git_files_mime(args.ls_files_mime):
38
- print(file_name)
29
+ version = pkg_resources.get_distribution("c2cciutils").version
30
+ print(f"c2cciutils {version}")
39
31
 
40
32
 
41
33
  if __name__ == "__main__":
@@ -13,15 +13,16 @@ from re import Match
13
13
  from typing import Optional, cast
14
14
 
15
15
  import requests
16
+ import security_md
16
17
  import yaml
17
18
 
18
19
  import c2cciutils
19
20
  import c2cciutils.configuration
20
21
  import c2cciutils.env
21
22
  import c2cciutils.lib.docker
23
+ import c2cciutils.lib.oidc
22
24
  import c2cciutils.publish
23
25
  import c2cciutils.scripts.download_applications
24
- import c2cciutils.security
25
26
  from c2cciutils.publish import GoogleCalendar
26
27
  from c2cciutils.scripts.trigger_image_update import dispatch
27
28
 
@@ -170,6 +171,9 @@ def main() -> None:
170
171
  config.get("publish", {}).get("pypi", {}) if config.get("publish", {}).get("pypi", False) else {},
171
172
  )
172
173
  if pypi_config:
174
+ if pypi_config["packages"]:
175
+ c2cciutils.lib.oidc.pypi_login()
176
+
173
177
  for package in pypi_config["packages"]:
174
178
  if package.get("group", c2cciutils.configuration.PUBLISH_PIP_PACKAGE_GROUP_DEFAULT) == args.group:
175
179
  publish = version_type in pypi_config.get("versions", [])
@@ -213,11 +217,9 @@ def main() -> None:
213
217
  print(f"::error:: {security_response.status_code} {security_response.text}")
214
218
  sys.exit(1)
215
219
 
216
- security = c2cciutils.security.Security(security_text)
217
- version_index = security.headers.index("Version") if "Version" in security.headers else -1
218
- alternate_tag_index = (
219
- security.headers.index("Alternate Tag") if "Alternate Tag" in security.headers else -1
220
- )
220
+ security = security_md.Security(security_text)
221
+ version_index = security.version_index
222
+ alternate_tag_index = security.alternate_tag_index
221
223
 
222
224
  row_index = -1
223
225
  if version_index >= 0:
@@ -392,19 +394,34 @@ def main() -> None:
392
394
  dpkg_success &= c2cciutils.lib.docker.check_versions(versions_config.get(image, {}), image)
393
395
 
394
396
  if not dpkg_success:
395
- current_versions_in_images = {}
396
- if os.path.exists("ci/dpkg-versions.yaml"):
397
+ current_versions_in_images: dict[str, dict[str, str]] = {}
398
+ if dpkg_config_found:
397
399
  with open("ci/dpkg-versions.yaml", encoding="utf-8") as dpkg_versions_file:
398
400
  current_versions_in_images = yaml.load(dpkg_versions_file, Loader=yaml.SafeLoader)
399
401
  for image in images_src:
402
+ if image in current_versions_in_images:
403
+ current_versions_in_images[image] = dict(current_versions_in_images[image])
400
404
  _, versions_image = c2cciutils.lib.docker.get_dpkg_packages_versions(image)
401
- current_versions_in_images[image] = {k: str(v) for k, v in versions_image.items()}
405
+ for dpkg_package, package_version in versions_image.items():
406
+ if dpkg_package not in current_versions_in_images.get(image, {}):
407
+ current_versions_in_images.setdefault(image, {})[dpkg_package] = str(package_version)
408
+ for dpkg_package in list(current_versions_in_images[image].keys()):
409
+ if dpkg_package not in versions_image:
410
+ del current_versions_in_images[image][dpkg_package]
402
411
  if dpkg_config_found:
403
412
  print(
404
413
  "::error::Some packages are have a greater version in the config raster then in the image."
405
414
  )
406
415
  print("Current versions of the Debian packages in Docker images:")
407
416
  print(yaml.dump(current_versions_in_images, Dumper=yaml.SafeDumper, default_flow_style=False))
417
+ if dpkg_config_found:
418
+ with open("ci/dpkg-versions.yaml", "w", encoding="utf-8") as dpkg_versions_file:
419
+ yaml.dump(
420
+ current_versions_in_images,
421
+ dpkg_versions_file,
422
+ Dumper=yaml.SafeDumper,
423
+ default_flow_style=False,
424
+ )
408
425
 
409
426
  if dpkg_config_found:
410
427
  success = False
@@ -63,7 +63,6 @@ def dispatch(repository: str, event_type: str, images_full: list[str]) -> None:
63
63
  """
64
64
  Trigger an image update on the argocd repository.
65
65
  """
66
-
67
66
  id_ = random.randint(1, 100000) # nosec
68
67
  print(f"Triggering {event_type}:{id_} on {repository} with {','.join(images_full)}")
69
68
 
@@ -14,7 +14,6 @@ import c2cciutils
14
14
 
15
15
  def main() -> None:
16
16
  """Create a new version with its stabilization branch."""
17
-
18
17
  args_parser = argparse.ArgumentParser(
19
18
  description="Create a new version with its stabilization branch",
20
19
  usage="""
@@ -1,4 +1,4 @@
1
- Copyright (c) 2020-2023, Camptocamp SA
1
+ Copyright (c) 2020-2025, Camptocamp SA
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without