launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #02375
[Merge] lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-5 into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-5 into lp:launchpad with lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-4 as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-5/+merge/46852
Building on the work in https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-4/+merge/46535, this branch completely kills build-notification.txt moving it into unit tests.
I would like to apologise for the length of this branch, but I can't win if I'm deleting 634 lines of doctest.
--
https://code.launchpad.net/~stevenk/launchpad/bpb-currentcomponent-assertion-part-5/+merge/46852
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/bpb-currentcomponent-assertion-part-5 into lp:launchpad.
=== removed file 'lib/lp/soyuz/doc/build-notification.txt'
--- lib/lp/soyuz/doc/build-notification.txt 2011-01-12 23:07:40 +0000
+++ lib/lp/soyuz/doc/build-notification.txt 1970-01-01 00:00:00 +0000
@@ -1,629 +0,0 @@
-=========================
-Build Notification System
-=========================
-
-IBinaryPackageBuild instance implements the 'notify' method which sends
-a status report about the current record to the
-ISourcePackageRelease.creator and the package uploader's preferred email
-address.
-
-We rely on get_contact_email_addresses() to DTRT, either use the
-Team.contactaddress of the Launchpad Buildd Celebrity or the
-preferredemail of its members.
-
-The report is based on the emailtemplate/build-notification.txt.
-
-All build states are supported by the current implementation, however
-only failures should be reported this time.
-
- >>> from lp.soyuz.interfaces.binarypackagebuild import (
- ... IBinaryPackageBuildSet)
- >>> from lp.testing.mail_helpers import pop_notifications
- >>> buildset = getUtility(IBinaryPackageBuildSet)
-
-To avoid consequences of modified sampledata, specially if we add
-more builds for test we are going to pick a specific build record
-in a known state to perform the tests.
-
-Notification for a FAILEDTOBUILD (failed) build record:
-
- >>> failed_candidate = buildset.getByBuildID(9)
- >>> failed_candidate.source_package_release.name
- u'pmount'
- >>> failed_candidate.status.name
- 'FAILEDTOBUILD'
- >>> failed_candidate.source_package_release.creator.name
- u'mark'
-
- >>> failed_candidate.notify()
-
-Check how many email the system have sent:
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 3
-
-The members of launchpad-buildd-admins are notified:
-
- >>> notifications.pop(0)['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
- >>> notifications.pop(0)['To']
- 'foo.bar@xxxxxxxxxxxxx'
-
-The maintainer is notified:
-
- >>> build_notification = notifications.pop(0)
- >>> build_notification['To']
- 'mark@xxxxxxxxxxx'
-
-Checking subject and extra headers. Build notifications have a set of
-special headers to help filtering on users' mailboxes, they are:
-
- * X-Creator-Recipient: the creator email address which can be
- notified or not according a configuration parameter.
- * X-Launchpad-Build-{State, Component, Arch}: build record attributes
- * X-Launchpad-PPA: omitted if it's not a PPA build-notification,
- contains the PPA owner.name otherwise.
-
- >>> def dump_build_notification(notification):
- ... clean_subject = notification['Subject'].replace(
- ... '\n','').replace('\t', ' ')
- ... build_state = notification['X-Launchpad-Build-State']
- ... build_component = notification['X-Launchpad-Build-Component']
- ... build_arch = notification['X-Launchpad-Build-Arch']
- ... ppa_header = 'X-Launchpad-PPA' in notification.keys()
- ... print 'Subject:', clean_subject
- ... print 'X-Creator-Recipient:', notification['X-Creator-Recipient']
- ... print 'X-Launchpad-Build-State:', build_state
- ... print 'X-Launchpad-Build-Component:', build_component
- ... print 'X-Launchpad-Build-Arch:', build_arch
- ... if ppa_header:
- ... print 'X-Launchpad-PPA:', notification['X-Launchpad-PPA']
- ... else:
- ... print 'X-Launchpad-PPA: omitted'
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #9] i386 build of pmount 0.1-1 in ubuntu warty RELEASE
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: FAILEDTOBUILD
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: omitted
-
-Let's check the notification content. It should contain:
-
- * The source package name
- * The source package version
- * The build architecture
- * The build state
- * The duration of the build
- * A link to the build log
- * A link to the build page
- * A link to the source page
-
-This same basic content applies to all types of notification.
-
- >>> notification_body = build_notification.get_payload(decode=True)
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: pmount
- * Version: 0.1-1
- * Architecture: i386
- * Archive: ubuntu primary archive
- * Component: main
- * State: Failed to build
- * Duration: three minutes
- * Build Log: http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+buildjob/9/+files/netapplet-1.0.0.tar.gz
- * Builder: http://launchpad.dev/builders/bob
- * Source: http://launchpad.dev/ubuntu/+source/pmount/0.1-1
- <BLANKLINE>
- <BLANKLINE>
- <BLANKLINE>
- If you want further information about this situation, feel free to
- contact a member of the Launchpad Buildd Administrators team.
- <BLANKLINE>
- --
- i386 build of pmount 0.1-1 in ubuntu warty RELEASE
- http://launchpad.dev/ubuntu/+source/pmount/0.1-1/+buildjob/9
- <BLANKLINE>
-
-Notification for a pending (NEEDSBUILD) build record:
-
- >>> pending_candidate = buildset.getByBuildID(11)
- >>> pending_candidate.source_package_release.name
- u'alsa-utils'
- >>> pending_candidate.status.name
- 'NEEDSBUILD'
- >>> pending_candidate.source_package_release.creator.name
- u'mark'
-
- >>> pending_candidate.notify()
-
-Check how many email the system have sent:
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 3
-
-The members of launchpad-buildd-admins are notified:
-
- >>> notifications.pop(0)['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
- >>> notifications.pop(0)['To']
- 'foo.bar@xxxxxxxxxxxxx'
-
-The maintainer is notified:
-
- >>> build_notification = notifications.pop(0)
- >>> build_notification['To']
- 'mark@xxxxxxxxxxx'
-
-Checking subject and extra headers:
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #11] i386 build of alsa-utils 1.0.9a-4ubuntu1 in ubuntu hoary RELEASE
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: NEEDSBUILD
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: omitted
-
-Check the notification content:
-
- >>> notification_body = build_notification.get_payload()
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: alsa-utils
- * Version: 1.0.9a-4ubuntu1
- * Architecture: i386
- * Archive: ubuntu primary archive
- * Component: main
- * State: Needs building
- * Duration: not available
- * Build Log: not available
- * Builder: not available
- * Source: http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1
- <BLANKLINE>
- <BLANKLINE>
- <BLANKLINE>
- If you want further information about this situation, feel free to
- contact a member of the Launchpad Buildd Administrators team.
- <BLANKLINE>
- --
- i386 build of alsa-utils 1.0.9a-4ubuntu1 in ubuntu hoary RELEASE
- http://launchpad.dev/ubuntu/+source/alsa-utils/1.0.9a-4ubuntu1/+buildjob/11
- <BLANKLINE>
-
-Notification for a BUILDING build record:
-
- >>> building_candidate = buildset.getByBuildID(8)
- >>> building_candidate.source_package_release.name
- u'mozilla-firefox'
- >>> building_candidate.status.name
- 'BUILDING'
- >>> building_candidate.source_package_release.creator.name
- u'mark'
-
- >>> building_candidate.notify()
-
-Check how many email the system have sent:
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 3
-
-The members of launchpad-buildd-admins are notified:
-
- >>> notifications.pop(0)['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
- >>> notifications.pop(0)['To']
- 'foo.bar@xxxxxxxxxxxxx'
-
-The maintainer is notified:
-
- >>> build_notification = notifications.pop(0)
- >>> build_notification['To']
- 'mark@xxxxxxxxxxx'
-
-Checking subject and extra headers:
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #8] i386 build of mozilla-firefox 0.9 in ubuntu hoary RELEASE
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: BUILDING
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: omitted
-
-Check the notification content:
-
- >>> notification_body = build_notification.get_payload()
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: mozilla-firefox
- * Version: 0.9
- * Architecture: i386
- * Archive: ubuntu primary archive
- * Component: main
- * State: Currently building
- * Duration: not finished
- * Build Log: see builder page
- * Builder: http://launchpad.dev/builders/bob
- * Source: http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9
- <BLANKLINE>
- <BLANKLINE>
- <BLANKLINE>
- If you want further information about this situation, feel free to
- contact a member of the Launchpad Buildd Administrators team.
- <BLANKLINE>
- --
- i386 build of mozilla-firefox 0.9 in ubuntu hoary RELEASE
- http://launchpad.dev/ubuntu/+source/mozilla-firefox/0.9/+buildjob/8
- <BLANKLINE>
-
-Notification for a SUPERSEDED build record:
-
- >>> superseded_candidate = buildset.getByBuildID(15)
- >>> superseded_candidate.source_package_release.name
- u'at'
- >>> superseded_candidate.status.name
- 'SUPERSEDED'
- >>> superseded_candidate.source_package_release.creator.name
- u'mark'
-
- >>> superseded_candidate.notify()
-
-Check how many email the system have sent:
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 3
-
-The members of launchpad-buildd-admins are notified:
-
- >>> notifications.pop(0)['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
- >>> notifications.pop(0)['To']
- 'foo.bar@xxxxxxxxxxxxx'
-
-The maintainer is notified:
-
- >>> build_notification = notifications.pop(0)
- >>> build_notification['To']
- 'mark@xxxxxxxxxxx'
-
-Checking subject and extra headers:
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #15] i386 build of at 0.00 in ubuntu warty RELEASE
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: SUPERSEDED
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: omitted
-
-Check the notification content:
-
- >>> notification_body = build_notification.get_payload()
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: at
- * Version: 0.00
- * Architecture: i386
- * Archive: ubuntu primary archive
- * Component: main
- * State: Build for superseded Source
- * Duration: not available
- * Build Log: not available
- * Builder: not available
- * Source: http://launchpad.dev/ubuntu/+source/at/0.00
- <BLANKLINE>
- <BLANKLINE>
- <BLANKLINE>
- If you want further information about this situation, feel free to
- contact a member of the Launchpad Buildd Administrators team.
- <BLANKLINE>
- --
- i386 build of at 0.00 in ubuntu warty RELEASE
- http://launchpad.dev/ubuntu/+source/at/0.00/+buildjob/15
- <BLANKLINE>
-
-Check if the 'build_notification' configuration option really suppress
-notification as promised:
-
- >>> from canonical.config import config
- >>> send_build_notification = """
- ... [builddmaster]
- ... send_build_notification: False
- ... """
- >>> config.push('send_build_notification', send_build_notification)
- >>> superseeded_candidate = buildset.getByBuildID(15)
- >>> superseeded_candidate.notify()
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 0
-
- >>> config_data = config.pop('send_build_notification')
-
-Check if 'notify_owner' config option really suppress email to
-the SPR owner, but still sending it to the default recipient:
-
- >>> notify_owner = """
- ... [builddmaster]
- ... send_build_notification: True
- ... notify_owner: False
- ... """
- >>> config.push('notify_owner', notify_owner)
- >>> superseded_candidate = buildset.getByBuildID(15)
-
- >>> superseded_candidate.notify()
-
-Check how many email the system have sent:
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 2
-
-Only the members of launchpad-buildd-admins are notified:
-
- >>> notifications.pop(0)['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
- >>> notifications.pop(0)['To']
- 'foo.bar@xxxxxxxxxxxxx'
-
-Checking subject and extra headers:
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #15] i386 build of at 0.00 in ubuntu warty RELEASE
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: SUPERSEDED
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: omitted
-
-Just to keep the config sane, as it was before:
-
- >>> config_data = config.pop('notify_owner')
-
-
-PPA build notifications
-=======================
-
-As for the normal (main archive) build candidates we are also able
-send notification about current (changed) PPA build record status.
-
-PPA build notifications should be as much as possible similar to those
-in the main archive, the important differences are:
-
- * We do not include 'buildd-admins' celebrity in its recipients,
- instead we include the Archive owner;
-
- * We try to be explicit in the subject and in the body of the message
- that it is about a PPA build candidate;
-
- * We don't have a 'source package' page for PPA sources.
-
- * We only warn the uploader (person specified in 'Changed-By'
- changesfile) and the signer (person who owns the GPG key used to
- sign the package) if the package was not copied. Additionally,
- the Changed-By person is only notified if they are the PPA owner or
- they are in the team owning the PPA (to avoid spamming the innocent
- when PPA users upload unchanged source packages).
-
- >>> from lp.registry.interfaces.person import IPersonSet
- >>> cprov = getUtility(IPersonSet).getByName('cprov')
-
- >>> from lp.buildmaster.enums import BuildStatus
- >>> failed_candidate = cprov.archive.getBuildRecords(
- ... build_state=BuildStatus.FAILEDTOBUILD, name='cdrkit')[0]
-
- >>> failed_candidate.notify()
-
-Was this package copied?
-
- >>> (failed_candidate.archive !=
- ... failed_candidate.source_package_release.upload_archive)
- True
-
-Since the package *was* copied, only the owner of the destination
-archive will get notified.
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 1
-
-Checking the message contents:
-
- >>> build_notification = notifications.pop(0)
- >>> notification_body = build_notification.get_payload(decode=True)
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: cdrkit
- * Version: 1.0
- * Architecture: i386
- * Archive: cprov PPA
- * Component: main
- * State: Failed to build
- * Duration: a minute
- * Build Log: http://launchpad.dev/~cprov/+archive/ppa/+buildjob/26/+files/netapplet-1.0.0.tar.gz
- * Builder: http://launchpad.dev/builders/bob
- * Source: not available
- ...
-
-The notification went to the PPA owner.
-
- >>> build_notification['To']
- 'celso.providelo@xxxxxxxxxxxxx'
-
-Checking subject and extra headers:
-
- >>> dump_build_notification(build_notification)
- Subject: [Build #26] i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE (cprov PPA)
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: FAILEDTOBUILD
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: cprov
-
-In order to test build notifications for sources that were not copied,
-we will change the 'failed_candidate' source, setting its
-'upload_archive' to the same archive was built, Celso's PPA.
-
- >>> from canonical.database.sqlbase import commit
- >>> from canonical.testing.layers import LaunchpadZopelessLayer
-
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
-
- >>> from zope.security.proxy import removeSecurityProxy
- >>> naked_candidate = removeSecurityProxy(failed_candidate)
- >>> naked_sourcepackagerelease = naked_candidate.source_package_release
- >>> naked_sourcepackagerelease.upload_archive = failed_candidate.archive
-
-We also make 'Foo Bar' the source signer.
-
- >>> from lp.registry.interfaces.gpg import IGPGKeySet
- >>> gpgkey = getUtility(IGPGKeySet).get(1)
- >>> print gpgkey.owner.name
- name16
- >>> naked_sourcepackagerelease.dscsigningkey = gpgkey
-
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
-
-Since 'mark' is the 'creator' it makes the failed-to-build source
-look like a 'sponsored' upload.
-
- >>> print failed_candidate.source_package_release.creator.name
- mark
-
-Finally we issue the notification.
-
- >>> failed_candidate.notify()
-
-As expected for a 'not-copied and sponsored' PPA upload, only two
-people involved with the source are notified.
-
- * 'cprov' who owns the PPA where the source is being built;
- * 'name16' who signed the source upload;
-
-However, 'mark' who was listed as the creator of the source revision is
-not notified because he is not in the PPA team or its owner.
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 2
-
- >>> for notification in notifications:
- ... print notification['To']
- celso.providelo@xxxxxxxxxxxxx
- foo.bar@xxxxxxxxxxxxx
-
-If the failed build candidate is for a PPA where mark is a member,
-he will be notified.
-
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
- >>> team = factory.makeTeam(owner=cprov, email="team@xxxxxxxxxxx")
- >>> mark = failed_candidate.source_package_release.creator
- >>> ignored = team.addMember(mark, mark)
- >>> discard = pop_notifications() # Discard team join email.
- >>> team_ppa = factory.makeArchive(owner=team)
- >>> naked_candidate = removeSecurityProxy(failed_candidate)
- >>> naked_candidate.archive = team_ppa
- >>> naked_candidate.source_package_release.upload_archive = team_ppa
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
-
- >>> failed_candidate.notify()
-
-This notification will be sent to the package uploader
-(foo.bar@xxxxxxxxxxxxx), the package creator (mark@xxxxxxx) and the archive
-team's contact address (team@xxxxxxxxxxx).
-
- >>> notifications = pop_notifications()
- >>> len(notifications)
- 3
-
- >>> for notification in notifications:
- ... print notification['To']
- foo.bar@xxxxxxxxxxxxx
- mark@xxxxxxxxxxx
- team@xxxxxxxxxxx
-
-
-Named PPA notifications
-=======================
-
-Named PPA build notifications contain a specific reference to the PPA
-in context. We will override the testing build to be in the context of
-a just created named-ppa for Celso.
-
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
-
- >>> from lp.soyuz.enums import ArchivePurpose
- >>> from lp.soyuz.interfaces.archive import IArchiveSet
- >>> named_ppa = getUtility(IArchiveSet).new(
- ... owner=cprov, name='testing', purpose=ArchivePurpose.PPA)
-
- >>> naked_candidate = removeSecurityProxy(failed_candidate)
- >>> naked_candidate.archive = named_ppa
-
- >>> commit()
- >>> LaunchpadZopelessLayer.switchDbUser(test_dbuser)
-
-As described before, copied sources result in one build notification
-only, for the archive owner.
-
- >>> failed_candidate.notify()
-
- >>> notifications = pop_notifications()
- >>> for notification in notifications:
- ... print notification['To']
- celso.providelo@xxxxxxxxxxxxx
-
-The build-notification subject and headers correctly point
-to the named-ppa, 'cprov-testing'.
-
- >>> build_notification = notifications.pop(0)
- >>> dump_build_notification(build_notification)
- Subject: [Build #26] i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE (cprov-testing PPA)
- X-Creator-Recipient: mark@xxxxxxxxxxx
- X-Launchpad-Build-State: FAILEDTOBUILD
- X-Launchpad-Build-Component: main
- X-Launchpad-Build-Arch: i386
- X-Launchpad-PPA: cprov-testing
-
-The build notification body contains a reference to the named PPA, and
-the correct links to it the build in files in its context.
-
- >>> notification_body = build_notification.get_payload(decode=True)
- >>> print notification_body #doctest: -NORMALIZE_WHITESPACE
- <BLANKLINE>
- * Source Package: cdrkit
- * Version: 1.0
- * Architecture: i386
- * Archive: cprov-testing PPA
- * Component: main
- * State: Failed to build
- * Duration: a minute
- * Build Log: http://launchpad.dev/~cprov/+archive/testing/+buildjob/26/+files/netapplet-1.0.0.tar.gz
- * Builder: http://launchpad.dev/builders/bob
- * Source: not available
- <BLANKLINE>
- <BLANKLINE>
- <BLANKLINE>
- If you want further information about this situation, feel free to
- contact a member of the Launchpad Buildd Administrators team.
- <BLANKLINE>
- --
- i386 build of cdrkit 1.0 in ubuntu breezy-autotest RELEASE
- http://launchpad.dev/~cprov/+archive/testing/+buildjob/26
- <BLANKLINE>
=== added file 'lib/lp/soyuz/tests/test_build_notify.py'
--- lib/lp/soyuz/tests/test_build_notify.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_build_notify.py 2011-01-19 22:55:51 +0000
@@ -0,0 +1,304 @@
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+from datetime import (
+ datetime,
+ timedelta,
+ )
+import pytz
+from textwrap import dedent
+from zope.component import getUtility
+
+from canonical.launchpad.webapp import canonical_url
+from canonical.testing.layers import LaunchpadFunctionalLayer
+from lp.app.browser.tales import DurationFormatterAPI
+from lp.archivepublisher.utils import get_ppa_reference
+from lp.buildmaster.enums import BuildStatus
+from lp.registry.interfaces.person import IPersonSet
+from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.interfaces.publishing import PackagePublishingPocket
+from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
+from lp.testing import (
+ person_logged_in,
+ TestCaseWithFactory,
+ )
+from lp.testing.mail_helpers import pop_notifications
+from lp.testing.sampledata import ADMIN_EMAIL
+
+
+class TestBuildNotify(TestCaseWithFactory):
+
+ layer = LaunchpadFunctionalLayer
+
+ def setUp(self):
+ super(TestBuildNotify, self).setUp()
+ self.admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
+ # Create all of the items we need to create builds
+ self.pf = self.factory.makeProcessorFamily()
+ pf_proc = self.pf.addProcessor(self.factory.getUniqueString(), '', '')
+ self.distroseries = self.factory.makeDistroSeries()
+ self.das = self.factory.makeDistroArchSeries(
+ distroseries=self.distroseries, processorfamily=self.pf,
+ supports_virtualized=True)
+ self.creator = self.factory.makePerson(email='test@xxxxxxxxxxx')
+ self.archive = self.factory.makeArchive(
+ distribution=self.distroseries.distribution,
+ purpose=ArchivePurpose.PRIMARY)
+ self.ppa = self.factory.makeArchive()
+ with person_logged_in(self.admin):
+ self.publisher = SoyuzTestPublisher()
+ self.publisher.prepareBreezyAutotest()
+ self.distroseries.nominatedarchindep = self.das
+ self.publisher.addFakeChroots(distroseries=self.distroseries)
+ self.builder = self.factory.makeBuilder(processor=pf_proc)
+ self.builds = []
+
+ def create_builds(self, archive):
+ for status in BuildStatus.items:
+ spph = self.publisher.getPubSource(
+ sourcename=self.factory.getUniqueString(),
+ version="%s.%s" % (
+ self.factory.getUniqueInteger(), status.value),
+ distroseries=self.distroseries, architecturehintlist='any',
+ creator=self.creator, archive=archive)
+ [build] = spph.createMissingBuilds()
+ with person_logged_in(self.admin):
+ build.status = status
+ build.builder = self.builder
+ if status != BuildStatus.BUILDING:
+ build.buildqueue_record.destroySelf()
+ else:
+ build.buildqueue_record.builder = self.builder
+ build.date_started = datetime.now(pytz.UTC)
+ build.date_finished = build.date_started + timedelta(
+ minutes=5 * (status.value + 1))
+ self.builds.append(build)
+
+ def _assert_mail_is_correct(self, build, notification, ppa=False):
+ self.assertEquals('test@xxxxxxxxxxx',
+ notification['X-Creator-Recipient'])
+ self.assertEquals(
+ self.das.architecturetag, notification['X-Launchpad-Build-Arch'])
+ self.assertEquals(
+ 'main', notification['X-Launchpad-Build-Component'])
+ if ppa is True:
+ self.assertEquals(
+ get_ppa_reference(self.ppa), notification['X-Launchpad-PPA'])
+ body = notification.get_payload(decode=True)
+ duration = DurationFormatterAPI(build.duration).approximateduration()
+ build_log = 'None'
+ if ppa is True:
+ archive = '%s PPA' % get_ppa_reference(build.archive)
+ source = 'not available'
+ else:
+ archive = '%s primary archive' % (
+ self.distroseries.distribution.name)
+ source = canonical_url(build.distributionsourcepackagerelease)
+ builder = canonical_url(build.builder)
+ if build.status == BuildStatus.BUILDING:
+ duration = 'not finished'
+ build_log = 'see builder page'
+ elif (
+ build.status == BuildStatus.SUPERSEDED or
+ build.status == BuildStatus.NEEDSBUILD):
+ duration = 'not available'
+ build_log = 'not available'
+ builder = 'not available'
+ elif build.status == BuildStatus.UPLOADING:
+ duration = 'uploading'
+ build_log = 'see builder page'
+ builder = 'not available'
+ expected_body = dedent("""
+ * Source Package: %s
+ * Version: %s
+ * Architecture: %s
+ * Archive: %s
+ * Component: main
+ * State: %s
+ * Duration: %s
+ * Build Log: %s
+ * Builder: %s
+ * Source: %s
+
+
+
+ If you want further information about this situation, feel free to
+ contact a member of the Launchpad Buildd Administrators team.
+
+ --
+ %s
+ %s
+ """ % (
+ build.source_package_release.sourcepackagename.name,
+ build.source_package_release.version, self.das.architecturetag,
+ archive, build.status.title, duration, build_log, builder,
+ source, build.title, canonical_url(build)))
+ self.assertEquals(expected_body, body)
+
+ def test_notify_buildd_admins(self):
+ # A build will cause an e-mail to be sent out to the buildd-admins,
+ # for primary archive builds.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.FAILEDTOBUILD.value]
+ build.notify()
+ notifications = pop_notifications()
+ # There are 2 buildd-admins in the sample data, as well as the creator
+ self.assertEquals(3, len(notifications))
+
+ def test_ppa_does_not_notify_buildd_admins(self):
+ # A build for a PPA does not notify the buildd admins.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.FAILEDTOBUILD.value]
+ build.notify()
+ notifications = pop_notifications()
+ # An e-mail is sent to the archive owner, as well as the creator
+ self.assertEquals(2, len(notifications))
+
+ def test_notify_failed_to_build(self):
+ # An e-mail is sent to the source package creator on build failures.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.FAILEDTOBUILD.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_failed_to_build_ppa(self):
+ # An e-mail is sent to the source package creator on build failures.
+ self.create_builds(archive=self.ppa)
+ build = self.builds[BuildStatus.FAILEDTOBUILD.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_needs_building(self):
+ # We can notify the creator when the build is needing to be built.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.NEEDSBUILD.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_needs_building_ppa(self):
+ # We can notify the creator when the build is needing to be built.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.NEEDSBUILD.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_successfully_built(self):
+ # We can notify the creator when the build is sucessful.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.FULLYBUILT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_successfully_built_ppa(self):
+ # We can notify the creator when the build is sucessful.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.FULLYBUILT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_dependency_wait(self):
+ # We can notify the creator when the build can't find a dependency.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.MANUALDEPWAIT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_dependency_wait_ppa(self):
+ # We can notify the creator when the build can't find a dependency.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.MANUALDEPWAIT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_chroot_problem(self):
+ # We can notify the creator when the builder the build attempted to
+ # be built on has an internal problem.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.CHROOTWAIT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_chroot_problem_ppa(self):
+ # We can notify the creator when the builder the build attempted to
+ # be built on has an internal problem.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.CHROOTWAIT.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_build_for_superseded_source(self):
+ # We can notify the creator when the source package had a newer
+ # version uploaded before this build had a chance to be dispatched.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.SUPERSEDED.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_build_for_superseded_source_ppa(self):
+ # We can notify the creator when the source package had a newer
+ # version uploaded before this build had a chance to be dispatched.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.SUPERSEDED.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_currently_building(self):
+ # We can notify the creator when the build is currently building.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.BUILDING.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_currently_building_ppa(self):
+ # We can notify the creator when the build is currently building.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.BUILDING.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_notify_uploading_build(self):
+ # We can notify the creator when the build has completed, and binary
+ # packages are being uploaded by the builder.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.UPLOADING.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification)
+
+ def test_notify_uploading_build_ppa(self):
+ # We can notify the creator when the build has completed, and binary
+ # packages are being uploaded by the builder.
+ self.create_builds(self.ppa)
+ build = self.builds[BuildStatus.UPLOADING.value]
+ build.notify()
+ notification = pop_notifications()[1]
+ self._assert_mail_is_correct(build, notification, ppa=True)
+
+ def test_copied_into_ppa_does_not_spam(self):
+ # When a package is copied into a PPA, we don't send mail to the
+ # original creator of the source package.
+ self.create_builds(self.archive)
+ build = self.builds[BuildStatus.FULLYBUILT.value]
+ spph = build.current_source_publication
+ ppa_spph = spph.copyTo(
+ self.distroseries, PackagePublishingPocket.RELEASE, self.ppa)
+ [ppa_build] = ppa_spph.createMissingBuilds()
+ ppa_build.notify()
+ notifications = pop_notifications()
+ self.assertEquals(1, len(notifications))
=== modified file 'lib/lp/soyuz/tests/test_doc.py'
--- lib/lp/soyuz/tests/test_doc.py 2011-01-19 22:54:51 +0000
+++ lib/lp/soyuz/tests/test_doc.py 2011-01-19 22:55:51 +0000
@@ -141,11 +141,6 @@
special = {
- 'build-notification.txt': LayeredDocFileSuite(
- '../doc/build-notification.txt',
- setUp=builddmasterSetUp,
- layer=LaunchpadZopelessLayer,
- ),
'buildd-scoring.txt': LayeredDocFileSuite(
'../doc/buildd-scoring.txt',
setUp=builddmasterSetUp,
Follow ups