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

Commit 3a6665d

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

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

scripts/images_containers_manifest.py

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

0 commit comments

Comments
 (0)