Merge lp:~wgrant/launchpad/bug-680889-arch-wildcards into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: Henning Eggers
Approved revision: no longer in the source branch.
Merged at revision: 12029
Proposed branch: lp:~wgrant/launchpad/bug-680889-arch-wildcards
Merge into: lp:launchpad
Diff against target: 291 lines (+121/-131)
3 files modified
lib/lp/soyuz/doc/package-arch-specific.txt (+0/-116)
lib/lp/soyuz/pas.py (+22/-15)
lib/lp/soyuz/tests/test_pas.py (+99/-0)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-680889-arch-wildcards
Reviewer Review Type Date Requested Status
Henning Eggers (community) code Approve
Review via email: mp+42723@code.launchpad.net

Commit message

[r=henninge][ui=none][bug=680889] Complex architecture hint strings involving architecture wildcards (e.g. "all linux-any") are now handled correctly.

Description of the change

As reported in bug #680889, lp.soyuz.pas.determineArchitecturesToBuild fails to properly handle valid architecture hint strings such as "all linux-any", creating no builds at all. This branch adjusts the "all", "any", and "linux-any" special cases to match even when they are not the sole component of the string.

It's a pretty simple change, except that I had to move the "all" check to the end, so hint strings like "all amd64" create an amd64 build, not an i386 arch-indep one.

I extended the tests to cover the specific problem reported and a few other edge cases.

To post a comment you must log in.
Revision history for this message
Henning Eggers (henninge) wrote :

Hi William,
thanks for this fix. The code looks good to me with my limited domain knowledge. ;-) I am worried about the doc test growing out of proportion, though, as it covers more corner cases. I would think these should be tested in a unit test while the doctest just shows the general operation of the code. Could you do something along those lines, please?
Cheers,
Henning

review: Needs Fixing (code)
Revision history for this message
Henning Eggers (henninge) wrote :

Thanks, great work, enormous improvement!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/soyuz/doc/package-arch-specific.txt'
--- lib/lp/soyuz/doc/package-arch-specific.txt 2010-10-14 18:42:19 +0000
+++ lib/lp/soyuz/doc/package-arch-specific.txt 2010-12-08 13:37:07 +0000
@@ -26,43 +26,10 @@
26 >>> ignore = test_publisher.setUpDefaultDistroSeries(hoary)26 >>> ignore = test_publisher.setUpDefaultDistroSeries(hoary)
27 >>> test_publisher.addFakeChroots()27 >>> test_publisher.addFakeChroots()
2828
29Create an architecture-independent source.
30
31 >>> pub_all = test_publisher.getPubSource(
32 ... sourcename='test-buildd', version='667')
33
34Create an architecture-specific source.
35
36 >>> pub_any = test_publisher.getPubSource(
37 ... sourcename='test-buildd-2', version='668',
38 ... architecturehintlist="any")
39
40Create a source with a specific list of architectures to be built.
41
42 >>> pub_three = test_publisher.getPubSource(29 >>> pub_three = test_publisher.getPubSource(
43 ... sourcename='test-buildd-3', version='669',30 ... sourcename='test-buildd-3', version='669',
44 ... architecturehintlist="i386 hppa amd64")31 ... architecturehintlist="i386 hppa amd64")
4532
46Create a source with one single specific architecture to be built.
47
48 >>> pub_one = test_publisher.getPubSource(
49 ... sourcename='test-buildd-4', version='670',
50 ... architecturehintlist="hppa")
51
52Create sources with 'any-$(ARCH)', 'linux-$(ARCH)' and 'linux-any' notation.
53
54 >>> pub_any_foo = test_publisher.getPubSource(
55 ... sourcename='test-buildd-6', version='672',
56 ... architecturehintlist="any-hppa")
57
58 >>> pub_linux_foo = test_publisher.getPubSource(
59 ... sourcename='test-buildd-7', version='673',
60 ... architecturehintlist="linux-i386")
61
62 >>> pub_linux_any = test_publisher.getPubSource(
63 ... sourcename='test-buildd-7', version='674',
64 ... architecturehintlist="linux-any")
65
66Create a PPA source publication.33Create a PPA source publication.
6734
68 >>> from lp.registry.interfaces.person import IPersonSet35 >>> from lp.registry.interfaces.person import IPersonSet
@@ -107,89 +74,6 @@
107 ... pub, legal_archs, hoary, pas_verify)74 ... pub, legal_archs, hoary, pas_verify)
108 ... print_architectures(allowed_architectures)75 ... print_architectures(allowed_architectures)
10976
110 >>> print_build_architectures(pub_all)
111 i386
112
113 >>> print_build_architectures(pub_any)
114 hppa
115 i386
116
117 >>> print_build_architectures(pub_three)
118 hppa
119 i386
120
121 >>> print_build_architectures(pub_one)
122 hppa
123
124If an architecture is disabled for some reason, then the results from
125determineArchitecturesToBuild() will not include it.
126
127 >>> hoary['hppa'].enabled = False
128
129 >>> print_build_architectures(pub_three)
130 i386
131
132Re-enable it before continuing:
133 >>> hoary['hppa'].enabled = True
134
135
136== Check support for kernel notation in architecture hint list ==
137
138dpkg supports the use of the '<kernel-><arch>' notation in the
139'Architecture' field, where 'kernel-' is one of the kernel platform
140available in debian systems: ['linux-', 'kfreebsd', 'hurd-', 'any-']
141
142See bug 73761 and http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=268709
143for further information about this dpkg feature.
144
145Soyuz will consider only 'any-' and 'linux-' elements as the
146corresponding architecture, since only linux is supported in Ubuntu.
147
148 >>> print_build_architectures(pub_any_foo)
149 hppa
150
151 >>> print_build_architectures(pub_linux_foo)
152 i386
153
154 >>> print_build_architectures(pub_linux_any)
155 hppa
156 i386
157
158
159== PPA architectures ==
160
161For virtualized archives only architectures with established support for
162PPA will be considered when creating PPA builds. See distroarchseries.txt
163for further information.
164
165 >>> ppa_architectures = [
166 ... arch for arch in hoary.architectures if arch.supports_virtualized]
167 >>> print_architectures(ppa_architectures)
168 i386
169
170 >>> print_build_architectures(pub_ppa)
171 i386
172
173Conversely, for non-virtual archives, build records are created for all
174architectures supported for the distroseries.
175
176 >>> LaunchpadZopelessLayer.switchDbUser("launchpad")
177 >>> pub_ppa.archive.require_virtualized = False
178 >>> commit()
179 >>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
180
181 >>> print_build_architectures(pub_ppa)
182 hppa
183 i386
184
185Revert the PPA changes.
186
187 >>> LaunchpadZopelessLayer.switchDbUser("launchpad")
188 >>> pub_ppa.archive.require_virtualized = True
189 >>> commit()
190 >>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
191
192
193=== Source PAS ===77=== Source PAS ===
19478
195Source PAS lines are the ones starting with '%' followed by the source79Source PAS lines are the ones starting with '%' followed by the source
19680
=== modified file 'lib/lp/soyuz/pas.py'
--- lib/lp/soyuz/pas.py 2010-10-06 11:46:51 +0000
+++ lib/lp/soyuz/pas.py 2010-12-08 13:37:07 +0000
@@ -167,23 +167,30 @@
167 legal_arch_tags = set(167 legal_arch_tags = set(
168 arch.architecturetag for arch in legal_archseries if arch.enabled)168 arch.architecturetag for arch in legal_archseries if arch.enabled)
169169
170 # We need to support arch tags like any-foo and linux-foo, so remove170 hint_archs = set(hint_string.split())
171 # supported kernel prefixes, Also allow linux-any but not any-any.171
172 # See bugs #73761 and #605002.172 # If a *-any architecture wildcard is present, build for everything
173 if hint_string in ['any', 'linux-any']:173 # we can. We only support Linux-based architectures at the moment,
174 # and any-any isn't a valid wildcard. See bug #605002.
175 if hint_archs.intersection(('any', 'linux-any')):
174 package_tags = legal_arch_tags176 package_tags = legal_arch_tags
175 elif hint_string == 'all':
176 nominated_arch = distroseries.nominatedarchindep
177 legal_archseries_ids = [arch.id for arch in legal_archseries]
178 assert nominated_arch.id in legal_archseries_ids, (
179 'nominatedarchindep is not present in legal_archseries: %s' %
180 ' '.join(legal_arch_tags))
181 package_tags = set([nominated_arch.architecturetag])
182 else:177 else:
183 my_archs = hint_string.split()178 # We need to support arch tags like any-foo and linux-foo, so remove
184 for kernel in ['linux', 'any']:179 # supported kernel prefixes. See bug #73761.
185 my_archs = [arch.replace("%s-" % kernel, "") for arch in my_archs]180 stripped_archs = hint_archs
186 package_tags = set(my_archs).intersection(legal_arch_tags)181 for kernel in ('linux', 'any'):
182 stripped_archs = set(
183 arch.replace("%s-" % kernel, "") for arch in stripped_archs)
184 package_tags = stripped_archs.intersection(legal_arch_tags)
185
186 # 'all' is only used as a last resort, to create an arch-indep
187 # build where no builds would otherwise exist.
188 if len(package_tags) == 0 and 'all' in hint_archs:
189 nominated_arch = distroseries.nominatedarchindep
190 assert nominated_arch in legal_archseries, (
191 'nominatedarchindep is not present in legal_archseries: %s' %
192 ' '.join(legal_arch_tags))
193 package_tags = set([nominated_arch.architecturetag])
187194
188 if pas_verify:195 if pas_verify:
189 build_tags = set()196 build_tags = set()
190197
=== added file 'lib/lp/soyuz/tests/test_pas.py'
--- lib/lp/soyuz/tests/test_pas.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_pas.py 2010-12-08 13:37:07 +0000
@@ -0,0 +1,99 @@
1# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4from canonical.testing.layers import LaunchpadZopelessLayer
5from lp.soyuz.pas import determineArchitecturesToBuild
6from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
7from lp.testing import TestCaseWithFactory
8
9
10class TestDetermineArchitecturesToBuild(TestCaseWithFactory):
11 """Test that determineArchitecturesToBuild correctly interprets hints."""
12
13 layer = LaunchpadZopelessLayer
14
15 def setUp(self):
16 super(TestDetermineArchitecturesToBuild, self).setUp()
17 self.publisher = SoyuzTestPublisher()
18 self.publisher.prepareBreezyAutotest()
19 self.publisher.addFakeChroots()
20
21 def assertArchsForHint(self, hint_string, expected_arch_tags):
22 """Assert that the given hint resolves to the expected archtags."""
23 pub = self.publisher.getPubSource(architecturehintlist=hint_string)
24 architectures = determineArchitecturesToBuild(
25 pub, self.publisher.breezy_autotest.architectures,
26 self.publisher.breezy_autotest)
27 self.assertEqual(
28 expected_arch_tags, [a.architecturetag for a in architectures])
29
30 def test_single_architecture(self):
31 # A hint string with a single arch resolves to just that arch.
32 self.assertArchsForHint('hppa', ['hppa'])
33
34 def test_three_architectures(self):
35 # A hint string with multiple archs resolves to just those
36 # archs.
37 self.assertArchsForHint('amd64 i386 hppa', ['hppa', 'i386'])
38
39 def test_independent(self):
40 # 'all' is special, meaning just a single build. The
41 # nominatedarchindep architecture is used -- in this case i386.
42 self.assertArchsForHint('all', ['i386'])
43
44 def test_one_and_independent(self):
45 # 'all' is redundant if we have another build anyway.
46 self.assertArchsForHint('hppa all', ['hppa'])
47
48 def test_fictional_and_independent(self):
49 # But 'all' is useful if present with an arch that wouldn't
50 # generate a build.
51 self.assertArchsForHint('foo all', ['i386'])
52
53 def test_wildcard(self):
54 # 'any' is a wildcard that matches all available archs.
55 self.assertArchsForHint('any', ['hppa', 'i386'])
56
57 def test_kernel_specific_architecture(self):
58 # Since we only support Linux-based architectures, 'linux-foo'
59 # is treated the same as 'foo'.
60 self.assertArchsForHint('linux-hppa', ['hppa'])
61
62 def test_unknown_kernel_specific_architecture(self):
63 # Non-Linux architectures aren't supported.
64 self.assertArchsForHint('kfreebsd-hppa', [])
65
66 def test_kernel_wildcard_architecture(self):
67 # Wildcards work for kernels: 'any-foo' is treated like 'foo'.
68 self.assertArchsForHint('any-hppa', ['hppa'])
69
70 def test_kernel_specific_architecture_wildcard(self):
71 # Wildcards work for archs too: 'linux-any' is treated like 'any'.
72 self.assertArchsForHint('linux-any', ['hppa', 'i386'])
73
74 def test_unknown_kernel_specific_architecture_wildcard(self):
75 # But unknown kernels continue to result in nothing.
76 self.assertArchsForHint('kfreebsd-any', [])
77
78 def test_wildcard_and_independent(self):
79 # 'all' continues to be ignored alongside a valid wildcard.
80 self.assertArchsForHint('all linux-any', ['hppa', 'i386'])
81
82 def test_kernel_independent_is_invalid(self):
83 # 'linux-all' isn't supported.
84 self.assertArchsForHint('linux-all', [])
85
86 def test_double_wildcard_is_invalid(self):
87 # 'any-any' is invalid; you want 'any'.
88 self.assertArchsForHint('any-any', [])
89
90 def test_disabled_architectures_omitted(self):
91 # Disabled architectures are not buildable, so are excluded.
92 self.publisher.breezy_autotest['hppa'].enabled = False
93 self.assertArchsForHint('any', ['i386'])
94
95 def test_virtualized_archives_have_only_virtualized_archs(self):
96 # For archives which must build on virtual builders, only
97 # virtual archs are returned.
98 self.publisher.breezy_autotest.main_archive.require_virtualized = True
99 self.assertArchsForHint('any', ['i386'])