← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad-buildd/bug-1460363 into lp:launchpad-buildd

 

William Grant has proposed merging lp:~wgrant/launchpad-buildd/bug-1460363 into lp:launchpad-buildd.

Commit message:
Tighten apt depwait parsing to not return uninstallable deps as missing.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #1460363 in launchpad-buildd: "New sbuild depwait parsing finds uninstallable deps"
  https://bugs.launchpad.net/launchpad-buildd/+bug/1460363

For more details, see:
https://code.launchpad.net/~wgrant/launchpad-buildd/bug-1460363/+merge/260666

The new lpbuildd.binarypackage depwait regular expression counted errors like "but it is not going to be installed" as missing dependencies. But that error means the package exists but its deps aren't satisfiable, so retry-depwait retries the build in a loop.

This branch tightens the expression to match only patterns that indicate missing deps or bad versions.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad-buildd/bug-1460363 into lp:launchpad-buildd.
=== modified file 'debian/changelog'
--- debian/changelog	2015-05-26 01:27:37 +0000
+++ debian/changelog	2015-05-31 23:44:08 +0000
@@ -1,3 +1,9 @@
+launchpad-buildd (129) UNRELEASED; urgency=low
+
+  * Tighten apt depwait parsing to not return uninstallable deps as missing.
+
+ -- William Grant <wgrant@xxxxxxxxxx>  Mon, 01 Jun 2015 09:39:37 +1000
+
 launchpad-buildd (128) trusty; urgency=medium
 
   [ Colin Watson ]

=== modified file 'lpbuildd/binarypackage.py'
--- lpbuildd/binarypackage.py	2015-05-12 02:03:53 +0000
+++ lpbuildd/binarypackage.py	2015-05-31 23:44:08 +0000
@@ -17,6 +17,14 @@
     BUILDERFAIL = 4
 
 
+APT_MISSING_DEP_PATTERNS = [
+    'but [^ ]* is to be installed',
+    'but [^ ]* is installed',
+    'but it is not installable',
+    'but it is a virtual package',
+    ]
+
+
 class BuildLogRegexes:
     """Build log regexes for performing actions based on regexes, and extracting dependencies for auto dep-waits"""
     GIVENBACK = [
@@ -24,7 +32,8 @@
         ]
     DEPFAIL = {
         'The following packages have unmet dependencies:\n'
-        '.*: Depends: (?P<p>[^ ]*( \([^)]*\))?)': "\g<p>",
+        '.*: Depends: (?P<p>[^ ]*( \([^)]*\))?) (%s)\n'
+        % '|'.join(APT_MISSING_DEP_PATTERNS): "\g<p>",
         }
 
 

=== modified file 'lpbuildd/tests/test_binarypackage.py'
--- lpbuildd/tests/test_binarypackage.py	2015-05-11 10:45:32 +0000
+++ lpbuildd/tests/test_binarypackage.py	2015-05-31 23:44:08 +0000
@@ -250,26 +250,46 @@
         self.assertUnmountsSanely()
         self.assertTrue(self.slave.wasCalled('buildFail'))
 
-    def test_detects_depfail(self):
-        # The build manager detects dependency installation failures.
+    def assertMatchesDepfail(self, error, dep):
         self.startBuild()
         write_file(
             os.path.join(self.buildmanager._cachepath, 'buildlog'),
             "The following packages have unmet dependencies:\n"
-            + " sbuild-build-depends-hello-dummy : Depends: enoent but it is "
-            + "not installable\n"
+            + (" sbuild-build-depends-hello-dummy : Depends: %s\n" % error)
             + "E: Unable to correct problems, you have held broken packages.\n"
             + ("a" * 4096) + "\n"
             + "Fail-Stage: install-deps\n")
 
-        # After building the package, reap processes.
         self.assertScansSanely(SBuildExitCodes.GIVENBACK)
-        self.assertFalse(self.slave.wasCalled('buildFail'))
-        self.assertEqual([(("enoent",), {})], self.slave.depFail.calls)
-
-        # Control returns to the DebianBuildManager in the UMOUNT state.
         self.assertUnmountsSanely()
-        self.assertFalse(self.slave.wasCalled('buildFail'))
+        if dep is not None:
+            self.assertFalse(self.slave.wasCalled('buildFail'))
+            self.assertEqual([((dep,), {})], self.slave.depFail.calls)
+        else:
+            self.assertFalse(self.slave.wasCalled('depFail'))
+            self.assertTrue(self.slave.wasCalled('buildFail'))
+
+    def test_detects_depfail(self):
+        # The build manager detects dependency installation failures.
+        self.assertMatchesDepfail(
+            "enoent but it is not installable", "enoent")
+
+    def test_detects_versioned_depfail(self):
+        # The build manager detects dependency installation failures.
+        self.assertMatchesDepfail(
+            "ebadver (< 2.0) but 3.0 is to be installed", "ebadver (< 2.0)")
+
+    def test_detects_versioned_current_depfail(self):
+        # The build manager detects dependency installation failures.
+        self.assertMatchesDepfail(
+            "ebadver (< 2.0) but 3.0 is installed", "ebadver (< 2.0)")
+
+    def test_uninstallable_deps_fail(self):
+        # Uninstallable build dependencies are considered to be
+        # failures, as we can't determine installability to
+        # automatically retry.
+        self.assertMatchesDepfail(
+            "ebadver but it is not going to be installed", None)
 
     def test_depfail_with_unknown_error_converted_to_packagefail(self):
         # The build manager converts a DEPFAIL to a PACKAGEFAIL if the


Follow ups