-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathto-ghci
executable file
·130 lines (108 loc) · 4.49 KB
/
to-ghci
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env python3
import argparse
import glob
import os
import subprocess
from datetime import datetime, timedelta, timezone
from typing import Any
import ruamel.yaml.error
from ruamel.yaml import YAML, CommentToken
def _get_image_name(image_config: dict[str, str]) -> str:
image = f'{image_config["registry"]}/' if "registry" in image_config else ""
image += image_config["repository"]
if "tag" in image_config:
image += f':{image_config["tag"]}'
return image
def _find_images(yaml: dict[str, Any], images: set[str], filename: str) -> None:
if not isinstance(yaml, dict):
return
for key, value in yaml.items():
if key == "image":
if "repository" in value and "tag" in value:
images.add(_get_image_name(value))
else:
print(f"::warning::{filename}: Unsupported image: {value}")
elif isinstance(value, dict):
_find_images(value, images, filename)
def _update_images_sha(yaml: dict[str, Any], images_data: dict[str, dict[str, datetime]]) -> None:
if not isinstance(yaml, dict):
return
for key, value in yaml.items():
if key == "image":
if "repository" in value and "tag" in value and not value.get("lock", False):
at_least_old = datetime.now(timezone.utc) - timedelta(days=value.get("atleastOldDays", 0))
at_least_new = value.get("atleastDate", datetime(1970, 1, 1, tzinfo=timezone.utc))
if at_least_new > at_least_old:
shas = [
(sha, date)
for sha, date in images_data.setdefault(_get_image_name(value), {}).items()
if date >= at_least_new
]
shas.sort(key=lambda x: x[1])
# Only the older one
sha = shas[0][0] if shas else None
else:
shas = [
(sha, date)
for sha, date in images_data.setdefault(_get_image_name(value), {}).items()
if date <= at_least_old
]
shas.sort(key=lambda x: x[1])
# Only the newer one
sha = shas[-1][0] if shas else None
if sha:
# for compatibility with bitnami charts
sha_key = "digest" if "digest" in value else "sha"
value[sha_key] = sha
value.ca.items.clear()
value.ca.items[sha_key] = [
None,
None,
CommentToken(
"# Managed by update-image-hash script\n\n",
ruamel.yaml.error.CommentMark(0),
None,
),
None,
]
elif isinstance(value, dict):
_update_images_sha(value, images_data)
class GitHubLogGroup:
def __init__(self, message: str) -> None:
self.message = message
def __enter__(self) -> None:
print(f"::group::{self.message}")
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
del exc_type, exc_value, traceback
print("::endgroup::")
def main() -> None:
parser = argparse.ArgumentParser(description="Update the images hash.")
args = parser.parse_args()
yaml = YAML()
yaml.default_flow_style = False
used_images = set()
for filename in glob.glob("**/*.yaml", recursive=True):
if "/templates/" in filename:
continue
basename = os.path.basename(filename)
if basename == "secrets.yaml" or basename.startswith("secrets-"):
continue
print(f"Open file: {filename}")
with open(filename, encoding="utf-8") as f:
values = yaml.load(f)
if "global" in values:
del values["global"]
_find_images(values, used_images, filename)
ghci_images = {}
for image in used_images:
print(f"Inspecting {image}")
if image.startswith("camptocamp/"):
image_name, image_tag = image.split(":", 1)
ghci_images[image] = {
"image": f'ghcr.io/{image_name}',
"tag": image_tag,
}
with open("data/ghci-images.yaml", "w", encoding="utf-8") as ghci_images_file:
yaml.dump(ghci_images, ghci_images_file)
if __name__ == "__main__":
main()