Skip to content
This repository was archived by the owner on Aug 25, 2024. It is now read-only.

Commit 9840d7c

Browse files
committed
scripts: images containers manifest: Build json from dirs
Related: #1273 Signed-off-by: John Andersen <[email protected]>
1 parent 7f98408 commit 9840d7c

File tree

1 file changed

+216
-0
lines changed

1 file changed

+216
-0
lines changed

scripts/images_containers_manifest.py

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
#!/usr/bin/env python
2+
# This file generates a manifest for building container images
3+
# Usage: JSON_INDENT=" " nodemon -e py,Dockerfile,HEAD --exec 'clear; python scripts/images_containers_manifest.py; test 1'
4+
import os
5+
import sys
6+
import json
7+
import pathlib
8+
import itertools
9+
import traceback
10+
import subprocess
11+
import urllib.request
12+
13+
14+
def path_to_image_name(path, root_path):
15+
# Stem as image name
16+
if path.stem != "Dockerfile":
17+
return path.stem
18+
# Non-top level no stem as image name (filename is Dockerfile)
19+
hyphen_dir_path = str(path.parent.relative_to(root_path)).replace(os.sep, "-").replace(".", "").replace("_", "-")
20+
if hyphen_dir_path != "." and hyphen_dir_path != "":
21+
return hyphen_dir_path
22+
# Top level dir Dockerfile use top level dirname
23+
return str(root_path.resolve().name)
24+
25+
26+
def main():
27+
# For running under GitHub actions within a container
28+
if "GITHUB_WORKSPACE" in os.environ:
29+
subprocess.check_call(["git", "config", "--global", "--add", "safe.directory", os.environ["GITHUB_WORKSPACE"]])
30+
31+
try:
32+
os.environ.update({
33+
"COMMIT": subprocess.check_output(["git", "log", "-n", "1", "--format=%H"]).decode().strip(),
34+
})
35+
except:
36+
traceback.print_exc(file=sys.stderr)
37+
38+
try:
39+
os.environ.update({
40+
"ROOT_PATH": str(pathlib.Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode().strip()).relative_to(os.getcwd())),
41+
"SCHEMA": "https://github.com/intel/dffml/raw/c82f7ddd29a00d24217c50370907c281c4b5b54d/schema/github/actions/build/images/containers/0.0.0.schema.json",
42+
"OWNER_REPOSITORY": "/".join(subprocess.check_output(["git", "remote", "get-url", "origin"]).decode().strip().replace(".git", "").split("/")[-2:]),
43+
"BRANCH": subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]).decode().strip(),
44+
"PREFIX": os.environ.get("PREFIX", json.dumps([
45+
".",
46+
"scripts",
47+
"dffml/skel/operations",
48+
])),
49+
"NO_DELTA_PREFIX": os.environ.get("NO_DELTA_PREFIX", json.dumps([
50+
".",
51+
"scripts",
52+
"dffml/skel/operations",
53+
])),
54+
})
55+
except:
56+
traceback.print_exc(file=sys.stderr)
57+
58+
# Pull request file change delta filter using GitHub API
59+
prefixes = json.loads(os.environ["PREFIX"])
60+
no_delta_prefixes = json.loads(os.environ["NO_DELTA_PREFIX"])
61+
owner, repository = os.environ["OWNER_REPOSITORY"].split("/", maxsplit=1)
62+
base = None
63+
env_vars = ["BASE", "BASE_REF"]
64+
for env_var in env_vars:
65+
if env_var in os.environ and os.environ[env_var].strip():
66+
# Set if present and not blank
67+
base = os.environ[env_var]
68+
69+
# Empty manifest (list of manifests for each build file) in case not triggered
70+
# from on file change (workflow changed or dispatched).
71+
manifest = []
72+
# Path to root of repo
73+
root_path = pathlib.Path(os.environ["ROOT_PATH"])
74+
# Grab commit from git
75+
commit = os.environ["COMMIT"]
76+
if base is not None:
77+
if "GITHUB_DELTA_RESPONSE_JSON" in os.environ:
78+
response_json = json.loads(os.environ["GITHUB_DELTA_RESPONSE_JSON"])
79+
else:
80+
compare_url = os.environ["COMPARE_URL"]
81+
compare_url = compare_url.replace("{base}", base)
82+
compare_url = compare_url.replace("{head}", os.environ["HEAD"])
83+
with urllib.request.urlopen(
84+
urllib.request.Request(
85+
compare_url,
86+
headers={
87+
"Authorization": "bearer " + os.environ["GH_ACCESS_TOKEN"],
88+
},
89+
)
90+
) as response:
91+
response_json = json.load(response)
92+
# Print for debug
93+
print(json.dumps({
94+
"@context": {
95+
"@vocab": "github_delta_response_json",
96+
},
97+
**response_json,
98+
}, sort_keys=True, indent=4), file=sys.stderr)
99+
# Build the most recent commit
100+
commit = response_json["commits"][-1]["sha"]
101+
manifest = list(itertools.chain(*(
102+
[
103+
[
104+
{
105+
"image_name": path_to_image_name(path, root_path),
106+
"dockerfile": str(path.relative_to(root_path)),
107+
"owner": owner,
108+
"repository": repository,
109+
"branch": os.environ["BRANCH"],
110+
"commit": commit,
111+
}
112+
for path in [
113+
pathlib.Path(compare_file["filename"])
114+
for compare_file in response_json["files"]
115+
if (
116+
any([
117+
(
118+
(
119+
pathlib.Path(compare_file["filename"]).parent.name == ""
120+
and prefix_path == "."
121+
)
122+
or pathlib.Path(compare_file["filename"]).parent.name == prefix_path
123+
)
124+
for prefix_path in prefixes
125+
]) and compare_file["filename"].endswith("Dockerfile")
126+
)
127+
]
128+
]
129+
] + [
130+
[
131+
json.loads(path.read_text())
132+
for path in [
133+
pathlib.Path(compare_file["filename"])
134+
for compare_file in response_json["files"]
135+
if (
136+
any([
137+
(
138+
(
139+
pathlib.Path(compare_file["filename"]).parent.name == ""
140+
and prefix_path == "."
141+
)
142+
or pathlib.Path(compare_file["filename"]).parent.name == prefix_path
143+
)
144+
for prefix_path in prefixes
145+
]) and compare_file["filename"].endswith("manifest.json")
146+
)
147+
]
148+
]
149+
]
150+
)))
151+
else:
152+
print(f"::notice file={__file__},line=1,endLine=1,title=nobase::None of {env_vars!r} found in os.environ", file=sys.stderr)
153+
manifest = list(itertools.chain(*(
154+
[
155+
[
156+
{
157+
"image_name": path_to_image_name(path, root_path),
158+
"dockerfile": str(path.relative_to(root_path)),
159+
"owner": owner,
160+
"repository": repository,
161+
"branch": os.environ["BRANCH"],
162+
"commit": commit,
163+
}
164+
for path in prefix_path.glob("*Dockerfile")
165+
]
166+
for prefix_path in map(pathlib.Path, prefixes)
167+
if any(
168+
str(prefix_path.relative_to(root_path)) in no_delta_prefix
169+
for no_delta_prefix in no_delta_prefixes
170+
)
171+
] + [
172+
[
173+
json.loads(path.read_text())
174+
for path in prefix_path.glob("*manifest.json")
175+
]
176+
for prefix_path in map(pathlib.Path, prefixes)
177+
if any(
178+
str(prefix_path.relative_to(root_path)) in no_delta_prefix
179+
for no_delta_prefix in no_delta_prefixes
180+
)
181+
]
182+
)))
183+
184+
# Add proxies or other runtime args/env vars
185+
for i in manifest:
186+
build_args = {}
187+
if "build_args" in i:
188+
build_args = dict(json.loads(i["build_args"]))
189+
for env_var in [
190+
"HTTP_PROXY",
191+
"HTTPS_PROXY",
192+
"NO_PROXY",
193+
]:
194+
if not env_var in os.environ:
195+
continue
196+
build_args[env_var] = os.environ[env_var]
197+
i["build_args"] = json.dumps(list(build_args.items()))
198+
199+
github_actions_manifest = {
200+
"include": manifest,
201+
}
202+
json_ld_manifest = {
203+
"@context": {
204+
"@vocab": os.environ["SCHEMA"],
205+
},
206+
**github_actions_manifest,
207+
}
208+
print(json.dumps(json_ld_manifest, sort_keys=True, indent=os.environ.get("JSON_INDENT", None)))
209+
210+
if "GITHUB_OUTPUT" in os.environ:
211+
with open(os.environ["GITHUB_OUTPUT"], "a") as fileobj:
212+
fileobj.write(f"manifest={json.dumps(manifest)}\n")
213+
fileobj.write(f'github_actions_manifest={json.dumps(github_actions_manifest)}\n')
214+
215+
if __name__ == "__main__":
216+
main()

0 commit comments

Comments
 (0)