Merge lp:~julian-edwards/launchpad/config-ppa-for-slaves into lp:launchpad

Proposed by Julian Edwards
Status: Merged
Merged at revision: not available
Proposed branch: lp:~julian-edwards/launchpad/config-ppa-for-slaves
Merge into: lp:launchpad
Diff against target: 181 lines (+91/-4)
4 files modified
configs/development/launchpad-lazr.conf (+1/-0)
lib/canonical/config/schema-lazr.conf (+6/-0)
lib/lp/code/model/recipebuilder.py (+27/-2)
lib/lp/code/tests/test_recipebuilder.py (+57/-2)
To merge this branch: bzr merge lp:~julian-edwards/launchpad/config-ppa-for-slaves
Reviewer Review Type Date Requested Status
Michael Nelson (community) code Approve
Review via email: mp+24409@code.launchpad.net

Description of the change

= Summary =
Send a configured sources.list entry to the build slaves for recipe builds.

== Proposed fix ==
This branch adds a new config item builddmaster.bzr_builder_sources_list which
can optionally contain a sources.list entry that is set up on the build slaves
before starting recipe builds.

This will enable us to set up a PPA with a bzr-builder package in it that the
recipe builds can use.

We're doing this because the rate of change of development on bzr-builder is
too fast to make changes in Ubuntu with its SRU policy.

We'll set up two PPAs, one containing development package for testing which is
owned by the Launchpad team, and one for production owned by IS/buildd-admins.
The buildd admins will copy a package from the development PPA once it's
proven tested on dogfood.

This is why there's a config item: the PPA to use needs to be configured
differently on dogfood, development and production.

== Tests ==

bin/test -cvv test_recipebuilder

== Demo and Q/A ==

The Code team is testing this approach on dogfood right now with a hacked
change. We'll drop in this replacement branch and things should continue to
work :)

To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :

Great Julian!

As per IRC, you'll add a new test for the case where the config option is not set, and try s/AttributeError/KeyError for the substitution exception.

Thanks!

{{{
16:31 < noodles775> bigjools: given that you're change will also require updating lp-production-configs, should you be wrapping the actual config.buildmaster.bzr_builder_sources_list in a try/except?
16:31 < noodles775> wgrant: yep, trying now.
16:32 < wgrant> noodles775: Thanks.
16:32 < noodles775> bigjools: also, why not catch KeyError rather than StandardError when substituting the series?
16:33 < bigjools> noodles775: it returns None if it doesn't exist
16:33 < bigjools> I think!
16:33 < noodles775> bigjools: I just tried locally - AttributeError: No section key named bzr_builder_sources_list.
16:33 < bigjools> re. second point, I am shamefully copy & wasting the code in adapters/archivedependencies.py that does a similar thing
16:34 < bigjools> noodles775: crap, I'll fix that, thanks for noticing
16:34 < noodles775> np. Great.
16:38 < noodles775> bigjools: you could rework the second test (or add a separate test) so it shows the failure when the config option is not set?
16:39 < bigjools> noodles775: yep, I can add another test
}}}

review: Approve (code)
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Thanks Michael!

Here's the partial diff for completeness. As we discussed, the KeyError
doesn't really catch everything, so I left the StandardError in.

1=== modified file 'lib/lp/code/model/recipebuilder.py'
2--- lib/lp/code/model/recipebuilder.py 2010-04-28 16:53:18 +0000
3+++ lib/lp/code/model/recipebuilder.py 2010-04-29 14:51:16 +0000
4@@ -79,17 +79,22 @@
5 # sources.list entry for an archive that will contain a
6 # bzr-builder package that needs to be used to build this
7 # recipe.
8- extra_archive = config.builddmaster.bzr_builder_sources_list
9+ try:
10+ extra_archive = config.builddmaster.bzr_builder_sources_list
11+ except AttributeError:
12+ extra_archive = None
13+
14 if extra_archive is not None:
15 try:
16 sources_line = extra_archive % (
17 {'series': self.build.distroseries.name})
18 args['archives'].append(sources_line)
19- except StandardError, e:
20+ except StandardError:
21 # Someone messed up the config, don't add it.
22 logger.error(
23 "Exception processing bzr_builder_sources_list:\n%s"
24 % traceback.format_exc())
25+
26 args['distroseries_name'] = self.build.distroseries.name
27 return args
28
29
30=== modified file 'lib/lp/code/tests/test_recipebuilder.py'
31--- lib/lp/code/tests/test_recipebuilder.py 2010-04-29 11:37:15 +0000
32+++ lib/lp/code/tests/test_recipebuilder.py 2010-04-29 14:42:36 +0000
33@@ -127,7 +127,7 @@
34 'distroseries_name': job.build.distroseries.name,
35 }, job._extraBuildArgs(distroarchseries))
36
37- def test__extraBuildArgs_withBadConfigForBzrBuilderPPA(self):
38+ def test_extraBuildArgs_withBadConfigForBzrBuilderPPA(self):
39 # Ensure _extraBuildArgs doesn't blow up with a badly formatted
40 # bzr_builder_sources_list in the config.
41 bzr_builder_config = """
42@@ -160,6 +160,16 @@
43 "Exception processing bzr_builder_sources_list:",
44 logger.buffer.getvalue())
45
46+ def test_extraBuildArgs_withNoBZrBuilderConfigSet(self):
47+ # Ensure _extraBuildArgs doesn't blow up when
48+ # bzr_builder_sources_list isn't set.
49+ job = self.makeJob()
50+ distroarchseries = job.build.distroseries.architectures[0]
51+ args = job._extraBuildArgs(distroarchseries)
52+ expected_archives = get_sources_list_for_building(
53+ job.build, distroarchseries, job.build.sourcepackagename.name)
54+ self.assertEqual(args["archives"], expected_archives)
55+
56
57 def test_dispatchBuildToSlave(self):
58 # Ensure dispatchBuildToSlave will make the right calls to the slave

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configs/development/launchpad-lazr.conf'
2--- configs/development/launchpad-lazr.conf 2010-04-19 03:44:27 +0000
3+++ configs/development/launchpad-lazr.conf 2010-04-29 14:57:34 +0000
4@@ -16,6 +16,7 @@
5 [builddmaster]
6 root: /var/tmp/builddmaster/
7 uploader: scripts/process-upload.py -Mvv
8+bzr_builder_sources_list: None
9
10 [buildsequencer]
11 mailproblemsto: root
12
13=== modified file 'lib/canonical/config/schema-lazr.conf'
14--- lib/canonical/config/schema-lazr.conf 2010-04-19 03:44:27 +0000
15+++ lib/canonical/config/schema-lazr.conf 2010-04-29 14:57:34 +0000
16@@ -110,6 +110,12 @@
17 # datatype: string
18 root: none
19
20+# Optional sources.list entry to send to build slaves when doing recipe
21+# builds involving bzr-builder. Use this form so that the series is set:
22+# deb http://foo %(series)s main
23+# datatype: string
24+bzr_builder_sources_list: none
25+
26
27 [buildsequencer]
28 # The name of the log file for the sequencer (passed to twistd)
29
30=== modified file 'lib/lp/code/model/recipebuilder.py'
31--- lib/lp/code/model/recipebuilder.py 2010-04-20 01:36:29 +0000
32+++ lib/lp/code/model/recipebuilder.py 2010-04-29 14:57:34 +0000
33@@ -8,9 +8,13 @@
34 'RecipeBuildBehavior',
35 ]
36
37+import traceback
38+
39 from zope.component import adapts
40 from zope.interface import implements
41
42+from canonical.config import config
43+
44 from lp.archiveuploader.permission import check_upload_to_pocket
45 from lp.buildmaster.interfaces.buildfarmjobbehavior import (
46 IBuildFarmJobBehavior)
47@@ -50,7 +54,7 @@
48 """See `IBuildFarmJobBehavior`."""
49 logger.info("startBuild(%s)", self.display_name)
50
51- def _extraBuildArgs(self, distroarchseries):
52+ def _extraBuildArgs(self, distroarchseries, logger=None):
53 """
54 Return the extra arguments required by the slave for the given build.
55 """
56@@ -70,6 +74,27 @@
57 self.build.sourcepackagename.name)
58 args['archives'] = get_sources_list_for_building(self.build,
59 distroarchseries, self.build.sourcepackagename.name)
60+
61+ # config.builddmaster.bzr_builder_sources_list can contain a
62+ # sources.list entry for an archive that will contain a
63+ # bzr-builder package that needs to be used to build this
64+ # recipe.
65+ try:
66+ extra_archive = config.builddmaster.bzr_builder_sources_list
67+ except AttributeError:
68+ extra_archive = None
69+
70+ if extra_archive is not None:
71+ try:
72+ sources_line = extra_archive % (
73+ {'series': self.build.distroseries.name})
74+ args['archives'].append(sources_line)
75+ except StandardError:
76+ # Someone messed up the config, don't add it.
77+ logger.error(
78+ "Exception processing bzr_builder_sources_list:\n%s"
79+ % traceback.format_exc())
80+
81 args['distroseries_name'] = self.build.distroseries.name
82 return args
83
84@@ -101,7 +126,7 @@
85 logger.debug(
86 "Initiating build %s on %s" % (buildid, self._builder.url))
87
88- args = self._extraBuildArgs(distroarchseries)
89+ args = self._extraBuildArgs(distroarchseries, logger)
90 status, info = self._builder.slave.build(
91 cookie, "sourcepackagerecipe", chroot_sha1, {}, args)
92 message = """%s (%s):
93
94=== modified file 'lib/lp/code/tests/test_recipebuilder.py'
95--- lib/lp/code/tests/test_recipebuilder.py 2010-04-20 23:22:24 +0000
96+++ lib/lp/code/tests/test_recipebuilder.py 2010-04-29 14:57:34 +0000
97@@ -12,6 +12,7 @@
98
99 from zope.security.proxy import removeSecurityProxy
100
101+from canonical.config import config
102 from canonical.testing import LaunchpadFunctionalLayer
103 from canonical.launchpad.scripts.logger import BufferLogger
104
105@@ -100,8 +101,19 @@
106
107 def test__extraBuildArgs(self):
108 # _extraBuildArgs will return a sane set of additional arguments
109+ bzr_builder_config = """
110+ [builddmaster]
111+ bzr_builder_sources_list = deb http://foo %(series)s main
112+ """
113+ config.push("bzr_builder_config", bzr_builder_config)
114+ self.addCleanup(config.pop, "bzr_builder_config")
115+
116 job = self.makeJob()
117 distroarchseries = job.build.distroseries.architectures[0]
118+ expected_archives = get_sources_list_for_building(
119+ job.build, distroarchseries, job.build.sourcepackagename.name)
120+ expected_archives.append(
121+ "deb http://foo %s main" % job.build.distroseries.name)
122 self.assertEqual({
123 'author_email': u'requester@ubuntu.com',
124 'suite': u'mydistro',
125@@ -111,11 +123,54 @@
126 'ogrecomponent': 'universe',
127 'recipe_text': '# bzr-builder format 0.2 deb-version 1.0\n'
128 'lp://dev/~joe/someapp/pkg\n',
129- 'archives': get_sources_list_for_building(job.build,
130- distroarchseries, job.build.sourcepackagename.name),
131+ 'archives': expected_archives,
132 'distroseries_name': job.build.distroseries.name,
133 }, job._extraBuildArgs(distroarchseries))
134
135+ def test_extraBuildArgs_withBadConfigForBzrBuilderPPA(self):
136+ # Ensure _extraBuildArgs doesn't blow up with a badly formatted
137+ # bzr_builder_sources_list in the config.
138+ bzr_builder_config = """
139+ [builddmaster]
140+ bzr_builder_sources_list = deb http://foo %(series) main
141+ """
142+ # (note the missing 's' in %(series)
143+
144+ config.push("bzr_builder_config", bzr_builder_config)
145+ self.addCleanup(config.pop, "bzr_builder_config")
146+
147+ job = self.makeJob()
148+ distroarchseries = job.build.distroseries.architectures[0]
149+ expected_archives = get_sources_list_for_building(
150+ job.build, distroarchseries, job.build.sourcepackagename.name)
151+ logger = BufferLogger()
152+ self.assertEqual({
153+ 'author_email': u'requester@ubuntu.com',
154+ 'suite': u'mydistro',
155+ 'author_name': u'Joe User',
156+ 'package_name': u'apackage',
157+ 'archive_purpose': 'PPA',
158+ 'ogrecomponent': 'universe',
159+ 'recipe_text': '# bzr-builder format 0.2 deb-version 1.0\n'
160+ 'lp://dev/~joe/someapp/pkg\n',
161+ 'archives': expected_archives,
162+ 'distroseries_name': job.build.distroseries.name,
163+ }, job._extraBuildArgs(distroarchseries, logger))
164+ self.assertIn(
165+ "Exception processing bzr_builder_sources_list:",
166+ logger.buffer.getvalue())
167+
168+ def test_extraBuildArgs_withNoBZrBuilderConfigSet(self):
169+ # Ensure _extraBuildArgs doesn't blow up when
170+ # bzr_builder_sources_list isn't set.
171+ job = self.makeJob()
172+ distroarchseries = job.build.distroseries.architectures[0]
173+ args = job._extraBuildArgs(distroarchseries)
174+ expected_archives = get_sources_list_for_building(
175+ job.build, distroarchseries, job.build.sourcepackagename.name)
176+ self.assertEqual(args["archives"], expected_archives)
177+
178+
179 def test_dispatchBuildToSlave(self):
180 # Ensure dispatchBuildToSlave will make the right calls to the slave
181 job = self.makeJob()