aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@arrcus.com>2018-06-30 23:38:42 -0400
committerRob Austein <sra@arrcus.com>2018-06-30 23:38:42 -0400
commitdb0e9e728e166ba5f84659d335709f2f9f25eeb2 (patch)
tree41401e0e6b33e67740e6b7374dd45bb01d084236
parente4703afd50a586ca3e1ba5975e4d01c33c1d7efd (diff)
Working.
Well, maybe. arrcus-sw runs to completion, anyway, good start.
-rwxr-xr-xbaiji114
1 files changed, 74 insertions, 40 deletions
diff --git a/baiji b/baiji
index 854bd52..bdfda97 100755
--- a/baiji
+++ b/baiji
@@ -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.