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

Proposed by Colin Watson on 2016-11-21
Status: Rejected
Rejected by: Colin Watson on 2019-07-30
Proposed branch: lp:~cjwatson/launchpad/snap-pending-import
Merge into: lp:launchpad
Diff against target: 140 lines (+97/-0)
2 files modified
lib/lp/snappy/model/snapbuild.py (+25/-0)
lib/lp/snappy/tests/test_snapbuild.py (+72/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/snap-pending-import
Reviewer Review Type Date Requested Status
Launchpad code reviewers 2016-11-21 Pending
Review via email: mp+311391@code.launchpad.net

Commit message

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

Description of the change

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.

To post a comment you must log in.
William Grant (wgrant) wrote :

This seems risky. The set of snap builds that have to be considered in each dispatch will grow without bound as imports fail or refs to non-commits attempt to be built. I suppose we could just have graphs of that and check them occasionally.

Colin Watson (cjwatson) wrote :

I'm withdrawing this since I have no current plans to work on the problem William raised, and the code import workflow has been mostly superseded for automation purposes these days by building directly from external repositories instead.

Unmerged revisions

18280. By Colin Watson on 2016-11-21

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/snappy/model/snapbuild.py'
2--- lib/lp/snappy/model/snapbuild.py 2016-08-16 16:24:51 +0000
3+++ lib/lp/snappy/model/snapbuild.py 2016-11-21 14:12:14 +0000
4@@ -48,6 +48,7 @@
5 IMasterStore,
6 IStore,
7 )
8+from lp.services.database.sqlbase import sqlvalues
9 from lp.services.job.interfaces.job import JobStatus
10 from lp.services.job.model.job import Job
11 from lp.services.librarian.browser import ProxiedLibraryFileAlias
12@@ -469,3 +470,27 @@
13 SnapBuild, SnapBuild.build_farm_job_id.is_in(
14 bfj.id for bfj in build_farm_jobs))
15 return DecoratedResultSet(rows, pre_iter_hook=self.preloadBuildsData)
16+
17+ def addCandidateSelectionCriteria(self, processor, virtualized):
18+ """See `ISpecificBuildFarmJobSource`."""
19+ return """
20+ SELECT 1 FROM Snap, SnapBuild
21+ WHERE
22+ SnapBuild.build_farm_job = BuildQueue.build_farm_job AND
23+ SnapBuild.snap = Snap.id AND
24+ ((Snap.branch IS NOT NULL AND
25+ EXISTS (
26+ SELECT 1 FROM Branch
27+ WHERE
28+ Branch.id = Snap.branch AND
29+ Branch.revision_count != 0))
30+ OR
31+ (Snap.git_repository IS NOT NULL AND
32+ EXISTS (
33+ SELECT 1 FROM GitRef
34+ WHERE
35+ GitRef.repository = Snap.git_repository AND
36+ GitRef.path = Snap.git_path AND
37+ GitRef.commit_message IS NOT NULL))) AND
38+ SnapBuild.status = %s
39+ """ % sqlvalues(BuildStatus.NEEDSBUILD)
40
41=== modified file 'lib/lp/snappy/tests/test_snapbuild.py'
42--- lib/lp/snappy/tests/test_snapbuild.py 2016-08-16 16:24:51 +0000
43+++ lib/lp/snappy/tests/test_snapbuild.py 2016-11-21 14:12:14 +0000
44@@ -15,6 +15,10 @@
45 )
46
47 import pytz
48+from testscenarios import (
49+ load_tests_apply_scenarios,
50+ WithScenarios,
51+ )
52 from testtools.matchers import (
53 Equals,
54 MatchesDict,
55@@ -29,6 +33,8 @@
56 from lp.buildmaster.interfaces.buildqueue import IBuildQueue
57 from lp.buildmaster.interfaces.packagebuild import IPackageBuild
58 from lp.buildmaster.interfaces.processor import IProcessorSet
59+from lp.buildmaster.tests.mock_slaves import make_publisher
60+from lp.code.interfaces.revision import IRevisionSet
61 from lp.registry.enums import PersonVisibility
62 from lp.services.config import config
63 from lp.services.features.testing import FeatureFixture
64@@ -466,6 +472,69 @@
65 [], getUtility(ISnapBuildSet).getByBuildFarmJobs([]))
66
67
68+class TestSnapBuildFindBuildCandidate(WithScenarios, TestCaseWithFactory):
69+
70+ layer = LaunchpadZopelessLayer
71+
72+ scenarios = [
73+ ("Branch", {"context_type": "branch"}),
74+ ("GitRef", {"context_type": "gitref"}),
75+ ]
76+
77+ def setUp(self):
78+ super(TestSnapBuildFindBuildCandidate, self).setUp()
79+ self.publisher = make_publisher()
80+ self.publisher.prepareBreezyAutotest()
81+ self.builder = self.factory.makeBuilder(
82+ processors=[self.publisher.breezy_autotest_i386.processor],
83+ virtualized=True)
84+
85+ def makeSnap(self, with_revisions=True):
86+ if self.context_type == "branch":
87+ branch = self.factory.makeBranch()
88+ if with_revisions:
89+ self.factory.makeRevisionsForBranch(branch)
90+ return self.factory.makeSnap(branch=branch)
91+ elif self.context_type == "gitref":
92+ [ref] = self.factory.makeGitRefs()
93+ if with_revisions:
94+ person = self.factory.makePerson()
95+ email = removeSecurityProxy(person).preferredemail.email
96+ author = getUtility(IRevisionSet).acquireRevisionAuthors(
97+ [email])[email]
98+ now = datetime.now(pytz.UTC)
99+ naked_ref = removeSecurityProxy(ref)
100+ naked_ref.author = naked_ref.committer = author
101+ naked_ref.author_date = naked_ref.committer_date = now
102+ naked_ref.commit_message = u"something"
103+ return self.factory.makeSnap(git_ref=ref)
104+ else:
105+ raise AssertionError("unknown context_type %s" % self.context_type)
106+
107+ def test_findBuildCandidate_ready(self):
108+ # Builder._findBuildCandidate finds a SnapBuild with a usable code
109+ # object.
110+ snap = self.makeSnap()
111+ build = self.factory.makeSnapBuild(
112+ snap=snap, distroarchseries=self.publisher.breezy_autotest_i386)
113+ build.queueBuild()
114+ next_job = removeSecurityProxy(self.builder)._findBuildCandidate()
115+ self.assertEqual(
116+ build,
117+ getUtility(ISnapBuildSet).getByBuildFarmJob(
118+ removeSecurityProxy(next_job)._build_farm_job))
119+
120+ def test_findBuildCandidate_no_revisions(self):
121+ # Builder._findBuildCandidate skips SnapBuilds without a usable code
122+ # object, such as an imported branch whose import hasn't run yet.
123+ snap = self.makeSnap(with_revisions=False)
124+ build = self.factory.makeSnapBuild(
125+ snap=snap, distroarchseries=self.publisher.breezy_autotest_i386)
126+ build.queueBuild()
127+ self.assertIsNone(
128+ removeSecurityProxy(self.builder)._findBuildCandidate())
129+
130+
131 class TestSnapBuildWebservice(TestCaseWithFactory):
132
133 layer = LaunchpadFunctionalLayer
134@@ -621,3 +690,6 @@
135 browser = self.getNonRedirectingBrowser(user=self.person)
136 for file_url in file_urls:
137 self.assertCanOpenRedirectedUrl(browser, file_url)
138+
139+
140+load_tests = load_tests_apply_scenarios