diff --git a/scripts/generate_release_metadata.py b/scripts/generate_release_metadata.py index f1f6418bd616d94b04cb9bf51a7cfda0837a0be1..01752a767d9da1cd6f014829458ba6145e3e021f 100755 --- a/scripts/generate_release_metadata.py +++ b/scripts/generate_release_metadata.py @@ -7,39 +7,29 @@ from datetime import datetime def generate_metadata( machine, version, - artifacts_image, + image_artifacts, sdk, - output_dir, - outlocal_dir, + output_file, ): - """Generates a metainfo.json for the release""" + """Generate a metainfo.json for the release and write it to output_file.""" install_script = None licenses = None image_general = None image_wic = None - # Join filepath for metadata - - if output_dir is not None: - filepath = os.path.join(output_dir, machine, "metainfo.json") - elif outlocal_dir is not None: - filepath = os.path.join(outlocal_dir, machine, "metainfo.json") - else: - print("Error: Filepath is empty") - return -1 - # Collect metadata and write to metainfo.json - for artifact in artifacts_image: - if artifact == "fng-install.sh": - install_script = artifact - elif artifact == "license.manifest": - licenses = artifact - elif artifact.endswith(machine + ".tar.gz"): - image_general = artifact - elif artifact.endswith(machine + ".wic"): - image_wic = artifact + for artifact in image_artifacts: + filename = os.path.basename(artifact) + if filename == "fng-install.sh": + install_script = filename + elif filename == "license.manifest": + licenses = filename + elif filename.endswith(machine + ".tar.gz"): + image_general = filename + elif filename.endswith(machine + ".wic"): + image_wic = filename metadata = dict() @@ -78,5 +68,5 @@ def generate_metadata( new_file["path"] = licenses metadata["files"].append(new_file) - with open(filepath, "w", encoding="utf-8") as file: + with open(output_file, "w", encoding="utf-8") as file: file.write(json.dumps(metadata)) diff --git a/scripts/package_release.py b/scripts/package_release.py index 9e7a414dc21f42cc7a692d840346052300411182..68773cfd5e6f21d403f0ef8690e0fcbd305e491f 100755 --- a/scripts/package_release.py +++ b/scripts/package_release.py @@ -6,74 +6,53 @@ import os import sys import shutil import hashlib -import tempfile + from convert_md2html import convertmd2html from generate_release_metadata import generate_metadata -def md5(fname): +def md5(input_file: str): + """ + Calculate and return the MD5 sum of the given input_file. + """ hash_md5 = hashlib.md5() - with open(fname, "rb", encoding=None) as f: + with open(input_file, "rb", encoding=None) as f: for chunk in iter(lambda: f.read(4096), b""): hash_md5.update(chunk) return hash_md5.hexdigest() -def write_md5sums_file(md5sums, subdir, output_dir, outlocal_dir): - with tempfile.TemporaryDirectory() as tmp: - source_file = os.path.join(tmp, subdir, "md5sums.txt") - os.makedirs(os.path.dirname(source_file), exist_ok=True) - - with open(source_file, "w", encoding="utf-8") as f_md5: - for f, h in md5sums.items(): - f_md5.write("{} {}\n".format(h, f)) - - if output_dir is not None: - target_file = os.path.join( - output_dir, subdir, os.path.basename(source_file) - ) - print("Copy: %s -> %s" % (source_file, target_file)) - shutil.copyfile(source_file, target_file, follow_symlinks=True) - - if outlocal_dir is not None: - target_file = os.path.join( - outlocal_dir, subdir, os.path.basename(source_file) - ) - print("Copy: %s -> %s" % (source_file, target_file)) - shutil.copyfile(source_file, target_file, follow_symlinks=True) - - -def copy_files(files, input_dir, subdir, output_dir, outlocal_dir): +def generate_md5sums_file(input_files: list[str], output_file: str): + """ + Calculate MD5 sums of all input_files and write them to output_file. + """ md5sums = {} - if output_dir is not None: - os.makedirs(os.path.join(output_dir, subdir), exist_ok=True) - if outlocal_dir is not None: - os.makedirs(os.path.join(outlocal_dir, subdir), exist_ok=True) - - for f in files: - source_file = os.path.join(input_dir, f) + for f in input_files: + md5sums[os.path.basename(f)] = md5(f) + output_dir = os.path.dirname(output_file) + if output_dir: + os.makedirs(output_dir, exist_ok=True) + with open(output_file, "w", encoding="utf-8") as f_md5: + for f, h in md5sums.items(): + f_md5.write("{} {}\n".format(h, f)) + + +def copy_files(files: list[str], target_dir: str): + """ + Copy given files to target_dir. Create target_dir, if it does not exist. Subfolder + hierarchies on the input files will not be preserved, only plain files are copied. + """ + if target_dir is None: + return + os.makedirs(target_dir, exist_ok=True) + for source_file in files: if os.path.exists(source_file): - - if output_dir is not None: - target_file = os.path.join( - output_dir, subdir, os.path.basename(source_file) - ) - print("Copy: %s -> %s" % (source_file, target_file)) - shutil.copyfile(source_file, target_file, follow_symlinks=True) - - if outlocal_dir is not None: - target_file = os.path.join( - outlocal_dir, subdir, os.path.basename(source_file) - ) - print("Copy: %s -> %s" % (source_file, target_file)) - shutil.copyfile(source_file, target_file, follow_symlinks=True) - - md5sums[os.path.basename(source_file)] = md5(source_file) + target_file = os.path.join(target_dir, os.path.basename(source_file)) + print("Copy: %s -> %s" % (source_file, target_file)) + shutil.copyfile(source_file, target_file, follow_symlinks=True) else: print("Missing: " + source_file) - return md5sums - def main(): parser = argparse.ArgumentParser() @@ -121,7 +100,7 @@ def main(): if args.sdk_dir is not None: testdata_files += glob.glob(os.path.join(args.sdk_dir, "*.testdata.json")) - # Debug stuff + # Debug output if no testdata file found if not testdata_files: if args.images_dir is not None: print(args.images_dir) @@ -133,37 +112,39 @@ def main(): print("-- ", f) sys.exit("ERROR: no *.testdata.json file found in image or sdk dir.") + # The required build variables from testdata have the same values for image and SDK + # builds, so we just read one of them. with open(testdata_files[0], "r", encoding="utf-8") as f: buildvars = json.load(f) machine = buildvars["MACHINE"] version = buildvars["DISTRO_VERSION"] sdkname = buildvars["TOOLCHAIN_OUTPUTNAME"] - artifacts_image = buildvars["DISTRO_IMAGES"].split() - artifacts_all = buildvars["DISTRO_RELEASE_ARTEFACTS"].split() - artifacts_all.append("BUILD_SRCREVS.log") + image_artifacts = buildvars["DISTRO_IMAGES"].split() + artifacts = buildvars["DISTRO_RELEASE_ARTEFACTS"].split() + artifacts.append("BUILD_SRCREVS.log") + # Set release name if version.startswith("fngsystem"): - release_name_local = version.replace("fngsystem", "FNGSystem") - # outlocal_base = "/artifacts-fngsystem" + release_name = version.replace("fngsystem", "FNGSystem") else: - release_name_local = "Yocto-%s" % version - # outlocal_base = "/artifacts-yocto" + release_name = "Yocto-%s" % version # Create output directories if args.outputdir_upload is not None: - output_dir = os.path.join(args.outputdir_upload, release_name_local) - os.makedirs(output_dir, exist_ok=True) + outputdir_upload = os.path.join(args.outputdir_upload, release_name) + os.makedirs(outputdir_upload, exist_ok=True) else: - output_dir = None + outputdir_upload = None if args.outputdir_local is not None: - outlocal_dir = os.path.join(args.outputdir_local, release_name_local) - os.makedirs(outlocal_dir, exist_ok=True) + outputdir_local = os.path.join(args.outputdir_local, release_name) + os.makedirs(outputdir_local, exist_ok=True) else: - outlocal_dir = None + outputdir_local = None - # Convert markdown files into html and package them + # Package documentation files if args.doc_dir is not None: + # Convert markdown to html doc_files = glob.glob(os.path.join(args.doc_dir, "*.md")) html_files = [] for f in doc_files: @@ -171,20 +152,28 @@ def main(): convertmd2html(f, fout) html_files.append(fout) - doc_md5sums = copy_files( - doc_files + html_files, "", "", output_dir, outlocal_dir - ) - write_md5sums_file(doc_md5sums, "", output_dir, outlocal_dir) + files = doc_files + html_files + # Generate MD5 sums file + doc_md5sums_file = "md5sums.txt" + generate_md5sums_file(files, doc_md5sums_file) + files.append(doc_md5sums_file) + + # Copy files + if outputdir_upload is not None: + copy_files(files, outputdir_upload) + if outputdir_local is not None: + copy_files(files, outputdir_local) + + # Package image files if args.images_dir is not None: # Add some additional files to the artifacts - for artifact in artifacts_image: - artifacts_all.append(artifact.split(".")[0] + ".manifest") - artifacts_all.append(artifact.split(".")[0] + ".testdata.json") + for artifact in image_artifacts: + artifacts.append(artifact.split(".")[0] + ".manifest") + artifacts.append(artifact.split(".")[0] + ".testdata.json") - md5sums = copy_files( - artifacts_all, args.images_dir, machine, output_dir, outlocal_dir - ) + # Prepend path to artifacts + artifacts = [os.path.join(args.images_dir, artifact) for artifact in artifacts] # If the path for the licenses is set, we check for the list with all # licenses. If the list is found, we copy it to the output directory @@ -194,52 +183,49 @@ def main(): license_manifest = glob.glob( os.path.join(args.licenses_dir, "**", "license.manifest") ) + artifacts.append( + os.path.join(os.path.dirname(license_manifest[0]), "license.manifest") + ) - if license_manifest: - md5sums.update( - copy_files( - ["license.manifest"], - os.path.dirname(license_manifest[0]), - machine, - output_dir, - outlocal_dir, - ) - ) - artifacts_all.append("license.manifest") - - # Create md5sums file for build artifacts - write_md5sums_file(md5sums, machine, output_dir, outlocal_dir) - - # Generate metadata in case of an image build - if args.sdk_dir is None: + # Generate MD5 sums file + image_md5sums_file = os.path.join(args.images_dir, "md5sums.txt") + generate_md5sums_file(artifacts, image_md5sums_file) + artifacts.append(image_md5sums_file) + + # Generate metadata file generate_metadata( machine, version, - artifacts_all, + artifacts, sdkname, - output_dir, - outlocal_dir, + os.path.join(args.images_dir, "metainfo.json"), ) + artifacts.append(os.path.join(args.images_dir, "metainfo.json")) + + # Copy files + if outputdir_upload is not None: + copy_files(artifacts, os.path.join(outputdir_upload, machine)) + if outputdir_local is not None: + copy_files(artifacts, os.path.join(outputdir_local, machine)) - # Handle SDK if available + # Package SDK if args.sdk_dir is not None: sdkfiles = glob.glob(os.path.join(args.sdk_dir, sdkname + "*")) - print("package_release.py: Upload the following sdk files:") - print(sdkfiles) - sdk_md5sums = copy_files( - sdkfiles, "", os.path.join(machine, "sdk"), None, outlocal_dir - ) - write_md5sums_file( - sdk_md5sums, os.path.join(machine, "sdk"), None, outlocal_dir - ) - else: - print("package_release.py: sdk_dir is not specified") + + # Generate MD5 sums file + sdk_md5sums_file = os.path.join(machine, "sdk", "md5sums.txt") + generate_md5sums_file(sdkfiles, sdk_md5sums_file) + sdkfiles.append(sdk_md5sums_file) + + # Copy files + if outputdir_local is not None: + copy_files(sdkfiles, os.path.join(outputdir_local, machine, "sdk")) # Store pathes and other stuff in environment variable file with open("package.env", "w", encoding="utf-8") as env_file: env_file.write("VERSION={}\n".format(version)) env_file.write("MACHINE={}\n".format(machine)) - env_file.write("LOCALDIR={}\n".format(outlocal_dir)) + env_file.write("LOCALDIR={}\n".format(outputdir_local)) if __name__ == "__main__":