Skip to content

Commit

Permalink
test: use osbuild commit for build test filtering
Browse files Browse the repository at this point in the history
Record the osbuild commit ID from the Schutzfile in the build info when
a build is successful.
If a commit ID isn't specified, record it as "RELEASE" to signify that
the osbuild version is the one in the distro repos.
If the osbuild version and commit ID don't match, schedule the config
for a build.

This makes sure that changes in osbuild which don't affect the manifest
get retested.  This can catch bugs that weren't caught in osbuild and is
useful for testing internal osbuild functionality changes.

This commit also fixes a typo in the build info.json:
obuild-version -> osbuild-version
  • Loading branch information
achilleas-k committed Dec 19, 2023
1 parent b48a61a commit 9038000
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 38 deletions.
27 changes: 17 additions & 10 deletions test/scripts/build-image
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def main():
print(f"👷 Building image {distro}/{image_type} using config {config_path}")

# print the config for logging
with open(config_path, "r") as config_file:
with open(config_path, "r", encoding="utf-8") as config_file:
config = json.load(config_file)
print(json.dumps(config, indent=2))
config_name = config["name"]
Expand All @@ -43,23 +43,30 @@ def main():
arch = os.uname().machine
build_dir = os.path.join("build", testlib.gen_build_name(distro, arch, image_type, config_name))
manifest_path = os.path.join(build_dir, "manifest.json")
with open(manifest_path, "r") as manifest_fp:
with open(manifest_path, "r", encoding="utf-8") as manifest_fp:
manifest_data = json.load(manifest_fp)
manifest_id = testlib.get_manifest_id(manifest_data)

osbuild_ver, _ = testlib.runcmd(["osbuild", "--version"])

osrelease = testlib.read_osrelease()
distro_version = osrelease["ID"] + "-" + osrelease["VERSION_ID"]
osbuild_commit = testlib.get_osbuild_commit(distro_version)
if osbuild_commit is None:
osbuild_commit = "RELEASE"

build_info = {
"distro": distro,
"arch": arch,
"image-type": image_type,
"config": config_name,
"manifest-checksum": manifest_id,
"obuild-version": osbuild_ver.decode(),
"commit": os.environ.get("CI_COMMIT_SHA", "N/A")
"distro": distro,
"arch": arch,
"image-type": image_type,
"config": config_name,
"manifest-checksum": manifest_id,
"osbuild-version": osbuild_ver.decode().strip(),
"osbuild-commit": osbuild_commit,
"commit": os.environ.get("CI_COMMIT_SHA", "N/A")
}
info_file_path = os.path.join(build_dir, "info.json")
with open(info_file_path, "w") as info_fp:
with open(info_file_path, "w", encoding="utf-8") as info_fp:
json.dump(build_info, info_fp, indent=2)


Expand Down
89 changes: 62 additions & 27 deletions test/scripts/imgtestlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,58 @@ def read_manifests(path):
return manifests


def check_for_build(manifest_fname, build_info_path, osbuild_ver, osbuild_commit, errors):
# rebuild if matching build info is not found
if not os.path.exists(build_info_path):
return True

try:
with open(build_info_path, encoding="utf-8") as build_info_fp:
dl_config = json.load(build_info_fp)
except json.JSONDecodeError as jd:
errors.append((
f"failed to parse {build_info_path}\n"
f"{jd.msg}\n"
"Scheduling config for rebuild\n"
))

# check if osbuild version matches
config_osbuild_commit = dl_config.get("osbuild-commit", None)
config_osbuild_ver = dl_config.get("osbuild-version", None)
if config_osbuild_commit is None:
# TODO: remove this check when all the build infos get updated
print("osbuild commit ID not found in build info. Scheduling config for rebuild.")
return True

osbuild_id = f"{osbuild_ver}:{osbuild_commit}"
config_osbuild_id = f"{config_osbuild_ver}:{config_osbuild_commit}"

if osbuild_id != config_osbuild_id:
print(f"🖼️ Manifest {manifest_fname} was built with {config_osbuild_id}")
print(f" Testing {osbuild_id}")
return True

commit = dl_config["commit"]
pr = dl_config.get("pr")
url = f"https://github.com/osbuild/images/commit/{commit}"
print(f"🖼️ Manifest {manifest_fname} was successfully built in commit {commit}\n {url}")
if pr:
print(f" PR-{pr}: https://github.com/osbuild/images/pull/{pr}")

image_type = dl_config["image-type"]
if image_type not in CAN_BOOT_TEST:
print(f" Boot testing for {image_type} is not yet supported")
return False

# boot testing supported: check if it's been tested, otherwise queue it for rebuild and boot
if dl_config.get("boot-success", False):
print(" This image was successfully boot tested")
return False

# default to build
return True


def filter_builds(manifests, skip_ostree_pull=True):
"""
Returns a list of build requests for the manifests that have no matching config in the test build cache.
Expand All @@ -187,6 +239,14 @@ def filter_builds(manifests, skip_ostree_pull=True):

errors = []

osrelease = read_osrelease()
distro_version = osrelease["ID"] + "-" + osrelease["VERSION_ID"]
osbuild_commit = get_osbuild_commit(distro_version)
if osbuild_commit is None:
osbuild_commit = "RELEASE"
osbuild_ver, _ = runcmd(["osbuild", "--version"])
osbuild_ver = osbuild_ver.decode().strip()

for manifest_fname, data in manifests.items():
manifest_id = data["id"]
data = data.get("data")
Expand All @@ -209,33 +269,8 @@ def filter_builds(manifests, skip_ostree_pull=True):
dl_config_dir = os.path.join(dl_path, distro, arch)
build_info_path = os.path.join(dl_config_dir, manifest_id, "info.json")

# check if the id_fname exists in the synced directory
if os.path.exists(build_info_path):
try:
with open(build_info_path) as build_info_fp:
dl_config = json.load(build_info_fp)
commit = dl_config["commit"]
pr = dl_config.get("pr")
url = f"https://github.com/osbuild/images/commit/{commit}"
print(f"🖼️ Manifest {manifest_fname} was successfully built in commit {commit}\n {url}")
if pr:
print(f" PR-{pr}: https://github.com/osbuild/images/pull/{pr}")
if image_type not in CAN_BOOT_TEST:
print(f" Boot testing for {image_type} is not yet supported")
continue
# boot testing supported: check if it's been tested, otherwise queue it for rebuild and boot
if dl_config.get("boot-success", False):
print(" This image was successfully boot tested")
continue
except json.JSONDecodeError as jd:
errors.append((
f"failed to parse {build_info_path}\n"
f"{jd.msg}\n"
"Scheduling config for rebuild\n"
f"Config: {distro}/{arch}/{image_type}/{config_name}\n"
))

build_requests.append(build_request)
if check_for_build(manifest_fname, build_info_path, osbuild_ver, osbuild_commit, errors):
build_requests.append(build_request)

print("✅ Config filtering done!\n")
if errors:
Expand Down
2 changes: 1 addition & 1 deletion test/scripts/setup-osbuild-repo
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def write_repo(commit, distro_version):
arch = os.uname().machine
repo_path = f"osbuild/{distro_version}/{arch}/{commit}"
print(f"Setting up dnf repository for {commit} ({repo_path})")
with open("/etc/yum.repos.d/osbuild.repo", "w", endoding="utf-8") as repofile:
with open("/etc/yum.repos.d/osbuild.repo", "w", encoding="utf-8") as repofile:
repofile.write(REPO_TEMPLATE.format(commit=commit, repo_path=repo_path))


Expand Down

0 comments on commit 9038000

Please sign in to comment.