[Qa-jenkins-scm] [Git][qa/jenkins.debian.net][master] 2 commits: reproducible_common: add file
Holger Levsen
gitlab at salsa.debian.org
Mon Oct 7 08:12:33 BST 2019
Holger Levsen pushed to branch master at Debian QA / jenkins.debian.net
Commits:
94dcfb4c by Paul Spooren at 2019-10-07T07:11:56Z
reproducible_common: add file
This file should grow later to a reusable python library to avoid
redundant code. For now it allows to run diffoscope both with and
withouth schroot and compare files and get diffoscope version.
Signed-off-by: Paul Spooren <mail at aparcar.org>
Signed-off-by: Holger Levsen <holger at layer-acht.org>
- - - - -
f73cf72f by Paul Spooren at 2019-10-07T07:12:04Z
openwrt-rebuild: update to use schroot
Signed-off-by: Holger Levsen <holger at layer-acht.org>
- - - - -
5 changed files:
- + bin/reproducible_common.py
- bin/reproducible_openwrt_rebuild.py
- mustache-templates/openwrt/header.mustache
- mustache-templates/openwrt/index.mustache
- mustache-templates/openwrt/target.mustache
Changes:
=====================================
bin/reproducible_common.py
=====================================
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2019 Paul Spooren <mail at aparcar.org>
+#
+# Inspired by reproducible_common.sh
+# © Holger Levsen <holger at layer-acht.org>
+#
+# Released under the GPLv2
+
+import os
+import subprocess
+import resource
+
+
+def e(var, default):
+ """Return env variable or default"""
+ return os.environ.get(var, default)
+
+
+# DBSUITE which version of diffoscope to use
+timeout = e("TIMEOUT", 30 * 60) # 30m
+# DIFFOSCOPE_VIRT_LIMIT max RAM usage
+ds_virt_limit = int(e("DIFFOSCOPE_VIRT_LIMIT", 10 * 1024 ** 3)) # 10GB
+# TIMEOUT timeout for diffoscope in seconds
+dbsuite = e("DBDSUITE", "unstable")
+# SCHROOT to use
+schroot = e("SCHROOT", f"source:jenkins-reproducible-{dbsuite}-diffoscope")
+
+
+def limit_resources():
+ resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
+ resource.setrlimit(resource.RLIMIT_AS, (ds_virt_limit, resource.RLIM_INFINITY))
+
+
+def diffoscope_version():
+ cmd = []
+ if schroot:
+ cmd.extend(["schroot", "--directory", "/tmp", "-c", schroot])
+
+ cmd.extend(["diffoscope", "--", "--version"])
+ print(cmd)
+ return (
+ subprocess.run(cmd, capture_output=True, text=True, preexec_fn=limit_resources)
+ .stdout.strip()
+ .split()[1]
+ )
+
+
+def diffoscope_compare(path_a, path_b, path_output_html):
+ """
+ Run diffoscope in a schroot environment
+
+ Args:
+ - path_a path to first file to compare
+ - path_b path to second file a to compare
+ - path_output_html path where to store result html
+ """
+ cmd = []
+ if schroot:
+ cmd.extend(
+ ["schroot", "--directory", os.path.dirname(path_output_html), "-c", schroot]
+ )
+
+ try:
+ cmd.extend(["diffoscope", "--", "--html", path_output_html, path_a, path_b])
+ result = subprocess.run(
+ cmd,
+ timeout=timeout,
+ capture_output=True,
+ text=True,
+ preexec_fn=limit_resources,
+ )
+ msg = f"diffoscope {diffoscope_version()} "
+ if result.returncode == 0:
+ print(msg + f"{path_a} reproducible, yay!")
+ else:
+ if result.returncode == 1:
+ print(msg + f"found issues, please investigate {path_a}")
+ elif result.returncode == 2:
+ with open(path_output_html, "w") as output_html_file:
+ output_html_file.write(
+ msg
+ + f"""had trouble comparing the two builds. Please
+ investigate {path_a}"""
+ )
+
+ except subprocess.TimeoutExpired:
+ if os.path.exists(path_output_html):
+ print(
+ msg
+ + f"""produced no output comparing {path_a} with {path_b} and
+ was killed after running into timeout after {timeout}..."""
+ )
+ else:
+ print(
+ msg
+ + """was killed after running into timeout after $TIMEOUT, but
+ there is still {path_output_html}"""
+ )
=====================================
bin/reproducible_openwrt_rebuild.py
=====================================
@@ -1,4 +1,14 @@
#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# Copyright © 2019 Paul Spooren <mail at aparcar.org>
+#
+# Based on the reproducible_openwrt.sh
+# © 2014-2019 Holger Levsen <holger at layer-acht.org>
+# © 2015 Reiner Herrmann <reiner at reiner-h.de>
+# © 2016-2018 Alexander Couzens <lynxis at fe80.eu>
+#
+# Released under the GPLv2
import os
import re
@@ -11,83 +21,94 @@ from multiprocessing import cpu_count
from multiprocessing import Pool
from time import strftime, gmtime
import shutil
-import importlib
+import json
+
+from reproducible_common import diffoscope_compare, diffoscope_version
+from reproducible_openwrt_package_parser import insert_into_db, show_list_difference
# target to be build
target = os.environ.get("TARGET", "ath79/generic")
# version to be build
version = os.environ.get("VERSION", "SNAPSHOT")
-# where to store rendered html and diffoscope output
-output_dir = os.environ.get("OUTPUT_DIR", "/srv/reproducible-results")
# where to (re)build openwrt
-temporary_dir = os.environ.get("TMP_DIR", mkdtemp(dir="/srv/workspace/chroots/"))
+# as of openwrt.git 27bf8abe69 should be /builder/shared-workdir/build
+rebuild_dir = os.environ.get("REBUILD_DIR")
+if not rebuild_dir:
+ rebuild_dir = mkdtemp(dir="/srv/workspace/chroots/")
+# where to store rendered html and diffoscope output
+results_dir = os.environ.get("RESULTS_DIR")
+if not results_dir:
+ results_dir = mkdtemp(dir="/srv/reproducible-results")
# where to find mustache templates
-template_dir = os.environ.get(
- "TEMPLATE_DIR", "/srv/jenkins/mustache-templates/reproducible"
-)
+template_dir = os.environ.get("TEMPLATE_DIR", "/srv/jenkins/mustache-templates/openwrt")
# where to find the origin builds
-openwrt_url = (
- os.environ.get("ORIGIN_URL", "https://downloads.openwrt.org/snapshots/targets/")
- + target
-)
+origin_url = os.environ.get("ORIGIN_URL", "https://downloads.openwrt.org")
+
+if version == "SNAPSHOT":
+ download_url = f"{origin_url}/snapshots/targets/{target}"
+else:
+ download_url = f"{origin_url}/releases/{version}/targets/{target}"
# dir of the version + target
-target_dir = os.path.join(output_dir, version, target)
+results_target_dir = os.path.join(results_dir, version, target)
+
# dir where openwrt actually stores binary files
-rebuild_dir = temporary_dir + "/bin/targets/" + target
+target_dir = rebuild_dir + "/bin/targets/" + target
# where to get the openwrt source git
openwrt_git = os.environ.get("OPENWRT_GIT", "https://github.com/openwrt/openwrt.git")
+
# run a command in shell
-def run_command(cmd, cwd=".", ignore_errors=False):
+def run_command(cmd, cwd=".", ignore_errors=False, env={}):
print("Running {} in {}".format(cmd, cwd))
- proc = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE)
- response = ""
- # print and store the output at the same time
- while True:
- line = proc.stdout.readline().decode("utf-8")
- if line == "" and proc.poll() != None:
- break
- response += line
- print(line, end="", flush=True)
-
- if proc.returncode and not ignore_errors:
+ current_env = os.environ.copy()
+ current_env.update(env)
+ result = subprocess.run(
+ cmd, cwd=cwd, capture_output=True, text=True, env=current_env
+ )
+
+ if result.returncode and not ignore_errors:
print("Error running {}".format(cmd))
+ print(result.stderr)
quit()
- return response
+
+ return result.stdout
# files not to check via diffoscope
meta_files = re.compile(
"|".join(
[
- ".+\.buildinfo",
- ".+\.manifest",
- "openwrt-imagebuilder",
- "openwrt-sdk",
- "sha256sums",
- "kernel-debug.tar.bz2",
+ r".+\.buildinfo",
+ r".+\.manifest",
+ r"openwrt-imagebuilder",
+ r"openwrt-sdk",
+ r"sha256sums",
+ r"kernel-debug.tar.bz2",
]
)
)
# the context to fill the mustache tempaltes
context = {
+ "root": "https://tests.reproducible-builds.org/openwrt",
"targets": [
{"version": "SNAPSHOT", "name": "ath79/generic"},
{"version": "SNAPSHOT", "name": "x86/64"},
{"version": "SNAPSHOT", "name": "ramips/mt7621"},
+ {"version": "SNAPSHOT", "name": "ramips/mt7620"},
],
"version": version,
"commit_string": "",
"images_repro": 0,
"images_repro_percent": 0,
+ "kernelversion": "unknown",
"images_total": 0,
"packages_repro": 0,
"packages_repro_percent": 0,
"packages_total": 0,
"today": strftime("%Y-%m-%d", gmtime()),
- "diffoscope_version": run_command(["diffoscope", "--version"]).split()[1],
+ "diffoscope_version": diffoscope_version(),
"target": target,
"images": [],
"packages": [],
@@ -95,26 +116,24 @@ context = {
"missing": [],
}
-# download file from openwrt server and compare it, store output in target_dir
+
+# download file from openwrt server and compare it, store output in results_target_dir
def diffoscope(origin_name):
file_origin = NamedTemporaryFile()
- if get_file(openwrt_url + "/" + origin_name, file_origin.name):
+ if get_file(download_url + "/" + origin_name, file_origin.name):
print("Error downloading {}".format(origin_name))
return
- run_command(
- [
- "diffoscope",
- file_origin.name,
- rebuild_dir + "/" + origin_name,
- "--html",
- target_dir + "/" + origin_name + ".html",
- ],
- ignore_errors=True,
+ diffoscope_compare(
+ file_origin.name,
+ target_dir + "/" + origin_name,
+ results_target_dir + "/" + origin_name + ".html",
)
+
file_origin.close()
+
# return sha256sum of given path
def sha256sum(path):
with open(path, "rb") as hash_file:
@@ -137,186 +156,326 @@ def get_file(url, path=None):
else:
return content.decode("utf-8")
+
# parse the origin sha256sums file from openwrt
def parse_origin_sha256sums():
- sha256sums = get_file(openwrt_url + "/sha256sums")
+ sha256sums = get_file(download_url + "/sha256sums")
return re.findall(r"(.+?) \*(.+?)\n", sha256sums)
-# not required for now
-# def exchange_signature(origin_path, rebuild_path):
-# file_sig = NamedTemporaryFile()
-# # extract original signatur in temporary file
-# run_command(
-# "./staging_dir/host/bin/fwtool -s {} {}".format(file_sig.name, origin_path),
-# temporary_dir,
-# )
-# # remove random signatur of rebuild
-# run_command(
-# "./staging_dir/host/bin/fwtool -t -s /dev/null {}".format(rebuild_path),
-# temporary_dir,
-# )
-# # add original signature to rebuild file
-# run_command(
-# "./staging_dir/host/bin/fwtool -S {} {}".format(file_sig.name, rebuild_path),
-# temporary_dir,
-# )
-# file_sig.close()
-
-
-# initial clone of openwrt.git
-run_command(["git", "clone", openwrt_git, temporary_dir])
-
-# download buildinfo files
-get_file(openwrt_url + "/config.buildinfo", temporary_dir + "/.config")
-with open(temporary_dir + "/.config", "a") as config_file:
- # extra options used by the buildbot
- config_file.writelines(
+def exchange_signature(origin_name):
+ file_origin = NamedTemporaryFile()
+ rebuild_path = target_dir + "/" + origin_name
+ sig_path = rebuild_path + ".sig"
+
+ if get_file(download_url + "/" + origin_name, file_origin.name):
+ print("Error downloading {}".format(origin_name))
+ file_origin.close()
+ return
+ # extract original signatur in temporary file
+ run_command(
[
- "CONFIG_CLEAN_IPKG=y\n",
- "CONFIG_TARGET_ROOTFS_TARGZ=y\n",
- "CONFIG_CLEAN_IPKG=y\n",
- 'CONFIG_KERNEL_BUILD_USER="builder"\n',
- 'CONFIG_KERNEL_BUILD_DOMAIN="buildhost"\n',
- ]
+ rebuild_dir + "/staging_dir/host/bin/fwtool",
+ "-s",
+ sig_path,
+ file_origin.name,
+ ],
+ ignore_errors=True,
)
+ if os.path.getsize(sig_path) > 0:
+ # remove random signatur of rebuild
+ run_command(
+ [
+ rebuild_dir + "/staging_dir/host/bin/fwtool",
+ "-t",
+ "-s",
+ "/dev/null",
+ rebuild_path,
+ ],
+ ignore_errors=True,
+ )
+ # add original signature to rebuild file
+ run_command(
+ [
+ rebuild_dir + "/staging_dir/host/bin/fwtool",
+ "-S",
+ sig_path,
+ rebuild_path,
+ ],
+ ignore_errors=True,
+ )
+ print("Attached origin signature to {}".format(rebuild_path))
+ file_origin.close()
+
+
+def clone_git():
+ # initial clone of openwrt.git
+ run_command(["git", "clone", openwrt_git, rebuild_dir])
+
+
+def setup_buildinfo():
+ # download buildinfo files
+ get_file(download_url + "/config.buildinfo", rebuild_dir + "/.config")
+ with open(rebuild_dir + "/.config", "a") as config_file:
+ # extra options used by the buildbot
+ config_file.writelines(
+ [
+ "CONFIG_IB=n\n",
+ "CONFIG_SDK=n\n",
+ 'CONFIG_KERNEL_BUILD_USER="builder"\n',
+ 'CONFIG_KERNEL_BUILD_DOMAIN="buildhost"\n',
+ ]
+ )
+
+ # download origin buildinfo file containing the feeds
+ get_file(download_url + "/feeds.buildinfo", rebuild_dir + "/feeds.conf")
-# insecure private key to build the images
-with open(temporary_dir + "/key-build", "w") as key_build_file:
- key_build_file.write(
- "Local build key\nRWRCSwAAAAB12EzgExgKPrR4LMduadFAw1Z8teYQAbg/EgKaN9SUNrgteVb81/bjFcvfnKF7jS1WU8cDdT2VjWE4Cp4cxoxJNrZoBnlXI+ISUeHMbUaFmOzzBR7B9u/LhX3KAmLsrPc="
+ # get current commit_string to show in website banner
+ context["commit_string"] = get_file(download_url + "/version.buildinfo")[:-1]
+ # ... and parse the actual commit to checkout
+ context["commit"] = context["commit_string"].split("-")[1]
+
+
+def setup_key():
+ # OpenWrt signs the release with a signing key, but generate the signing key if not
+ # present. To have a reproducible release we need to take care of signing keys.
+
+ # OpenWrt will also put the key-build.pub into the resulting image (pkg: base-files)!
+ # At the end of the build it will use the key-build to sign the Packages repo list.
+ # Use a workaround this problem:
+
+ # key-build.pub contains the pubkey of OpenWrt buildbot
+ # key-build contains our build key
+
+ # Meaning only signed files will be different but not the images.
+ # Packages.sig is unreproducible.
+
+ # here is our random signing key
+ # chosen by fair dice roll.
+ # guaranteed to be random.
+
+ # insecure pseudo private key to build the images
+ with open(rebuild_dir + "/key-build", "w") as key_build_file:
+ key_build_file.write(
+ "Local build key\nRWRCSwAAAAB12EzgExgKPrR4LMduadFAw1Z8teYQAbg/EgKaN9SUNrgteVb81/bjFcvfnKF7jS1WU8cDdT2VjWE4Cp4cxoxJNrZoBnlXI+ISUeHMbUaFmOzzBR7B9u/LhX3KAmLsrPc="
+ )
+
+ # spoof the official OpenWrt public key to prevent adding another key in the binary
+ with open(rebuild_dir + "/key-build.pub", "w") as key_build_pub_file:
+ key_build_pub_file.write(
+ "OpenWrt snapshot release signature\nRWS1BD5w+adc3j2Hqg9+b66CvLR7NlHbsj7wjNVj0XGt/othDgIAOJS+"
+ )
+
+ # buildbots set mode 600 for private and public key which is hereby imitated
+ os.chmod(rebuild_dir + "/key-build.pub", 0o600)
+
+
+def checkout_commit():
+ # checkout the desired commit
+ run_command(["git", "checkout", "-f", context["commit"]], rebuild_dir)
+
+
+def get_commit_log():
+ # show the last 20 commits to have an idea what was changed lately
+ context["git_log_oneline"] = run_command(
+ ["git", "log", "--oneline", "-n", "20"], rebuild_dir
)
-# spoof the official openwrt public key to prevent adding another key in the binary
-with open(temporary_dir + "/key-build.pub", "w") as key_build_pub_file:
- key_build_pub_file.write(
- "OpenWrt snapshot release signature\nRWS1BD5w+adc3j2Hqg9+b66CvLR7NlHbsj7wjNVj0XGt/othDgIAOJS+"
+
+def update_feeds():
+ # do as the buildbots do
+ run_command(["./scripts/feeds", "update"], rebuild_dir)
+ run_command(["./scripts/feeds", "install", "-a"], rebuild_dir)
+ make("defconfig")
+
+
+def add_kmods_feed():
+ target_staging_dir = run_command(
+ ["make", "--no-print-directory", "val.STAGING_DIR_ROOT"], rebuild_dir
+ )
+ os.makedirs(rebuild_dir + "/files/etc/opkg/", exist_ok=True)
+ context["kernelversion"] = "-".join(
+ run_command(
+ [
+ "make",
+ "--no-print-directory",
+ "-C",
+ "target/linux/",
+ "val.LINUX_VERSION",
+ "val.LINUX_RELEASE",
+ "val.LINUX_VERMAGIC",
+ ],
+ rebuild_dir,
+ env={"TOPDIR": "../..", "INCLUDE_DIR": "../../include"},
+ ).splitlines()
+ )
+ with open(
+ target_staging_dir[0:-1] + "/etc/opkg/distfeeds.conf", "r"
+ ) as distfeeds_orig_file:
+ distfeeds_orig = distfeeds_orig_file.read()
+
+ distfeeds_kmods = re.sub(
+ r"^(src/gz .*)_core (.*)/packages\n",
+ r"\1_core \2/packages\n\1_kmods \2/kmods/{}\n".format(context["kernelversion"]),
+ distfeeds_orig,
+ re.MULTILINE,
)
-# this specific key is odly chmodded to 600
-os.chmod(temporary_dir + "/key-build.pub", 0o600)
-# download origin buildinfo file containing the feeds
-get_file(openwrt_url + "/feeds.buildinfo", temporary_dir + "/feeds.conf")
+ print(distfeeds_kmods)
-# get current commit_string to show in website banner
-context["commit_string"] = get_file(openwrt_url + "/version.buildinfo")[:-1]
-# ... and parse the actual commit to checkout
-commit = context["commit_string"].split("-")[1]
+ with open(rebuild_dir + "/files/etc/opkg/distfeeds.conf", "w") as distfeeds_file:
+ distfeeds_file.write(distfeeds_kmods)
-# checkout the desired commit
-run_command(["git", "checkout", "-f", commit, temporary_dir])
-# show the last 20 commit to have an idea what was changed lately
-context["git_log_oneline"] = run_command(
- ["git", "log", "--oneline", "-n", "20"], temporary_dir
-)
+def make(*cmd):
+ run_command(
+ [
+ "make",
+ "IGNORE_ERRORS='n m'",
+ "BUILD_LOG=1",
+ "BUILD_LOG_DIR={}/logs".format(results_dir),
+ "-j{}".format(cpu_count() + 1),
+ ]
+ + list(cmd),
+ rebuild_dir,
+ )
-# do as the buildbots do
-run_command(["./scripts/feeds", "update"], temporary_dir)
-run_command(["./scripts/feeds", "install", "-a"], temporary_dir)
-run_command(["make", "defconfig"], temporary_dir)
-# actually build everything
-run_command(
- ["make", "IGNORE_ERRORS='n m y'", "BUILD_LOG=1", "-j", str(cpu_count() + 1)],
- temporary_dir,
-)
-# flush the current website dir of target
-shutil.rmtree(target_dir, ignore_errors=True)
+def reset_target_output():
+ # flush the current website dir of target
+ shutil.rmtree(results_target_dir, ignore_errors=True)
-# and recreate it here
-os.makedirs(target_dir + "/packages", exist_ok=True)
+ # and recreate it here
+ os.makedirs(results_target_dir + "/packages", exist_ok=True)
-# iterate over all sums in origin sha256sums and check rebuild files
-for origin in parse_origin_sha256sums():
- origin_sum, origin_name = origin
- # except the meta files defined above
- if meta_files.match(origin_name):
- print("Skipping meta file {}".format(origin_name))
- continue
- rebuild_path = temporary_dir + "/bin/targets/" + target + "/" + origin_name
- # report missing files
- if not os.path.exists(rebuild_path):
- context["missing"].append({"name": origin_name})
- else:
- rebuild_info = {
- "name": origin_name,
- "size": os.path.getsize(rebuild_path),
- "sha256sum": sha256sum(rebuild_path),
- "repro": False,
- }
-
- # files ending with ipk are considered packages
- if origin_name.endswith(".ipk"):
- if rebuild_info["sha256sum"] == origin_sum:
- rebuild_info["repro"] = True
- context["packages_repro"] += 1
- context["packages"].append(rebuild_info)
+def compare_checksums():
+ # iterate over all sums in origin sha256sums and check rebuild files
+ for origin in parse_origin_sha256sums():
+ origin_sum, origin_name = origin
+ # except the meta files defined above
+ if meta_files.match(origin_name):
+ print("Skipping meta file {}".format(origin_name))
+ continue
+
+ rebuild_path = target_dir + "/" + origin_name
+ # report missing files
+ if not os.path.exists(rebuild_path):
+ context["missing"].append({"name": origin_name})
else:
- #everything else should be images
- if rebuild_info["sha256sum"] == origin_sum:
- rebuild_info["repro"] = True
- context["images_repro"] += 1
- context["images"].append(rebuild_info)
-
-# calculate how many images are reproducible
-context["images_total"] = len(context["images"])
-if context["images_total"]:
- context["images_repro_percent"] = round(
- context["images_repro"] / context["images_total"] * 100.0, 2
+ print("checking {}".format(origin_name))
+ rebuild_info = {
+ "name": origin_name,
+ "size": os.path.getsize(rebuild_path),
+ "repro": False,
+ }
+
+ # files ending with ipk are considered packages
+ if origin_name.endswith(".ipk"):
+ rebuild_info["sha256sum"] = sha256sum(rebuild_path)
+ if rebuild_info["sha256sum"] == origin_sum:
+ rebuild_info["repro"] = True
+ context["packages_repro"] += 1
+ context["packages"].append(rebuild_info)
+ else:
+ # everything else should be images
+ exchange_signature(origin_name)
+ rebuild_info["sha256sum"] = sha256sum(rebuild_path)
+ if rebuild_info["sha256sum"] == origin_sum:
+ rebuild_info["repro"] = True
+ context["images_repro"] += 1
+ context["images"].append(rebuild_info)
+
+
+def calculate_repro_stats():
+ # calculate how many images are reproducible
+ context["images_total"] = len(context["images"])
+ if context["images_total"]:
+ context["images_repro_percent"] = round(
+ context["images_repro"] / context["images_total"] * 100.0, 2
+ )
+
+ # calculate how many packages are reproducible
+ context["packages_total"] = len(context["packages"])
+ if context["packages_total"]:
+ context["packages_repro_percent"] = round(
+ context["packages_repro"] / context["packages_total"] * 100.0, 2
+ )
+
+ print(
+ "total_repro {}%".format(
+ (context["packages_repro_percent"] + context["images_repro_percent"]) / 2
+ )
)
-# calculate how many packages are reproducible
-context["packages_total"] = len(context["packages"])
-if context["packages_total"]:
- context["packages_repro_percent"] = round(
- context["packages_repro"] / context["packages_total"] * 100.0, 2
+
+def render_website():
+ # now render the website
+ renderer = pystache.Renderer()
+ mustache_header = renderer.load_template(template_dir + "/header")
+ mustache_footer = renderer.load_template(template_dir + "/footer")
+ mustache_target = renderer.load_template(template_dir + "/target")
+ mustache_index = renderer.load_template(template_dir + "/index")
+
+ index_html = renderer.render(mustache_header, context)
+ index_html += renderer.render(mustache_index, context)
+ index_html += renderer.render(mustache_footer, context)
+
+ target_html = renderer.render(mustache_header, context)
+ target_html += renderer.render(mustache_target, context)
+ target_html += renderer.render(mustache_footer, context)
+
+ # and store the files
+ with open(results_dir + "/index.html", "w") as index_file:
+ index_file.write(index_html)
+
+ with open(results_target_dir + "/index.html", "w") as target_file:
+ target_file.write(target_html)
+
+ # store context for future review
+ with open(results_target_dir + "/context.json", "w") as context_file:
+ json.dump(context, context_file, indent=" ")
+
+
+def diffoscope_multithread():
+ # run diffoscope over non reproducible files in all available threads
+ pool = Pool(cpu_count() + 1)
+ pool.map(
+ diffoscope,
+ map(
+ lambda x: x["name"],
+ filter(lambda x: not x["repro"], context["images"] + context["packages"]),
+ ),
)
-# now render the website
-renderer = pystache.Renderer()
-mustache_header = renderer.load_template(template_dir + "/header")
-mustache_footer = renderer.load_template(template_dir + "/footer")
-mustache_target = renderer.load_template(template_dir + "/target")
-mustache_index = renderer.load_template(template_dir + "/index")
-
-index_html = renderer.render(mustache_header, context)
-index_html += renderer.render(mustache_index, context)
-index_html += renderer.render(mustache_footer, context)
-
-target_html = renderer.render(mustache_header, context)
-target_html += renderer.render(mustache_target, context)
-target_html += renderer.render(mustache_footer, context)
-
-# and store the files
-with open(output_dir + "/index.html", "w") as index_file:
- index_file.write(index_html)
-
-with open(target_dir + "/index.html", "w") as target_file:
- target_file.write(target_html)
-
-# get the origin manifest
-origin_manifest = get_file(openwrt_url + "/packages/Packages.manifest")
-
-# and store it in the databse
-ropp = importlib.import_module("reproducible_openwrt_package_parser")
-with open(rebuild_dir + "/packages/Packages.manifest") as rebuild_manifest:
- result = ropp.show_list_difference(origin_manifest, rebuild_manifest.readlines())
- ropp.insert_into_db(result, "{}-rebuild".format(version))
-
-# run diffoscope over non reproducible files in all available threads
-pool = Pool(cpu_count() + 1)
-pool.map(
- diffoscope,
- map(
- lambda x: x["name"],
- filter(lambda x: not x["repro"], context["images"] + context["packages"]),
- ),
-)
-# debug option to keep build dir
-if not os.environ.get("KEEP_BUILD_DIR"):
- print("removing build dir")
- shutil.rmtree(temporary_dir)
-print("all done")
+def store_results():
+ with open(target_dir + "/packages/Packages.manifest") as rebuild_manifest:
+ origin_manifest = get_file(download_url + "/packages/Packages.manifest")
+ result = show_list_difference(origin_manifest, rebuild_manifest.readlines())
+ insert_into_db(result, "{}-rebuild".format(version))
+
+
+if __name__ == "__main__":
+ clone_git()
+ setup_buildinfo()
+ checkout_commit()
+ get_commit_log()
+ setup_key()
+ update_feeds()
+ make("tools/tar/compile")
+ make("tools/install")
+ make("toolchain/install")
+ make("target/compile")
+ make("package/compile")
+ make("package/install")
+ make("package/index", "CONFIG_SIGNED_PACKAGES=")
+ if version == "SNAPSHOT":
+ add_kmods_feed()
+ make("target/install")
+ reset_target_output()
+ compare_checksums()
+ calculate_repro_stats()
+ render_website()
+ store_results()
+ diffoscope_multithread()
=====================================
mustache-templates/openwrt/header.mustache
=====================================
@@ -4,8 +4,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
- <title>Reproducible OpenWrt ?</title>
- <link rel='stylesheet' id='kamikaze-style-css' href='cascade.css?ver=4.0' type='text/css' media='all'>
+ <title>Reproducible OpenWrt?</title>
</head>
<style type="text/css">
html,
@@ -115,7 +114,8 @@
<body>
<div id="content">
- <pre>
+ <a href="{{ root }}" style="text-decoration: none;">
+ <pre>
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
@@ -124,7 +124,8 @@
-----------------------------------------------------
OpenWrt {{ version }}, {{ commit_string }}
-----------------------------------------------------
- </pre>
+ </pre>
+ </a>
</div>
<div id="main-content">
<h1>OpenWrt - <em>reproducible</em> wireless freedom!</h1>
=====================================
mustache-templates/openwrt/index.mustache
=====================================
@@ -26,7 +26,7 @@
<p>
<ul>
{{ #targets }}
- <li><a href="{{ version }}/{{ name}}">{{ version }} - {{ name }}</a></li>
+ <li><a href="{{ root }}/{{ version }}/{{ name}}">{{ version }} - {{ name }}</a></li>
{{ /targets }}
</ul>
</p>
=====================================
mustache-templates/openwrt/target.mustache
=====================================
@@ -16,10 +16,10 @@
{{ #images }}
<tr>
{{ #repro }}
- <td><img src="/userContent/reproducible/static/weather-clear.png" alt="reproducible icon" /> {{ name }} ({{ sha256sum }}, {{ size }}K) is reproducible.</td>
+ <td><img src="{{ root }}/static/weather-clear.png" alt="reproducible icon" /> {{ name }} ({{ sha256sum }}, {{ size }}K) is reproducible.</td>
{{ /repro }}
{{ ^repro }}
- <td><a href="/{{ version }}/{{ target }}/{{ name }}.html"><img src="/userContent/reproducible/static/weather-showers-scattered.png" alt="unreproducible icon"> {{ name }}</a> ({{ size }}K) is unreproducible.</td>
+ <td><a href="{{ root }}/{{ version }}/{{ target }}/{{ name }}.html"><img src="{{ root }}/static/weather-showers-scattered.png" alt="unreproducible icon"> {{ name }}</a> ({{ size }}K) is unreproducible.</td>
{{ /repro }}
</tr>
{{ /images }}
@@ -31,7 +31,7 @@
{{ #packages }}
{{ ^repro }}
<tr>
- <td><a href="/{{ version }}/{{ target }}/{{ name }}.html"><img src="/userContent/reproducible/static/weather-showers-scattered.png" alt="unreproducible icon"> {{ name }}</a> ({{ size }}K) is unreproducible.</td>
+ <td><a href="{{ root }}/{{ version }}/{{ target }}/{{ name }}.html"><img src="{{ root }}/static/weather-showers-scattered.png" alt="unreproducible icon"> {{ name }}</a> ({{ size }}K) is unreproducible.</td>
</tr>
{{ /repro }}
{{ /packages }}
@@ -43,7 +43,7 @@
{{ #packages }}
{{ #repro }}
<tr>
- <td><img src="/userContent/reproducible/static/weather-clear.png" alt="reproducible icon" /> {{ name }} ({{ sha256sum }}, {{ size }}K) is reproducible.</td>
+ <td><img src="{{ root }}/static/weather-clear.png" alt="reproducible icon" /> {{ name }} ({{ sha256sum }}, {{ size }}K) is reproducible.</td>
</tr>
{{ /repro }}
{{ /packages }}
View it on GitLab: https://salsa.debian.org/qa/jenkins.debian.net/compare/d88424a92570f0d338ac343aeae1c45aa0edda22...f73cf72fe2cffb5aa2037efb71ab0328a37c261f
--
View it on GitLab: https://salsa.debian.org/qa/jenkins.debian.net/compare/d88424a92570f0d338ac343aeae1c45aa0edda22...f73cf72fe2cffb5aa2037efb71ab0328a37c261f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/qa-jenkins-scm/attachments/20191007/a95cb450/attachment-0001.html>
More information about the Qa-jenkins-scm
mailing list