← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/snap-pending-import into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/snap-pending-import into lp:launchpad.

Commit message:
Don't dispatch SnapBuilds whose code object is empty, perhaps because an associated code import hasn't finished.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snap-pending-import/+merge/311391

This should make it easier to create a code import, a snap, and some builds in quick succession (via automation) without needing to worry about whether the builds will be dispatched before the import has completed.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/snap-pending-import into lp:launchpad.
=== modified file 'lib/lp/snappy/model/snapbuild.py'
--- lib/lp/snappy/model/snapbuild.py	2016-08-16 16:24:51 +0000
+++ lib/lp/snappy/model/snapbuild.py	2016-11-21 14:12:14 +0000
@@ -48,6 +48,7 @@
     IMasterStore,
     IStore,
     )
+from lp.services.database.sqlbase import sqlvalues
 from lp.services.job.interfaces.job import JobStatus
 from lp.services.job.model.job import Job
 from lp.services.librarian.browser import ProxiedLibraryFileAlias
@@ -469,3 +470,27 @@
             SnapBuild, SnapBuild.build_farm_job_id.is_in(
                 bfj.id for bfj in build_farm_jobs))
         return DecoratedResultSet(rows, pre_iter_hook=self.preloadBuildsData)
+
+    def addCandidateSelectionCriteria(self, processor, virtualized):
+        """See `ISpecificBuildFarmJobSource`."""
+        return """
+            SELECT 1 FROM Snap, SnapBuild
+            WHERE
+                SnapBuild.build_farm_job = BuildQueue.build_farm_job AND
+                SnapBuild.snap = Snap.id AND
+                ((Snap.branch IS NOT NULL AND
+                  EXISTS (
+                      SELECT 1 FROM Branch
+                      WHERE
+                          Branch.id = Snap.branch AND
+                          Branch.revision_count != 0))
+                 OR
+                 (Snap.git_repository IS NOT NULL AND
+                  EXISTS (
+                      SELECT 1 FROM GitRef
+                      WHERE
+                          GitRef.repository = Snap.git_repository AND
+                          GitRef.path = Snap.git_path AND
+                          GitRef.commit_message IS NOT NULL))) AND
+                SnapBuild.status = %s
+            """ % sqlvalues(BuildStatus.NEEDSBUILD)

=== modified file 'lib/lp/snappy/tests/test_snapbuild.py'
--- lib/lp/snappy/tests/test_snapbuild.py	2016-08-16 16:24:51 +0000
+++ lib/lp/snappy/tests/test_snapbuild.py	2016-11-21 14:12:14 +0000
@@ -15,6 +15,10 @@
     )
 
 import pytz
+from testscenarios import (
+    load_tests_apply_scenarios,
+    WithScenarios,
+    )
 from testtools.matchers import (
     Equals,
     MatchesDict,
@@ -29,6 +33,8 @@
 from lp.buildmaster.interfaces.buildqueue import IBuildQueue
 from lp.buildmaster.interfaces.packagebuild import IPackageBuild
 from lp.buildmaster.interfaces.processor import IProcessorSet
+from lp.buildmaster.tests.mock_slaves import make_publisher
+from lp.code.interfaces.revision import IRevisionSet
 from lp.registry.enums import PersonVisibility
 from lp.services.config import config
 from lp.services.features.testing import FeatureFixture
@@ -466,6 +472,69 @@
             [], getUtility(ISnapBuildSet).getByBuildFarmJobs([]))
 
 
+class TestSnapBuildFindBuildCandidate(WithScenarios, TestCaseWithFactory):
+
+    layer = LaunchpadZopelessLayer
+
+    scenarios = [
+        ("Branch", {"context_type": "branch"}),
+        ("GitRef", {"context_type": "gitref"}),
+        ]
+
+    def setUp(self):
+        super(TestSnapBuildFindBuildCandidate, self).setUp()
+        self.publisher = make_publisher()
+        self.publisher.prepareBreezyAutotest()
+        self.builder = self.factory.makeBuilder(
+            processors=[self.publisher.breezy_autotest_i386.processor],
+            virtualized=True)
+
+    def makeSnap(self, with_revisions=True):
+        if self.context_type == "branch":
+            branch = self.factory.makeBranch()
+            if with_revisions:
+                self.factory.makeRevisionsForBranch(branch)
+            return self.factory.makeSnap(branch=branch)
+        elif self.context_type == "gitref":
+            [ref] = self.factory.makeGitRefs()
+            if with_revisions:
+                person = self.factory.makePerson()
+                email = removeSecurityProxy(person).preferredemail.email
+                author = getUtility(IRevisionSet).acquireRevisionAuthors(
+                    [email])[email]
+                now = datetime.now(pytz.UTC)
+                naked_ref = removeSecurityProxy(ref)
+                naked_ref.author = naked_ref.committer = author
+                naked_ref.author_date = naked_ref.committer_date = now
+                naked_ref.commit_message = u"something"
+            return self.factory.makeSnap(git_ref=ref)
+        else:
+            raise AssertionError("unknown context_type %s" % self.context_type)
+
+    def test_findBuildCandidate_ready(self):
+        # Builder._findBuildCandidate finds a SnapBuild with a usable code
+        # object.
+        snap = self.makeSnap()
+        build = self.factory.makeSnapBuild(
+            snap=snap, distroarchseries=self.publisher.breezy_autotest_i386)
+        build.queueBuild()
+        next_job = removeSecurityProxy(self.builder)._findBuildCandidate()
+        self.assertEqual(
+            build,
+            getUtility(ISnapBuildSet).getByBuildFarmJob(
+                removeSecurityProxy(next_job)._build_farm_job))
+
+    def test_findBuildCandidate_no_revisions(self):
+        # Builder._findBuildCandidate skips SnapBuilds without a usable code
+        # object, such as an imported branch whose import hasn't run yet.
+        snap = self.makeSnap(with_revisions=False)
+        build = self.factory.makeSnapBuild(
+            snap=snap, distroarchseries=self.publisher.breezy_autotest_i386)
+        build.queueBuild()
+        self.assertIsNone(
+            removeSecurityProxy(self.builder)._findBuildCandidate())
+
+
 class TestSnapBuildWebservice(TestCaseWithFactory):
 
     layer = LaunchpadFunctionalLayer
@@ -621,3 +690,6 @@
         browser = self.getNonRedirectingBrowser(user=self.person)
         for file_url in file_urls:
             self.assertCanOpenRedirectedUrl(browser, file_url)
+
+
+load_tests = load_tests_apply_scenarios


Follow ups