sandcastle-ng

Scripts for the deployment of Sandcastle (GNU Taler)
Log | Files | Refs | README

sandcastle-build-generic (4548B)


      1 #!/usr/bin/env python3
      2 # This file is in the public domain.
      3 # Helper script to build the latest DEB packages in the container.
      4 
      5 # Supported tag syntax variants:
      6 # v$maj.$min$.$patch => release version
      7 # v$maj.$min$.$patch-dev.$n => dev version
      8 # deb-v$maj.$min$.$patch-$revision => release version with debian revision
      9 # Debian revisions of dev versions are *not* supported
     10 
     11 import glob
     12 import os
     13 import shlex
     14 import shutil
     15 import subprocess
     16 import sys
     17 from email.utils import formatdate
     18 from logging import log, warning
     19 
     20 
     21 def run_cmd(cmd, shell=False, cwd=None, env=None):
     22     """Helper to run commands and exit on failure (mimicking set -e)."""
     23     # If specific env vars are passed, update the current env, otherwise use current
     24     command_env = os.environ.copy()
     25     if env:
     26         command_env.update(env)
     27 
     28     # Flush stdout so logs appear in order
     29     sys.stdout.flush()
     30 
     31     subprocess.check_call(cmd, shell=shell, cwd=cwd, env=command_env)
     32 
     33 
     34 def get_tag_debver(tag):
     35     """Get a debian version string from a git tag"""
     36     if tag.startswith("v"):
     37         devsuff = "-dev."
     38         d = tag.find(devsuff)
     39         if d < 0:
     40             return tag[1:]
     41         else:
     42             return tag[1:d] + "~dev" + tag[d + len(devsuff)]
     43     if tag.startswith("deb-v"):
     44         tag = tag[5:]
     45         if "-" in tag:
     46             a, b = tag.split("-")
     47             return a + ":" + b
     48         return tag
     49     warning(f"unexpected tag format: {tag}")
     50     return "100.0.0"  # Version big enough to work every time
     51 
     52 
     53 def main():
     54     if "LD_LIBRARY_PATH" in os.environ:
     55         del os.environ["LD_LIBRARY_PATH"]
     56 
     57     # Arguments
     58     if len(sys.argv) < 2:
     59         print(f"Usage: {sys.argv[0]} <PACKAGE>", file=sys.stderr)
     60         sys.exit(1)
     61 
     62     package = sys.argv[1]
     63 
     64     # Path of the debian/ folder in the repository
     65     DEBIANPATH = ""
     66     debpath_file = f"/buildconfig/{package}.debpath"
     67     if os.path.exists(debpath_file):
     68         with open(debpath_file, "r") as f:
     69             DEBIANPATH = f.read().strip()
     70 
     71     print(f"Building {package} with generic build logic", file=sys.stderr)
     72 
     73     with open(f"/buildconfig/{package}.tag", "r") as f:
     74         tag = f.read().strip()
     75 
     76     outdir = f"/packages/{package}/"
     77 
     78     os.makedirs(outdir, exist_ok=True)
     79 
     80     os.chdir("/packages/")
     81 
     82     # Using shell=True here to easily handle the pipe logic
     83     run_cmd("dpkg-scanpackages . | xz - > /packages/Packages.xz", shell=True)
     84 
     85     with open("/etc/apt/sources.list.d/taler-packaging-local.list", "w") as f:
     86         f.write("deb [trusted=yes] file:/packages ./\n")
     87 
     88     run_cmd(["apt-get", "update"])
     89 
     90     # Prepare Build Directory
     91     if not os.path.exists("/build"):
     92         os.makedirs("/build")
     93     os.chdir("/build")
     94 
     95     with open(f"/buildconfig/{package}.giturl", "r") as f:
     96         GITURL = f.read().strip()
     97 
     98     run_cmd(["git", "config", "--global", "advice.detachedHead", "false"])
     99     run_cmd(["git", "clone", "--depth=1", f"--branch={tag}", GITURL, package])
    100 
    101     build_pkg_path = os.path.join("/build", package, DEBIANPATH)
    102     os.chdir(build_pkg_path)
    103 
    104     deb_version = get_tag_debver(tag)
    105 
    106     # Bootstrap and Install Deps
    107     os.chdir(os.path.join("/build", package))
    108     run_cmd(["./bootstrap"])
    109 
    110     os.chdir(build_pkg_path)
    111 
    112     # Install build-time dependencies
    113     tool_cmd = "apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes"
    114     run_cmd(["mk-build-deps", "--install", f"--tool={tool_cmd}", "debian/control"])
    115 
    116     # Sparse checkout hint
    117     with open(".version", "w") as f:
    118         f.write(f"{deb_version}\n")
    119 
    120     # Configure Environment for Build
    121     deb_dbg_repo = "debian/.debhelper/"
    122     os.environ["DEB_DBG_SYMBOLS_REPO"] = deb_dbg_repo
    123     os.makedirs(deb_dbg_repo, exist_ok=True)
    124 
    125     open(os.path.join(deb_dbg_repo, "debian-symbols-pool"), "a").close()
    126 
    127     os.environ["DEB_BUILD_MAINT_OPTIONS"] = "debug"
    128 
    129     debian_date = formatdate(localtime=True)
    130 
    131     changelog = f"""\
    132 {package} ({deb_version}) unstable; urgency=low
    133 
    134   * Release {deb_version} (for sandcastle-ng).
    135 
    136  -- Taler Packaging Team <deb@taler.net>  {debian_date}
    137 """
    138 
    139     with open("debian/changelog", "w") as f:
    140         f.write(changelog)
    141 
    142     # Build Package
    143     run_cmd(["dpkg-buildpackage", "-rfakeroot", "-b", "-uc", "-us"])
    144 
    145     # Copy artifacts
    146     # Globs for ../*.deb and ../*.ddeb relative to current dir
    147     deb_files = glob.glob("../*.deb")
    148     ddeb_files = glob.glob("../*.ddeb")
    149 
    150     for f in deb_files:
    151         shutil.copy(f, outdir)
    152 
    153     for f in ddeb_files:
    154         shutil.copy(f, outdir)
    155 
    156 
    157 if __name__ == "__main__":
    158     main()