-
Jonas Höppner authored
BCS 746-000669
0f7e517b
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
package_release.py 10.39 KiB
#!/usr/bin/env python3
import argparse
import glob
import json
import os
import sys
import shutil
import hashlib
import tempfile
import alphaplan_fwr
from datetime import datetime
from convert_md2html import convertmd2html
def md5(fname):
hash_md5 = hashlib.md5()
with open(fname, "rb", encoding=None) as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def copy_files(files, input_dir, subdir, output_dir, outlocal_dir):
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)
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)
else:
print("Missing: " + source_file)
# Write md5sums file:
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)
return md5sums
def generate_metadata(
machine,
version,
artifacts_image,
sdk,
output_dir,
outlocal_dir,
):
"""Generates a metainfo.json for the release"""
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
metadata = dict()
metadata["files"] = []
metadata["version"] = version
metadata["machine"] = machine
metadata["date"] = datetime.today().strftime("%Y-%m-%d")
if install_script is not None:
new_file = dict()
new_file["name"] = "Install Script"
new_file["path"] = install_script
metadata["files"].append(new_file)
if image_general is not None:
new_file = dict()
new_file["name"] = "Image"
new_file["path"] = image_general
metadata["files"].append(new_file)
if image_wic is not None:
new_file = dict()
new_file["name"] = "SD-Card Image (WIC)"
new_file["path"] = image_wic
metadata["files"].append(new_file)
if sdk is not None:
new_file = dict()
new_file["name"] = "SDK"
new_file["path"] = "sdk/" + sdk + ".sh"
metadata["files"].append(new_file)
if licenses is not None:
new_file = dict()
new_file["name"] = "Licenses"
new_file["path"] = licenses
metadata["files"].append(new_file)
with open(filepath, "w", encoding="utf-8") as file:
file.write(json.dumps(metadata))
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--images-dir",
help="""Yocto images directory""",
dest="images_dir",
)
parser.add_argument(
"--licenses-dir",
help="""Yocto licenses directory""",
dest="licenses_dir",
)
parser.add_argument(
"--outputdir-upload",
help="""Base directory name for uploaded artifacts""",
dest="outputdir_upload",
)
parser.add_argument(
"--outputdir-local",
help="""Base directory for locally deployed artifacts, should contain absolut path.""",
dest="outputdir_local",
)
parser.add_argument(
"--sdk-dir",
help="""Yocto sdk directory""",
dest="sdk_dir",
)
parser.add_argument(
"--doc-dir",
help="""Documentation directory""",
dest="doc_dir",
)
parser.add_argument(
"--generate-fwr-articles",
help="""Enable AlphaPlan FWR generation""",
dest="generate_fwr_articles",
action="store_true",
)
parser.set_defaults(generate_fwr_articles=False)
args, _ = parser.parse_known_args()
if args.outputdir_upload is None and args.outputdir_local is None:
sys.exit(
"ERROR: Either outputdir-local and/or outputdir-upload needs to be specified."
)
# Get bitbake variables from testdata.json file
testdata_files = []
if args.images_dir is not None:
testdata_files += glob.glob(os.path.join(args.images_dir, "*.testdata.json"))
if args.sdk_dir is not None:
testdata_files += glob.glob(os.path.join(args.sdk_dir, "*.testdata.json"))
# Debug stuff
if not testdata_files:
if args.images_dir is not None:
print(args.images_dir)
for f in glob.glob(args.images_dir + "/*"):
print("-- ", f)
if args.sdk_dir is not None:
print(args.sdk_dir)
for f in glob.glob(args.sdk_dir + "/*"):
print("-- ", f)
sys.exit("ERROR: no *.testdata.json file found in image or sdk dir.")
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")
if version.startswith("fngsystem"):
release_name_local = version.replace("fngsystem", "FNGSystem")
release_name = release_name_local
# outlocal_base = "/artifacts-fngsystem"
else:
release_name = "GUF-Yocto-%s" % version
release_name_local = "Yocto-%s" % version
# outlocal_base = "/artifacts-yocto"
# Create output directories
if args.outputdir_upload is not None:
output_dir = os.path.join(args.outputdir_upload, release_name)
os.makedirs(output_dir, exist_ok=True)
else:
output_dir = 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)
else:
outlocal_dir = None
if args.doc_dir is not None:
doc_files = glob.glob(os.path.join(args.doc_dir, "*.md"))
html_files = []
for f in doc_files:
fout = os.path.splitext(f)[0] + ".html"
convertmd2html(f, fout)
html_files.append(fout)
copy_files(doc_files + html_files, "", "", output_dir, outlocal_dir)
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")
md5sums = copy_files(
artifacts_all, args.images_dir, machine, output_dir, outlocal_dir
)
# 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
# and also add it to the artifacts dictionary.
if args.licenses_dir is not None and os.path.isdir(args.licenses_dir):
manifest = glob.glob(
os.path.join(args.licenses_dir, "**", "license.manifest")
)
if manifest:
md5sums.update(
copy_files(
["license.manifest"],
os.path.dirname(manifest[0]),
machine,
output_dir,
outlocal_dir,
)
)
artifacts_all.append("license.manifest")
# Generate alphaplan FWR articles
if args.generate_fwr_articles:
alphaplan_fwr.generate_fwr_articles(
output_dir,
outlocal_dir,
machine,
release_name_local,
artifacts_all,
md5sums,
)
# Generate metadata
generate_metadata(
machine,
version,
artifacts_all,
sdkname,
output_dir,
outlocal_dir,
)
# Handle SDK if available
if args.sdk_dir is not None:
sdkfiles = glob.glob(os.path.join(args.sdk_dir, sdkname + "*"))
copy_files(sdkfiles, "", os.path.join(machine, "sdk"), None, outlocal_dir)
# 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))
if __name__ == "__main__":
main()