← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad-buildd:brz-builder into launchpad-buildd:master

 

Colin Watson has proposed merging ~cjwatson/launchpad-buildd:brz-builder into launchpad-buildd:master.

Commit message:
Use brz-build-daily-recipe if it exists

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1943292 in launchpad-buildd: "Launchpad builders kernel 4.15 too old to compile software that uses uring"
  https://bugs.launchpad.net/launchpad-buildd/+bug/1943292

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-buildd/+git/launchpad-buildd/+merge/412287

In order to fully support focal, we need to use `brz` rather than `bzr` to support Python 3.  Fortunately, `bzr-builder` was already ported upstream as `brz-builder`, so make use of it if it exists.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad-buildd:brz-builder into launchpad-buildd:master.
diff --git a/bin/buildrecipe b/bin/buildrecipe
index b447f01..d0effdc 100755
--- a/bin/buildrecipe
+++ b/bin/buildrecipe
@@ -84,6 +84,21 @@ class RecipeBuilder:
         """
         return self.chroot(['apt-get', 'install', '-y', 'lsb-release'])
 
+    # XXX cjwatson 2021-11-23: Use shutil.which instead once we can assume
+    # Python >= 3.3.
+    def _find_on_path(command):
+        """Is 'command' on the executable search path?"""
+        if "PATH" not in os.environ:
+            return False
+        path = os.environ["PATH"]
+        for element in path.split(os.pathsep):
+            if not element:
+                continue
+            filename = os.path.join(element, command)
+            if os.path.isfile(filename) and os.access(filename, os.X_OK):
+                return True
+        return False
+
     def buildTree(self):
         """Build the recipe into a source tree.
 
@@ -127,6 +142,8 @@ class RecipeBuilder:
             }
         if self.git:
             cmd = ['git-build-recipe']
+        elif self._find_on_path('brz-build-daily-recipe'):
+            cmd = ['brz-build-daily-recipe']
         else:
             cmd = ['bzr', '-Derror', 'dailydeb']
         cmd.extend([
diff --git a/debian/changelog b/debian/changelog
index a56c8da..f3d2dc4 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+launchpad-buildd (205) UNRELEASED; urgency=medium
+
+  * Use brz-build-daily-recipe rather than "bzr -Derror dailydeb" if the
+    former exists (see LP #1943292).
+
+ -- Colin Watson <cjwatson@xxxxxxxxxx>  Tue, 23 Nov 2021 16:08:51 +0000
+
 launchpad-buildd (204) bionic; urgency=medium
 
   * Configure apt to automatically retry downloads on failures
diff --git a/lpbuildd/tests/test_buildrecipe.py b/lpbuildd/tests/test_buildrecipe.py
index a4da180..37f8dae 100644
--- a/lpbuildd/tests/test_buildrecipe.py
+++ b/lpbuildd/tests/test_buildrecipe.py
@@ -139,6 +139,60 @@ class TestRecipeBuilder(TestCase):
                 """) % repr(expected_recipe_command),
             mock_stdout.getvalue())
 
+    def test_buildTree_brz(self):
+        def fake_bzr(args):
+            if args["args"][1] == "version":
+                print("brz version x.y.z")
+                return {}
+            elif args["args"][1] == "plugins":
+                print("brz-plugin x.y.z")
+                return {}
+            else:
+                return {"returncode": 1}
+
+        def fake_brz_build_daily_recipe(args):
+            print("dummy recipe build")
+            os.makedirs(os.path.join(self.builder.tree_path, "foo"))
+            return {}
+
+        processes_fixture = self.useFixture(FakeProcesses())
+        processes_fixture.add(
+            lambda _: {"stdout": io.StringIO(u"5.10\n")}, name="sudo")
+        processes_fixture.add(fake_bzr, name="bzr")
+        processes_fixture.add(
+            fake_brz_build_daily_recipe, name="brz-build-daily-recipe")
+        with open(os.path.join(self.builder.work_dir, "recipe"), "w") as f:
+            f.write("dummy recipe contents\n")
+        mock_stdout = six.StringIO()
+        self.useFixture(MockPatch("sys.stdout", mock_stdout))
+        self.useFixture(MockPatchObject(
+            self.builder, "_find_on_path",
+            side_effect=lambda command: command == "brz-build-daily-recipe"))
+        self.assertEqual(0, self.builder.buildTree())
+        self.assertEqual(
+            os.path.join(self.builder.work_dir_relative, "tree", "foo"),
+            self.builder.source_dir_relative)
+        expected_recipe_command = [
+            "brz-build-daily-recipe", "--safe", "--no-build",
+            "--manifest", os.path.join(self.builder.tree_path, "manifest"),
+            "--distribution", "grumpy", "--allow-fallback-to-native",
+            "--append-version", u"~ubuntu5.10.1",
+            os.path.join(self.builder.work_dir, "recipe"),
+            self.builder.tree_path,
+            ]
+        self.assertEqual(
+            dedent("""\
+                Bazaar versions:
+                brz version x.y.z
+                brz-plugin x.y.z
+                Building recipe:
+                dummy recipe contents
+
+                RUN %s
+                dummy recipe build
+                """) % repr(expected_recipe_command),
+            mock_stdout.getvalue())
+
     def test_buildTree_bzr(self):
         def fake_bzr(args):
             if args["args"][1] == "version":
@@ -162,6 +216,8 @@ class TestRecipeBuilder(TestCase):
             f.write("dummy recipe contents\n")
         mock_stdout = six.StringIO()
         self.useFixture(MockPatch("sys.stdout", mock_stdout))
+        self.useFixture(MockPatchObject(
+            self.builder, "_find_on_path", return_value=False))
         self.assertEqual(0, self.builder.buildTree())
         self.assertEqual(
             os.path.join(self.builder.work_dir_relative, "tree", "foo"),