diff options
author | Rob Austein <sra@arrcus.com> | 2018-06-30 23:38:42 -0400 |
---|---|---|
committer | Rob Austein <sra@arrcus.com> | 2018-06-30 23:38:42 -0400 |
commit | db0e9e728e166ba5f84659d335709f2f9f25eeb2 (patch) | |
tree | 41401e0e6b33e67740e6b7374dd45bb01d084236 | |
parent | e4703afd50a586ca3e1ba5975e4d01c33c1d7efd (diff) |
Working.
Well, maybe. arrcus-sw runs to completion, anyway, good start.
-rwxr-xr-x | baiji | 114 |
1 files changed, 74 insertions, 40 deletions
@@ -54,8 +54,12 @@ class Docker(subprocess.Popen): return self def __exit__(self, *oops): + if any(oops): + return + if self.stdin: + self.stdin.close() status = self.wait() - if status and all(o is None for o in oops): + if status: raise self.DockerError() # Filter which acts like fakeroot for tarfile.TarFile.add() @@ -71,7 +75,7 @@ def fakeroot_filter(info): @cmd(arg("--dist", default = "jessie", help = "distribution for base docker image"), arg("--tag", default = "baiji:jessie", help = "tag to use for constructed base docker image"), ) -def create_base(args): +def create(args): """ Construct a base Docker image. @@ -82,22 +86,22 @@ def create_base(args): with tempdir() as dn: subprocess.check_call(("fakeroot", "/usr/sbin/debootstrap", "--foreign", "--variant=buildd", args.dist, dn)) with Docker("import", "-", args.tag, stdin = subprocess.PIPE) as docker: - tar = tarfile.open(mode = "w|", fileobj = docker.stdin) - tar.add(dn, ".", filter = fakeroot_filter) - tar.close() - docker.stdin.close() + with tarfile.open(mode = "w|", fileobj = docker.stdin) as tar: + tar.add(dn, ".", filter = fakeroot_filter) with Docker("build", "-t", args.tag, "-", stdin = subprocess.PIPE) as docker: docker.communicate(textwrap.dedent('''\ FROM {args.tag} RUN sed -i '/mount -t proc /d; /mount -t sysfs /d' /debootstrap/functions && /debootstrap/debootstrap --second-stage RUN apt-get update && apt-get install -y --no-install-recommends build-essential fakeroot git apt-utils + RUN useradd -U -m -d /build baiji + WORKDIR /build '''.format(args = args))) @cmd(arg("--tag", default = "baiji:jessie", help = "tag of base docker image to update"), ) -def update_base(args): +def update(args): """ Update a base Docker image. """ @@ -109,9 +113,11 @@ def update_base(args): '''.format(args = args))) -@cmd(arg("--tag", default = "baiji:jessie", help = "tag of base docker image to use"), - arg("--dsc", required = True, type = argparse.FileType("r"), help = ".dsc file to build"), - arg("--local-package", default = [], nargs = "+", help = "local packages to make available to build"), +@cmd(arg("--tag", default = "baiji:jessie", help = "tag of base docker image to use"), + arg("--dsc", required = True, type = argparse.FileType("r"), help = ".dsc file to build"), + arg("--local-package", default = [], nargs = "+", help = "local packages to make available to build"), + arg("--reuse-image", action = "store_true", help = "don't rebuild Docker image"), + arg("--just-image", action = "store_true", help = "don't build, just generate Docker image"), ) def build(args): """ @@ -132,38 +138,66 @@ def build(args): for tag in ("Version", "Maintainer", "Homepage"): dummy[tag] = dsc[tag] - source_files = [os.path.join(os.path.dirname(args.dsc.name), f["name"]) for f in dsc["Files"]] - build_image = "baiji/build/{}:{}".format(dsc["Source"], dsc["Version"]) - with tempdir() as dn: - equivs = subprocess.Popen(("equivs-build", "/dev/stdin"), stdin = subprocess.PIPE, stdout = subprocess.PIPE, cwd = dn) - equivs.communicate(str(dummy)) - if equivs.wait(): - sys.exit("Couldn't generate dummy dependency package") - - dockerfile_fn = os.path.join(dn, "Dockerfile") - with open(dockerfile_fn, "w") as f: - f.write(textwrap.dedent('''\ - FROM {args.tag} - COPY micro-apt /micro-apt/ - RUN cd /micro-apt && apt-ftparchive packages . > Packages - RUN echo 'deb [trusted=yes] file:///micro-apt ./' > /etc/apt/sources.list.d/micro-apt.list - RUN apt-get update && apt-get install -y --no-install-recommends {dummy_name} && apt-get clean - '''.format(args = args, dummy_name = dummy_name))) - - with open(dockerfile_fn) as f: - sys.stderr.write("# Dockerfile:\n" + f.read() + "\n") - - with Docker("build", "-t", build_image, "-", stdin = subprocess.PIPE) as docker: - tar = tarfile.open(mode = "w|", fileobj = docker.stdin) - tar.add(dockerfile_fn, "Dockerfile", filter = fakeroot_filter) - for pkg in [os.path.join(dn, dummy_fn)] + args.local_package: - tar.add(pkg, os.path.join("micro-apt", os.path.basename(pkg)), filter = fakeroot_filter) - tar.close() - docker.stdin.close() - - # Continue here with actual build once we have environment set up + # Whether and when to rebuild the per-package docker image needs more thought. + # For the moment, just manual control, for testing. + + if not args.reuse_image: + + with tempdir() as dn: + equivs = subprocess.Popen(("equivs-build", "/dev/stdin"), stdin = subprocess.PIPE, stdout = subprocess.PIPE, cwd = dn) + equivs.communicate(str(dummy)) + if equivs.wait(): + sys.exit("Couldn't generate dummy dependency package") + + with open(os.path.join(dn, "Dockerfile"), "w") as f: + f.write(textwrap.dedent('''\ + FROM {args.tag} + COPY build.sh /baiji/ + COPY micro-apt /micro-apt/ + RUN cd /micro-apt && apt-ftparchive packages . > Packages + RUN echo 'deb [trusted=yes] file:///micro-apt ./' > /etc/apt/sources.list.d/micro-apt.list + RUN apt-get update && apt-get install -y --no-install-recommends {dummy_name} && apt-get clean + USER baiji + '''.format(args = args, dummy_name = dummy_name))) + + with open(os.path.join(dn, "build.sh"), "w") as f: + f.write(textwrap.dedent('''\ + #!/bin/bash - + set -eo pipefail + arch=`dpkg-architecture -qDEB_BUILD_ARCH` + dpkg-source -x /source/{source}_{version}.dsc + cd {source}-{version} + dpkg-buildpackage -b -uc -us 2>&1 | tee ../{source}_{version}_$arch.build + cd .. + rm -rf {source}-{version} + '''.format(source = dsc["Source"], version = dsc["Version"]))) + + with Docker("build", "-t", build_image, "-", stdin = subprocess.PIPE) as docker: + with tarfile.open(mode = "w|", fileobj = docker.stdin) as tar: + for fn in ("Dockerfile", "build.sh"): + tar.add(os.path.join(dn, fn), fn, filter = fakeroot_filter) + for pkg in [os.path.join(dn, dummy_fn)] + args.local_package: + tar.add(pkg, os.path.join("micro-apt", os.path.basename(pkg)), filter = fakeroot_filter) + + if not args.just_image: + + container_name = "baiji-build-{}".format(dsc["Source"]) + dn = os.path.dirname(args.dsc.name) + + with Docker("run", "-i", "--name", container_name, "--network", "none", + "-v", "{}:/source:ro".format(os.path.abspath(dn)), + build_image, "/bin/bash", "-x", "/baiji/build.sh"): + pass + + with Docker("cp", "{}:/build/.".format(container_name), "-", stdout = subprocess.PIPE) as docker: + with tarfile.open(mode = "r|*", fileobj = docker.stdout) as tar: + for member in tar: + fn = os.path.basename(member.name) + if any(fn.endswith(fn2) for fn2 in (".deb", ".changes")): + with open(os.path.join(dn, fn), "w") as f: + f.write(tar.extractfile(member).read()) # Parse arguments and dispatch to one of the commands above. |