launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #08336
[Merge] lp:~cjwatson/launchpad/pas-arm into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/pas-arm into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #917708 in Launchpad itself: "Launchpad does not recognize Arch = any-arm"
https://bugs.launchpad.net/launchpad/+bug/917708
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/pas-arm/+merge/107966
== Summary ==
Bug 917708 reports that the "any-arm" wildcard is not recognised in packages' Architecture fields.
== Proposed fix ==
Use dpkg-architecture to match architecture wildcards rather than doing an incomplete NIH job.
== Implementation details ==
Launchpad does its own parsing of architecture wildcards, but it does an incomplete job; it has misunderstood the second field of an any-* wildcard as being like an architecture name, whereas actually it's a canonicalised CPU name: these are almost equivalent, but not quite. The problem reported here is a perfect example of where they aren't equivalent.
Doing a more complete job of this in the framework of Launchpad's hand-rolled parser would involve either (a) a grotty accretion of special cases or (b) parsing dpkg-internal files such as /usr/share/dpkg/triplettable and /usr/share/dpkg/cputable. Really, though, it should delegate this task to the packaging system, which knows how to do it. Unfortunately the only public interfaces to this are by way of dpkg-architecture subprocess execution or a Perl module; but the product of the architectures supported by Launchpad and the set of wildcards in use is never going to be particularly large, so a reasonably economical way to approach this is just to cache the result of calling dpkg-architecture for every (architecture, wildcard) pair.
To restore the balance of the LoC force, I disassembled package-arch-specific.txt and merged it into test_pas.py. doctests--
== Tests ==
bin/test -vvct test_pas
== Demo and Q/A ==
I'm not sure it's possible to demo the fix as such, since there are no ARM builders on dogfood. To avoid trivial embarrassment, though, it might be worth uploading an any-i386 package to dogfood and making sure that that still gets scheduled for building on i386.
--
https://code.launchpad.net/~cjwatson/launchpad/pas-arm/+merge/107966
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/pas-arm into lp:launchpad.
=== removed file 'lib/lp/soyuz/doc/package-arch-specific.txt'
--- lib/lp/soyuz/doc/package-arch-specific.txt 2012-01-20 15:42:44 +0000
+++ lib/lp/soyuz/doc/package-arch-specific.txt 1970-01-01 00:00:00 +0000
@@ -1,271 +0,0 @@
-= Package Architecture Specific =
-
-The Package-Architecture-Specific (PAS) module is a parser to a set
-of restrictions to build packages based on archive-admin experiences.
-
-Those restrictions overlap the metadata information from the source
-packages (architecturehintlist).
-
-For testing PAS we will create a set of publications using
-`SoyuzTestPublisher`.
-
- >>> from lp.registry.interfaces.distribution import (
- ... IDistributionSet)
- >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
- >>> hoary = ubuntu.getSeries('hoary')
-
- >>> from lp.soyuz.tests.test_publishing import (
- ... SoyuzTestPublisher)
- >>> from lp.testing.dbuser import (
- ... lp_dbuser,
- ... switch_dbuser,
- ... )
-
-Publication will be added as 'launchpad' DB user.
-
- >>> switch_dbuser("launchpad")
-
- >>> test_publisher = SoyuzTestPublisher()
- >>> ignore = test_publisher.setUpDefaultDistroSeries(hoary)
- >>> test_publisher.addFakeChroots()
-
- >>> pub_three = test_publisher.getPubSource(
- ... sourcename='test-buildd-3', version='669',
- ... architecturehintlist="i386 hppa amd64")
-
-Create a PPA source publication.
-
- >>> from lp.registry.interfaces.person import IPersonSet
- >>> cprov = getUtility(IPersonSet).getByName('cprov')
-
- >>> pub_ppa = test_publisher.getPubSource(
- ... sourcename='test-ppa', version='675',
- ... architecturehintlist="i386 hppa",
- ... archive=cprov.archive)
-
-Good, all done, we can commit the publications and continue the tests
-with the buildmaster DB user.
-
- >>> switch_dbuser(test_dbuser)
-
-
-== Check the architectures to build ==
-
-Hoary has only 'hppa' and 'i386' architectures.
-
- >>> legal_archs = set(hoary.architectures)
-
- >>> def print_architectures(architectures):
- ... arch_tags = [arch.architecturetag for arch in architectures]
- ... for tag in sorted(arch_tags):
- ... print tag
-
- >>> print_architectures(legal_archs)
- hppa
- i386
-
-See if the code which determines archs to build does the right thing for
-each of these options:
-
- >>> from lp.soyuz.pas import (
- ... BuildDaemonPackagesArchSpecific, determineArchitecturesToBuild)
-
- >>> def print_build_architectures(pub, pas_verify=None):
- ... allowed_architectures = determineArchitecturesToBuild(
- ... pub, legal_archs, hoary, pas_verify)
- ... print_architectures(allowed_architectures)
-
-=== Source PAS ===
-
-Source PAS lines are the ones starting with '%' followed by the source
-package name, colon and then a list of architecture tags separated by
-space.
-
-Create a harness that lets us easily test PAS statements:
-
- >>> import os
- >>> import tempfile
- >>> import shutil
-
- >>> def getPASVerifier(pas_string):
- ... """Build and return a PAS verifier based on the string provided."""
- ... temp_dir = tempfile.mkdtemp()
- ... pas_filename = os.path.join(temp_dir, "Packages-arch-specific")
- ... pas_file = open(pas_filename, "w")
- ... pas_file.write(pas_string)
- ... pas_file.close()
- ... pas_verify = BuildDaemonPackagesArchSpecific(temp_dir, hoary)
- ... shutil.rmtree(temp_dir)
- ... return pas_verify
-
-Normally, 'pub_three' would be built on all available architectures in
-hoary.
-
- >>> print_build_architectures(pub_three)
- hppa
- i386
-
-But it it can be 'temporarily' restricted to build only on 'i386' via
-PAS.
-
- >>> pas_verify = getPASVerifier("%test-buildd-3: i386")
- >>> print_build_architectures(pub_three, pas_verify)
- i386
-
-Or even restricted to not be built in any architecture.
-
- >>> pas_verify = getPASVerifier("%test-buildd-3: sparc")
- >>> print_build_architectures(pub_three, pas_verify)
-
-PAS can also be used for excluding specific architectures.
-
- >>> pas_verify = getPASVerifier("%test-buildd-3: !i386")
- >>> print_build_architectures(pub_three, pas_verify)
- hppa
-
-PPA builds are not affected by PAS restrictions, i.e., they will
-build for all requested architectures currently supported in the PPA
-subsystem.
-
- >>> pas_verify = getPASVerifier("%test-ppa: hppa")
- >>> print_build_architectures(pub_ppa, pas_verify)
- i386
-
- >>> pas_verify = getPASVerifier("%test-ppa: !i386")
- >>> print_build_architectures(pub_ppa, pas_verify)
- i386
-
-
-== Binary PAS ==
-
-Binary PAS lines are the ones which does not start with '%'. They
-contain binary package name, colon and then a list of architecture
-tags separated by space.
-
-Binary PAS lines work as a shortcut to the source when they produce
-only a single binary. When the binary mentioned is part of a
-collection of binaries produced by the same source the architecture
-restriction does not make sense anymore. See more information about
-this aspect below.
-
-To check binary PAS listings we'll use a source publication for which
-produces a single binary.
-
- >>> from lp.soyuz.enums import (
- ... PackagePublishingStatus)
-
- >>> with lp_dbuser():
- ... pub_single = test_publisher.getPubSource(
- ... sourcename='single', version='1.0',
- ... architecturehintlist="any")
- ... binaries = test_publisher.getPubBinaries(
- ... binaryname='single-bin', pub_source=pub_single,
- ... status=PackagePublishingStatus.PUBLISHED)
-
- >>> len(set(pub.binarypackagerelease.name
- ... for pub in pub_single.getPublishedBinaries()))
- 1
-
-Normally the source would be built in all the available architectures
-in hoary.
-
- >>> print_build_architectures(pub_single)
- hppa
- i386
-
-The source building does not get affect by an unrelated binary PAS line.
-
- >>> pas_verify = getPASVerifier("boing: i386")
- >>> print_build_architectures(pub_single, pas_verify)
- hppa
- i386
-
-Using PAS, we can restrict the building architectures by tagging the
-produced binary with a specific list of allowed architectures.
-
- >>> pas_verify = getPASVerifier("single-bin: i386 sparc")
- >>> print_build_architectures(pub_single, pas_verify)
- i386
-
-It's also possible to only block specific architectures.
-
- >>> pas_verify = getPASVerifier("single-bin: !hppa")
- >>> print_build_architectures(pub_single, pas_verify)
- i386
-
-Although it's not possible to block the build on the
-'nominatedarchindep' architecture via a binary PAS line. The reason
-for that is the fact the architecture independent binaries are only
-built in i386, if it gets blacklisted those binaries won't be
-built. This would never be a legitimate use-case.
-
- >>> pas_verify = getPASVerifier("single-bin: !i386 !hppa")
- >>> print_build_architectures(pub_single, pas_verify)
- i386
-
-Binary PAS lines are ignored for PPAs as well. We create a binary for
-the existing test PPA source publication.
-
- >>> with lp_dbuser():
- ... pub_ppa.archive.require_virtualized = False
- ... binaries = test_publisher.getPubBinaries(
- ... binaryname='ppa-bin', pub_source=pub_ppa,
- ... status=PackagePublishingStatus.PUBLISHED)
-
-And it will build in the same architectures with or without a
-corresponding PAS binary line.
-
- >>> print_build_architectures(pub_ppa)
- hppa
- i386
-
- >>> pas_verify = getPASVerifier("ppa-bin: !hppa")
- >>> print_build_architectures(pub_single, pas_verify)
- hppa
- i386
-
-As mentioned above, PAS binary lines referring to binary packages for
-which the source produce other binaries are completely ignored. Other
-tools use that information but we can't restrict builds in this
-circumstances.
-
-We will create a 'multiple' source publication build two binaries,
-'bin-one' and 'bin-two'.
-
- >>> with lp_dbuser():
- ... pub_multiple = test_publisher.getPubSource(
- ... sourcename='multiple', version='1.1',
- ... architecturehintlist="any")
- ... for build in pub_multiple.createMissingBuilds():
- ... bin_one = test_publisher.uploadBinaryForBuild(
- ... build, 'bin-one')
- ... pub_bin_one = test_publisher.publishBinaryInArchive(
- ... bin_one, pub_multiple.archive,
- ... status=PackagePublishingStatus.PUBLISHED)
- ... bin_two = test_publisher.uploadBinaryForBuild(
- ... build, 'bin-two')
- ... pub_bin_two = test_publisher.publishBinaryInArchive(
- ... bin_two, pub_multiple.archive,
- ... status=PackagePublishingStatus.PUBLISHED)
-
- >>> len(set(pub.binarypackagerelease.name
- ... for pub in pub_multiple.getPublishedBinaries()))
- 2
-
-Any attempt to restrict the building architectures on 'multiple'
-source via its binaries will be ignored and it will continue to be
-built for all available architectures.
-
- >>> print_build_architectures(pub_multiple)
- hppa
- i386
-
- >>> pas_verify = getPASVerifier("bin-one: i386 sparc")
- >>> print_build_architectures(pub_multiple, pas_verify)
- hppa
- i386
-
- >>> pas_verify = getPASVerifier("bin-two: !hppa")
- >>> print_build_architectures(pub_multiple, pas_verify)
- hppa
- i386
=== modified file 'lib/lp/soyuz/pas.py'
--- lib/lp/soyuz/pas.py 2011-01-13 00:45:18 +0000
+++ lib/lp/soyuz/pas.py 2012-05-30 12:52:24 +0000
@@ -1,8 +1,9 @@
-# Copyright 2009 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
import operator
import os
+import subprocess
from sqlobject import SQLObjectNotFound
@@ -109,6 +110,29 @@
return source_name, arch_tags
+class DpkgArchitectureCache:
+ """Cache the results of asking questions of dpkg-architecture."""
+
+ def __init__(self):
+ self._matches = {}
+
+ def match(self, arch, wildcard):
+ if (arch, wildcard) not in self._matches:
+ command = ["dpkg-architecture", "-i%s" % wildcard]
+ env = dict(os.environ)
+ env["DEB_HOST_ARCH"] = arch
+ ret = (subprocess.call(command, env=env) == 0)
+ self._matches[(arch, wildcard)] = ret
+ return self._matches[(arch, wildcard)]
+
+ def findAllMatches(self, arches, wildcards):
+ return [arch for arch in arches for wildcard in wildcards
+ if self.match(arch, wildcard)]
+
+
+dpkg_architecture = DpkgArchitectureCache()
+
+
def determineArchitecturesToBuild(pubrec, legal_archseries,
distroseries, pas_verify=None):
"""Return a list of architectures for which this publication should build.
@@ -168,29 +192,17 @@
arch.architecturetag for arch in legal_archseries if arch.enabled)
hint_archs = set(hint_string.split())
-
- # If a *-any architecture wildcard is present, build for everything
- # we can. We only support Linux-based architectures at the moment,
- # and any-any isn't a valid wildcard. See bug #605002.
- if hint_archs.intersection(('any', 'linux-any')):
- package_tags = legal_arch_tags
- else:
- # We need to support arch tags like any-foo and linux-foo, so remove
- # supported kernel prefixes. See bug #73761.
- stripped_archs = hint_archs
- for kernel in ('linux', 'any'):
- stripped_archs = set(
- arch.replace("%s-" % kernel, "") for arch in stripped_archs)
- package_tags = stripped_archs.intersection(legal_arch_tags)
-
- # 'all' is only used as a last resort, to create an arch-indep
- # build where no builds would otherwise exist.
- if len(package_tags) == 0 and 'all' in hint_archs:
- nominated_arch = distroseries.nominatedarchindep
- if nominated_arch in legal_archseries:
- package_tags = set([nominated_arch.architecturetag])
- else:
- package_tags = set()
+ package_tags = set(dpkg_architecture.findAllMatches(
+ legal_arch_tags, hint_archs))
+
+ # 'all' is only used as a last resort, to create an arch-indep build
+ # where no builds would otherwise exist.
+ if len(package_tags) == 0 and 'all' in hint_archs:
+ nominated_arch = distroseries.nominatedarchindep
+ if nominated_arch in legal_archseries:
+ package_tags = set([nominated_arch.architecturetag])
+ else:
+ package_tags = set()
if pas_verify:
build_tags = set()
=== modified file 'lib/lp/soyuz/tests/test_doc.py'
--- lib/lp/soyuz/tests/test_doc.py 2012-05-25 13:26:08 +0000
+++ lib/lp/soyuz/tests/test_doc.py 2012-05-30 12:52:24 +0000
@@ -157,11 +157,6 @@
setUp=manageChrootSetup,
layer=LaunchpadZopelessLayer,
),
- 'package-arch-specific.txt': LayeredDocFileSuite(
- '../doc/package-arch-specific.txt',
- setUp=builddmasterSetUp,
- layer=LaunchpadZopelessLayer,
- ),
'queuebuilder.txt': LayeredDocFileSuite(
'../doc/queuebuilder.txt',
setUp=builddmasterSetUp,
=== modified file 'lib/lp/soyuz/tests/test_pas.py'
--- lib/lp/soyuz/tests/test_pas.py 2012-01-01 02:58:52 +0000
+++ lib/lp/soyuz/tests/test_pas.py 2012-05-30 12:52:24 +0000
@@ -1,7 +1,17 @@
-# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
-from lp.soyuz.pas import determineArchitecturesToBuild
+import os
+
+from lp.soyuz.enums import (
+ ArchivePurpose,
+ PackagePublishingStatus,
+ )
+from lp.soyuz.model.processor import ProcessorFamily
+from lp.soyuz.pas import (
+ BuildDaemonPackagesArchSpecific,
+ determineArchitecturesToBuild,
+ )
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import TestCaseWithFactory
from lp.testing.layers import LaunchpadZopelessLayer
@@ -16,23 +26,51 @@
super(TestDetermineArchitecturesToBuild, self).setUp()
self.publisher = SoyuzTestPublisher()
self.publisher.prepareBreezyAutotest()
+ armel_family = ProcessorFamily.get(5)
+ if not armel_family.processors:
+ armel_family.addProcessor('armel', 'armel', 'armel')
+ self.publisher.breezy_autotest.newArch(
+ 'armel', armel_family, False, self.publisher.person)
self.publisher.addFakeChroots()
- def assertArchsForHint(self, hint_string, expected_arch_tags,
- allowed_arch_tags=None):
- """Assert that the given hint resolves to the expected archtags."""
- pub = self.publisher.getPubSource(architecturehintlist=hint_string)
+ def getPASVerifier(self, pas_string):
+ """Build and return a PAS verifier based on the string provided."""
+ temp_dir = self.makeTemporaryDirectory()
+ pas_filename = os.path.join(temp_dir, "Packages-arch-specific")
+ with open(pas_filename, "w") as pas_file:
+ pas_file.write(pas_string)
+ pas_verify = BuildDaemonPackagesArchSpecific(
+ temp_dir, self.publisher.breezy_autotest)
+ return pas_verify
+
+ def assertArchitecturesToBuild(self, expected_arch_tags, pub,
+ allowed_arch_tags=None, pas_string=None):
if allowed_arch_tags is None:
allowed_archs = self.publisher.breezy_autotest.architectures
else:
allowed_archs = [
arch for arch in self.publisher.breezy_autotest.architectures
if arch.architecturetag in allowed_arch_tags]
+ if pas_string is None:
+ pas_verify = None
+ else:
+ pas_verify = self.getPASVerifier(pas_string)
architectures = determineArchitecturesToBuild(
- pub, allowed_archs, self.publisher.breezy_autotest)
- self.assertEqual(
+ pub, allowed_archs, self.publisher.breezy_autotest,
+ pas_verify=pas_verify)
+ self.assertContentEqual(
expected_arch_tags, [a.architecturetag for a in architectures])
+ def assertArchsForHint(self, hint_string, expected_arch_tags,
+ allowed_arch_tags=None, sourcename=None,
+ pas_string=None):
+ """Assert that the given hint resolves to the expected archtags."""
+ pub = self.publisher.getPubSource(
+ sourcename=sourcename, architecturehintlist=hint_string)
+ self.assertArchitecturesToBuild(
+ expected_arch_tags, pub, allowed_arch_tags=allowed_arch_tags,
+ pas_string=pas_string)
+
def test_single_architecture(self):
# A hint string with a single arch resolves to just that arch.
self.assertArchsForHint('hppa', ['hppa'])
@@ -58,7 +96,7 @@
def test_wildcard(self):
# 'any' is a wildcard that matches all available archs.
- self.assertArchsForHint('any', ['hppa', 'i386'])
+ self.assertArchsForHint('any', ['armel', 'hppa', 'i386'])
def test_kernel_specific_architecture(self):
# Since we only support Linux-based architectures, 'linux-foo'
@@ -73,9 +111,14 @@
# Wildcards work for kernels: 'any-foo' is treated like 'foo'.
self.assertArchsForHint('any-hppa', ['hppa'])
+ def test_kernel_wildcard_architecture_arm(self):
+ # The second part of a wildcard matches the canonical CPU name, not
+ # on the Debian architecture, so 'any-arm' matches 'armel'.
+ self.assertArchsForHint('any-arm', ['armel'])
+
def test_kernel_specific_architecture_wildcard(self):
# Wildcards work for archs too: 'linux-any' is treated like 'any'.
- self.assertArchsForHint('linux-any', ['hppa', 'i386'])
+ self.assertArchsForHint('linux-any', ['armel', 'hppa', 'i386'])
def test_unknown_kernel_specific_architecture_wildcard(self):
# But unknown kernels continue to result in nothing.
@@ -83,20 +126,21 @@
def test_wildcard_and_independent(self):
# 'all' continues to be ignored alongside a valid wildcard.
- self.assertArchsForHint('all linux-any', ['hppa', 'i386'])
+ self.assertArchsForHint('all linux-any', ['armel', 'hppa', 'i386'])
def test_kernel_independent_is_invalid(self):
# 'linux-all' isn't supported.
self.assertArchsForHint('linux-all', [])
- def test_double_wildcard_is_invalid(self):
- # 'any-any' is invalid; you want 'any'.
- self.assertArchsForHint('any-any', [])
+ def test_double_wildcard_is_same_as_single(self):
+ # 'any-any' is redundant with 'any', but dpkg-architecture supports
+ # it anyway.
+ self.assertArchsForHint('any-any', ['armel', 'hppa', 'i386'])
def test_disabled_architectures_omitted(self):
# Disabled architectures are not buildable, so are excluded.
self.publisher.breezy_autotest['hppa'].enabled = False
- self.assertArchsForHint('any', ['i386'])
+ self.assertArchsForHint('any', ['armel', 'i386'])
def test_virtualized_archives_have_only_virtualized_archs(self):
# For archives which must build on virtual builders, only
@@ -110,3 +154,128 @@
# i386) is omitted, no builds will be created for arch-indep
# sources.
self.assertArchsForHint('all', [], allowed_arch_tags=['hppa'])
+
+ def test_source_pas_defaults_to_all_available_architectures(self):
+ # Normally, a source package will be built on all available
+ # architectures in the series.
+ self.assertArchsForHint(
+ "i386 hppa amd64", ["hppa", "i386"], pas_string="")
+
+ def test_source_pas_can_restrict_to_one_architecture(self):
+ # A source package can be restricted to a single architecture via PAS.
+ self.assertArchsForHint(
+ "i386 hppa amd64", ["i386"], sourcename="test",
+ pas_string="%test: i386")
+
+ def test_source_pas_can_restrict_to_no_architectures(self):
+ # A source package can be restricted to not built on any architecture.
+ self.assertArchsForHint(
+ "i386 hppa amd64", [], sourcename="test",
+ pas_string="%test: sparc")
+
+ def test_source_pas_can_exclude_specific_architecture(self):
+ # A source PAS entry can exclude a specific architecture.
+ self.assertArchsForHint(
+ "i386 hppa amd64", ["hppa"], sourcename="test",
+ pas_string="%test: !i386")
+
+ def setUpPPAAndSource(self):
+ # Create a PPA and return a new source publication in it.
+ archive = self.factory.makeArchive(
+ distribution=self.publisher.ubuntutest, purpose=ArchivePurpose.PPA)
+ return self.publisher.getPubSource(
+ sourcename="test-ppa", architecturehintlist="i386 hppa",
+ archive=archive)
+
+ def test_source_pas_does_not_affect_ppa(self):
+ # PPA builds are not affected by source PAS restrictions; that is,
+ # they will build for all requested architectures currently
+ # supported in the PPA subsystem.
+ pub_ppa = self.setUpPPAAndSource()
+ self.assertArchitecturesToBuild(
+ ["i386"], pub_ppa, pas_string="%test-ppa: hppa")
+ self.assertArchitecturesToBuild(
+ ["i386"], pub_ppa, pas_string="%test-ppa: !i386")
+
+ def setUpSourceAndBinary(self):
+ # To check binary PAS listings we'll use a source publication which
+ # produces a single binary.
+ pub_single = self.publisher.getPubSource(
+ sourcename="single", architecturehintlist="any")
+ binaries = self.publisher.getPubBinaries(
+ binaryname="single-bin", pub_source=pub_single,
+ status=PackagePublishingStatus.PUBLISHED)
+ binary_names = set(
+ pub.binarypackagerelease.name
+ for pub in pub_single.getPublishedBinaries())
+ self.assertEqual(1, len(binary_names))
+ return pub_single, binaries
+
+ def test_binary_pas_unrelated_binary_lines_have_no_effect(self):
+ # Source packages are unaffected by an unrelated binary PAS line.
+ pub_single, binaries = self.setUpSourceAndBinary()
+ self.assertArchitecturesToBuild(
+ ["armel", "hppa", "i386"], pub_single, pas_string="boing: i386")
+
+ def test_binary_pas_can_restrict_architectures(self):
+ # A PAS entry can restrict the build architectures by tagging the
+ # produced binary with a list of allowed architectures.
+ pub_single, binaries = self.setUpSourceAndBinary()
+ self.assertArchitecturesToBuild(
+ ["i386"], pub_single, pas_string="single-bin: i386 sparc")
+
+ def test_binary_pas_can_exclude_specific_architecture(self):
+ # A binary PAS entry can exclude a specific architecture.
+ pub_single, binaries = self.setUpSourceAndBinary()
+ self.assertArchitecturesToBuild(
+ ["armel", "i386"], pub_single, pas_string="single-bin: !hppa")
+
+ def test_binary_pas_cannot_exclude_nominatedarchindep(self):
+ # A binary PAS entry cannot exclude the 'nominatedarchindep'
+ # architecture. Architecture-independent binaries are only built on
+ # nominatedarchindep; if that architecture is blacklisted, those
+ # binaries will never be built.
+ pub_single, binaries = self.setUpSourceAndBinary()
+ self.assertArchitecturesToBuild(
+ ["i386"], pub_single, pas_string="single-bin: !i386 !hppa !armel")
+
+ def test_binary_pas_does_not_affect_ppa(self):
+ # PPA builds are not affected by binary PAS restrictions.
+ pub_ppa = self.setUpPPAAndSource()
+ pub_ppa.archive.require_virtualized = False
+ self.publisher.getPubBinaries(
+ binaryname="ppa-bin", pub_source=pub_ppa,
+ status=PackagePublishingStatus.PUBLISHED)
+ self.assertArchitecturesToBuild(
+ ["hppa", "i386"], pub_ppa, pas_string="")
+ self.assertArchitecturesToBuild(
+ ["hppa", "i386"], pub_ppa, pas_string="ppa-bin: !hppa")
+
+ def test_binary_pas_does_not_affect_multi_binary_sources(self):
+ # Binary PAS entries referring to binary packages whose source
+ # produces other binaries are completely ignored. Other tools use
+ # that information, but we can't restrict builds in this
+ # circumstance.
+ pub_multiple = self.publisher.getPubSource(
+ sourcename="multiple", architecturehintlist="any")
+ for build in pub_multiple.createMissingBuilds():
+ bin_one = self.publisher.uploadBinaryForBuild(build, "bin-one")
+ self.publisher.publishBinaryInArchive(
+ bin_one, pub_multiple.archive,
+ status=PackagePublishingStatus.PUBLISHED)
+ bin_two = self.publisher.uploadBinaryForBuild(build, "bin-two")
+ self.publisher.publishBinaryInArchive(
+ bin_two, pub_multiple.archive,
+ status=PackagePublishingStatus.PUBLISHED)
+ binary_names = set(
+ pub.binarypackagerelease.name
+ for pub in pub_multiple.getPublishedBinaries())
+ self.assertEqual(2, len(binary_names))
+ self.assertArchitecturesToBuild(
+ ["armel", "hppa", "i386"], pub_multiple, pas_string="")
+ self.assertArchitecturesToBuild(
+ ["armel", "hppa", "i386"], pub_multiple,
+ pas_string="bin-one: i386 sparc")
+ self.assertArchitecturesToBuild(
+ ["armel", "hppa", "i386"], pub_multiple,
+ pas_string="bin-two: !hppa")
Follow ups