import argparse import gzip import platform import secrets import subprocess import sys from pathlib import Path BUILD_CONTEXT = "dangerzone/" IMAGE_NAME = "dangerzone.rocks/dangerzone" if platform.system() in ["Darwin", "Windows"]: CONTAINER_RUNTIME = "docker" elif platform.system() == "Linux": CONTAINER_RUNTIME = "podman" def str2bool(v): if isinstance(v, bool): return v if v.lower() in ("yes", "true", "t", "y", "1"): return True elif v.lower() in ("no", "false", "f", "n", "0"): return False else: raise argparse.ArgumentTypeError("Boolean value expected.") def determine_git_tag(): # Designate a unique tag for this image, depending on the Git commit it was created # from: # 1. If created from a Git tag (e.g., 0.8.0), the image tag will be `0.8.0`. # 2. If created from a commit, it will be something like `0.8.0-31-g6bdaa7a`. # 3. If the contents of the Git repo are dirty, we will append a unique identifier # for this run, something like `0.8.0-31-g6bdaa7a-fdcb` or `0.8.0-fdcb`. dirty_ident = secrets.token_hex(2) return ( subprocess.check_output( [ "git", "describe", "--long", "--first-parent", f"--dirty=-{dirty_ident}", ], ) .decode() .strip()[1:] # remove the "v" prefix of the tag. ) def determine_debian_archive_date(): """Get the date of the Debian archive from Dockerfile.env.""" for env in Path("Dockerfile.env").read_text().split("\n"): if env.startswith("DEBIAN_ARCHIVE_DATE"): return env.split("=")[1] raise Exception( "Could not find 'DEBIAN_ARCHIVE_DATE' build argument in Dockerfile.env" ) def main(): parser = argparse.ArgumentParser() parser.add_argument( "--runtime", choices=["docker", "podman"], default=CONTAINER_RUNTIME, help=f"The container runtime for building the image (default: {CONTAINER_RUNTIME})", ) parser.add_argument( "--platform", default=None, help=f"The platform for building the image (default: current platform)", ) parser.add_argument( "--output", "-o", default=str(Path("share") / "container.tar"), help="Path to store the container image", ) # parser.add_argument( # "--compress-level", # type=int, # choices=range(0, 10), # default=9, # help="The Gzip compression level, from 0 (lowest) to 9 (highest, default)", # ) parser.add_argument( "--use-cache", type=str2bool, nargs="?", default=True, const=True, help="Use the builder's cache to speed up the builds", ) parser.add_argument( "--tag", default=None, help="Provide a custom tag for the image (for development only)", ) parser.add_argument( "--debian-archive-date", "-d", default=determine_debian_archive_date(), help="Use a specific Debian snapshot archive, by its date (default %(default)s)", ) parser.add_argument( "--dry", default=False, action="store_true", help="Do not run any commands, just print what would happen", ) args = parser.parse_args() tag = args.tag or f"{args.debian_archive_date}-{determine_git_tag()}" image_name_tagged = f"{IMAGE_NAME}:{tag}" print(f"Will tag the container image as '{image_name_tagged}'") image_id_path = Path("share") / "image-id.txt" if not args.dry: with open(image_id_path, "w") as f: f.write(tag) # Build the container image, and tag it with the calculated tag print("Building container image") cache_args = [] if args.use_cache else ["--no-cache"] platform_args = [] if not args.platform else ["--platform", args.platform] rootless_args = [] if args.runtime == "docker" else ["--rootless"] rootless_args = [] dry_args = [] if not args.dry else ["--dry"] subprocess.run( [ "./dev_scripts/repro-build", "build", "--runtime", args.runtime, "--build-arg", f"DEBIAN_ARCHIVE_DATE={args.debian_archive_date}", "--datetime", args.debian_archive_date, *dry_args, *cache_args, *platform_args, *rootless_args, "--tag", image_name_tagged, "--output", args.output, "-f", "Dockerfile", BUILD_CONTEXT, ], check=True, ) if __name__ == "__main__": sys.exit(main())