#!/usr/bin/env python3 # # Build performance test script wrapper # # Copyright (c) 2019, Linux Foundation # # This program is free software; you can redistribute it and/or modify it # under the terms and conditions of the GNU General Public License, # version 2, as published by the Free Software Foundation. # # This program is distributed in the hope it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. # # This script is a simple wrapper around the build performance tests import os import fcntl import errno import utils import subprocess import sys import datetime parser = utils.ArgParser(description='Run a build performance test and process the results.') parser.add_argument('-a', '--archive-dir', action='store', help="Where to archive a results tarball") parser.add_argument('-C', '--git-repo', action='store', help="Commit results into this git repository") parser.add_argument('-d', '--download-dir', action='store', help="Directory to download sources into") parser.add_argument('-E', '--email-addr', action='store', help="Send an email report to this address") parser.add_argument('-g', '--global-results', action='store', help="Save a global results file in this directory") parser.add_argument('-P', '--push-remote', action='store', help="Push git changes to this remote repository") parser.add_argument('-r', '--results-dir', action='store', help="Where to store results artefacts") parser.add_argument('-w', '--work-dir', action='store', help="build directory to run the tests in") parser.add_argument('-p', '--publish-dir', action='store', help="directory to publish into") args = parser.parse_args() scriptsdir = os.path.dirname(os.path.realpath(__file__)) ourconfig = utils.loadconfig() if args.git_repo: os.makedirs(args.git_repo, exist_ok=True) if args.download_dir: os.makedirs(args.download_dir, exist_ok=True) if args.global_results: os.makedirs(args.global_results, exist_ok=True) if args.publish_dir: os.makedirs(args.publish_dir, exist_ok=True) archiveopts = "" if args.push_remote: archiveopts += "--push " + args.push_remote if args.results_dir: args.archive_dir = args.results_dir + "/archive" args.git_repo = args.results_dir + "/archive-repo" args.global_results = args.results_dir os.makedirs(args.results_dir, exist_ok=True) if args.email_addr: try: subprocess.check_output(["which", "phantomjs"]) except subprocess.CalledProcessError: print("Please install phantomjs to email reports") sys.exit(1) try: subprocess.check_output(["which", "optipng"]) except subprocess.CalledProcessError: print("Please install optipng to email reports") sys.exit(1) op = fcntl.LOCK_EX try: lf = open("/tmp/oe-build-perf-test-wrapper.lock", 'a+') fileno = lf.fileno() fcntl.flock(fileno, op) except OSError as e: print("Another version of the script is running") try: lf.close() except Exception: pass sys.exit(1) print("Running on " + os.uname()[1]) try: gitdir = subprocess.check_output("git rev-parse --show-toplevel", shell=True).decode("utf-8").strip() except subprocess.CalledProcessError: print("The current working dir doesn't seem to be a git clone. Please cd there before running " + sys.argv[0]) sys.exit(1) os.chdir(gitdir) # Determine name of the current branch branch = subprocess.check_output("git symbolic-ref HEAD 2> /dev/null", shell=True).decode("utf-8").strip() # Strip refs/heads/ branch = branch[11:] if not args.work_dir: args.work_dir = gitdir + "/build-perf-test" if not args.archive_dir: args.archive_dir = gitdir + "/archive-results" os.makedirs(args.archive_dir, exist_ok=True) # Ensure we start with a clean build buil directory subprocess.check_call("rm -rf %s/*" % args.work_dir, shell=True) os.makedirs(args.work_dir + "/conf", exist_ok=True) # copy in auto.conf subprocess.check_call("cp -r %s/build/conf/auto.conf %s/conf" % (gitdir, args.work_dir), shell=True) print("Using working dir " + args.work_dir) if not args.download_dir: args.download_dir = args.work_dir + "\downloads" if not args.global_results: args.global_results = args.work_dir timestamp = datetime.datetime.now().strftime('%Y%m%d%H%M%S') gitrev = subprocess.check_output("git rev-parse --short HEAD", shell=True).decode("utf-8").strip() build_dir = args.work_dir + "build-" + gitrev + "-" + timestamp results_tmpdir = args.work_dir + "results-" + gitrev + "-" + timestamp globalres_log = args.global_results + "/globalres.log" machine = "qemux86" os.makedirs(args.work_dir, exist_ok=True) # Run actual test script ret = subprocess.call(". ./oe-init-build-env %s >/dev/null; oe-build-perf-test --out-dir %s --globalres-file %s --lock-file %s/oe-build-perf.lock" % (build_dir, results_tmpdir, globalres_log, args.work_dir), shell=True) if ret == 1: print("ERROR: oe-build-perf-test script failed!") sys.exit(1) if ret == 2: print("ERROR: some tests failed!") if args.publish_dir: subprocess.check_call("cp -r " + results_tmpdir + "/* " + args.publish_dir, shell=True) # Commit results to git if args.git_repo: print("\nArchiving results in " + args.git_repo) subprocess.check_call(". ./oe-init-build-env %s >/dev/null; oe-git-archive " % build_dir + \ "--git-dir " + args.git_repo + " " \ "--branch-name '{hostname}/{branch}/{machine}' " \ "--tag-name '{hostname}/{branch}/{machine}/{commit_count}-g{commit}/{tag_number}' " \ "--exclude 'buildstats.json' " \ "--notes 'buildstats/{branch_name}' " + results_tmpdir + "/buildstats.json " \ + archiveopts + " " + results_tmpdir, shell=True) # Generate test reports sanitized_branch = branch.replace("/", "_") report_txt = os.uname()[1] + "_" + sanitized_branch + "_" + machine + ".txt" report_html = os.uname()[1] + "_" + sanitized_branch + "_" + machine + ".html" print("\nGenerating test report") subprocess.check_call(". ./oe-init-build-env %s >/dev/null; oe-build-perf-report -r " % build_dir + args.git_repo + " > ../" + report_txt, shell=True) subprocess.check_call(". ./oe-init-build-env %s >/dev/null; oe-build-perf-report -r " % build_dir + args.git_repo + " --html ../> " + report_html, shell=True) filename = os.uname()[1] + "_" + sanitized_branch + "_" + timestamp + "_" + gitrev subprocess.check_call("cp " + report_txt + " " + args.global_results + "/" + filename + ".txt", shell=True) subprocess.check_call("cp " + report_html + " " + args.global_results + "/" + filename + ".html", shell=True) if args.publish_dir: subprocess.check_call("cp " + report_txt + " " + args.publish_dir + "/" + filename + ".txt", shell=True) subprocess.check_call("cp " + report_html + " " + args.publish_dir + "/" + filename + ".html", shell=True) # Send email report if args.email_addr: print("Emailing test report") os_name = subprocess.check_output(". /etc/os-release; eval echo '$'PRETTY_NAME", shell=True).decode("utf-8").strip() cmd = scriptsdir + "/oe-build-perf-report-email.py --to '" + args.email_addr + \ "' --subject 'Build Perf Test Report for " + os_name + "' --text " + \ report_txt + " --html " + report_html try: subprocess.check_call(cmd, shell=True) except subprocess.CalledProcessError: print("ERROR: Send email command %s failed" % cmd) if args.archive_dir: print("\n\n-----------------\n") print("Archiving results in " + args.archive_dir) os.makedirs(args.archive_dir, exist_ok=True) results_basename = os.path.basename(results_tmpdir) results_dirname = os.path.dirname(results_tmpdir) cmd = "tar -czf" + args.archive_dir + "/" + os.uname()[1] + "-" + results_basename + ".tar.gz -C " + results_dirname + " " + results_basename subprocess.check_call(cmd, shell=True) subprocess.check_call("rm -rf %s" % build_dir, shell=True) subprocess.check_call("rm -rf %s" % results_tmpdir, shell=True) print("DONE")