launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #21434
[Merge] lp:~cjwatson/launchpad-buildd/extended-snap-status into lp:launchpad-buildd
Colin Watson has proposed merging lp:~cjwatson/launchpad-buildd/extended-snap-status into lp:launchpad-buildd.
Commit message:
Record the branch revision used to build a snap and return it along with other XML-RPC status information (LP: #1679157).
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1679157 in launchpad-buildd: "Collect revision information for snap builds"
https://bugs.launchpad.net/launchpad-buildd/+bug/1679157
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/extended-snap-status/+merge/321689
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad-buildd/extended-snap-status into lp:launchpad-buildd.
=== modified file 'buildsnap'
--- buildsnap 2017-02-10 14:53:12 +0000
+++ buildsnap 2017-04-03 12:38:12 +0000
@@ -9,6 +9,7 @@
__metaclass__ = type
import base64
+import json
from optparse import OptionParser
import os
import subprocess
@@ -50,11 +51,12 @@
# appropriate certificate for your codehosting system.
self.ssl_verify = True
- def chroot(self, args, echo=False):
+ def chroot(self, args, echo=False, get_output=False):
"""Run a command in the chroot.
:param args: the command and arguments to run.
:param echo: if True, print the command before executing it.
+ :param get_output: if True, return the output from the command.
"""
args = set_personality(self.options.arch, args)
if echo:
@@ -62,10 +64,14 @@
"Running in chroot: %s" % ' '.join(
"'%s'" % arg for arg in args))
sys.stdout.flush()
- subprocess.check_call([
- "/usr/bin/sudo", "/usr/sbin/chroot", self.chroot_path] + args)
+ cmd = ["/usr/bin/sudo", "/usr/sbin/chroot", self.chroot_path] + args
+ if get_output:
+ return subprocess.check_output(cmd, universal_newlines=True)
+ else:
+ subprocess.check_call(cmd)
- def run_build_command(self, args, path="/build", env=None, echo=False):
+ def run_build_command(self, args, path="/build", env=None, echo=False,
+ get_output=False):
"""Run a build command in the chroot.
This is unpleasant because we need to run it in /build under sudo
@@ -77,6 +83,7 @@
:param path: the working directory to use in the chroot.
:param env: dictionary of additional environment variables to set.
:param echo: if True, print the command before executing it.
+ :param get_output: if True, return the output from the command.
"""
args = [shell_escape(arg) for arg in args]
path = shell_escape(path)
@@ -89,7 +96,19 @@
"%s=%s" % (key, shell_escape(value))
for key, value in full_env.items()] + args
command = "cd %s && %s" % (path, " ".join(args))
- self.chroot(["/bin/sh", "-c", command], echo=echo)
+ return self.chroot(
+ ["/bin/sh", "-c", command], echo=echo, get_output=get_output)
+
+ def save_status(self, status):
+ """Save a dictionary of status information about this build.
+
+ This will be picked up by the build manager and included in XML-RPC
+ status responses.
+ """
+ status_path = get_build_path(self.options.build_id, "status")
+ with open("%s.tmp" % status_path, "w") as status_file:
+ json.dump(status, status_file)
+ os.rename("%s.tmp" % status_path, status_path)
def install(self):
print("Running install phase...")
@@ -122,6 +141,15 @@
if not self.ssl_verify:
env["GIT_SSL_NO_VERIFY"] = "1"
self.run_build_command(cmd, env=env)
+ status = {}
+ if self.options.branch is not None:
+ status["revision_id"] = self.run_build_command(
+ ["bzr", "revno", self.name], get_output=True).rstrip("\n")
+ else:
+ status["revision_id"] = self.run_build_command(
+ ["git", "-C", self.name, "rev-parse", self.options.git_path],
+ get_output=True).rstrip("\n")
+ self.save_status(status)
def pull(self):
"""Run pull phase."""
=== modified file 'debian/changelog'
--- debian/changelog 2017-02-10 14:55:42 +0000
+++ debian/changelog 2017-04-03 12:38:12 +0000
@@ -1,3 +1,10 @@
+launchpad-buildd (143) UNRELEASED; urgency=medium
+
+ * Record the branch revision used to build a snap and return it along with
+ other XML-RPC status information (LP: #1679157).
+
+ -- Colin Watson <cjwatson@xxxxxxxxxx> Fri, 31 Mar 2017 15:31:10 +0100
+
launchpad-buildd (142) trusty; urgency=medium
* lpbuildd.binarypackage: Pass DEB_BUILD_OPTIONS=noautodbgsym if we have
=== modified file 'lpbuildd/slave.py'
--- lpbuildd/slave.py 2016-12-09 18:04:00 +0000
+++ lpbuildd/slave.py 2017-04-03 12:38:12 +0000
@@ -199,6 +199,14 @@
self.runSubProcess(self._preppath, ["slave-prep"])
+ def status(self):
+ """Return extra status for this build manager, as a dictionary.
+
+ This may be used to return manager-specific information from the
+ XML-RPC status call.
+ """
+ return {}
+
def iterate(self, success):
"""Perform an iteration of the slave.
@@ -309,6 +317,7 @@
self.waitingfiles = {}
self.builddependencies = ""
self._log = None
+ self.manager = None
if not os.path.isdir(self._cachepath):
raise ValueError("FileCache path is not a dir")
@@ -665,6 +674,8 @@
if self._version is not None:
ret["builder_version"] = self._version
ret.update(func())
+ if self.slave.manager is not None:
+ ret.update(self.slave.manager.status())
return ret
def status_IDLE(self):
=== modified file 'lpbuildd/snap.py'
--- lpbuildd/snap.py 2016-08-30 12:47:03 +0000
+++ lpbuildd/snap.py 2017-04-03 12:38:12 +0000
@@ -1,10 +1,14 @@
# Copyright 2015-2016 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
+from __future__ import print_function
+
__metaclass__ = type
+import json
import os
import shutil
+import sys
from lpbuildd.debian import (
DebianBuildManager,
@@ -51,6 +55,19 @@
super(SnapBuildManager, self).initiate(files, chroot, extra_args)
+ def status(self):
+ status_path = get_build_path(self.home, self._buildid, "status")
+ try:
+ with open(status_path) as status_file:
+ return json.load(status_file)
+ except IOError:
+ pass
+ except Exception as e:
+ print(
+ "Error deserialising status from buildsnap: %s" % e,
+ file=sys.stderr)
+ return {}
+
def doRunBuild(self):
"""Run the process to build the snap."""
args = [
=== modified file 'lpbuildd/tests/test_snap.py'
--- lpbuildd/tests/test_snap.py 2016-08-30 12:47:03 +0000
+++ lpbuildd/tests/test_snap.py 2017-04-03 12:38:12 +0000
@@ -82,6 +82,16 @@
self.buildmanager.iterate, self.buildmanager.iterators[-1])
self.assertFalse(self.slave.wasCalled("chrootFail"))
+ def test_status(self):
+ # The build manager returns saved status information on request.
+ self.assertEqual({}, self.buildmanager.status())
+ status_path = os.path.join(
+ self.working_dir, "home", "build-%s" % self.buildid, "status")
+ os.makedirs(os.path.dirname(status_path))
+ with open(status_path, "w") as status_file:
+ status_file.write('{"revision_id": "dummy"}')
+ self.assertEqual({"revision_id": "dummy"}, self.buildmanager.status())
+
def test_iterate(self):
# The build manager iterates a normal build from start to finish.
self.startBuild()