Merge ~pappacena/launchpad:change-override-log into launchpad:master

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: 66fa2e6d4ae5720963eeb101e292584d33038254
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/launchpad:change-override-log
Merge into: launchpad:master
Diff against target: 331 lines (+131/-10)
7 files modified
lib/lp/soyuz/interfaces/publishing.py (+13/-3)
lib/lp/soyuz/model/publishing.py (+11/-3)
lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt (+27/-0)
lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt (+1/-0)
lib/lp/soyuz/templates/packagepublishing-details.pt (+8/-0)
lib/lp/soyuz/tests/test_publishing.py (+67/-2)
lib/lp/testing/factory.py (+4/-2)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+380252@code.launchpad.net

Commit message

Saving and showing the user that requested to override a package publishing.

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

cjwatson, this is still a WIP (I'm still missing tests, for example), but I would like to get a "pre-review", just to make sure we are aligned on what should be done here.

Basically, I checked lp:ubuntu-archive-tools repo and it seems that the `change-override` scripts call the changeOverride on the API, with an authenticated user.

So, on LP side, I'm getting the logged in user and setting it on the "creator" field both for Source and Binary PackagePublishingHistory. Then, showing it on the details of the +publishinghistory page.

Revision history for this message
Colin Watson (cjwatson) wrote :

This looks like broadly the right sort of direction. The main thing that I think needs to change is to explicitly pass the principal down from the caller (using @call_with(user=REQUEST_USER) or similar in the interface declaration) rather than picking out the principal in model code.

Revision history for this message
Colin Watson (cjwatson) :
review: Needs Information
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Added more info about why it's showing only for PENDING, cjwatson. Let me know what do you think about showing in every other situation.

I'm doing the other requests right now.

Revision history for this message
Colin Watson (cjwatson) :
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

cjwatson, pushed the requested change. It should now show the "Created by ..." always, apart from deleted and copied packages, which are special cases.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Changes pushed. It should good to go as soon as we deploy the database change to production.

Revision history for this message
Colin Watson (cjwatson) wrote :

This can land now - the database patch is in place.

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Thanks! I'll top-approve it now.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/soyuz/interfaces/publishing.py b/lib/lp/soyuz/interfaces/publishing.py
index 02c3615..4697209 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -1,4 +1,4 @@
1# Copyright 2009-2019 Canonical Ltd. This software is licensed under the1# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Publishing interfaces."""4"""Publishing interfaces."""
@@ -561,8 +561,9 @@ class ISourcePackagePublishingHistoryEdit(IPublishingEdit):
561 new_component=TextLine(title=u"The new component name."),561 new_component=TextLine(title=u"The new component name."),
562 new_section=TextLine(title=u"The new section name."))562 new_section=TextLine(title=u"The new section name."))
563 @export_write_operation()563 @export_write_operation()
564 @call_with(creator=REQUEST_USER)
564 @operation_for_version("devel")565 @operation_for_version("devel")
565 def changeOverride(new_component=None, new_section=None):566 def changeOverride(new_component=None, new_section=None, creator=None):
566 """Change the component and/or section of this publication.567 """Change the component and/or section of this publication.
567568
568 It is changed only if the argument is not None.569 It is changed only if the argument is not None.
@@ -663,6 +664,13 @@ class IBinaryPackagePublishingHistoryPublic(IPublishingView):
663 title=_('The build which superseded this one'),664 title=_('The build which superseded this one'),
664 required=False, readonly=False,665 required=False, readonly=False,
665 )666 )
667 creator = exported(
668 Reference(
669 IPerson,
670 title=_('Publication Creator'),
671 description=_('The IPerson who created this publication.'),
672 required=False, readonly=True
673 ))
666 datecreated = exported(674 datecreated = exported(
667 Datetime(675 Datetime(
668 title=_('Date Created'),676 title=_('Date Created'),
@@ -840,9 +848,11 @@ class IBinaryPackagePublishingHistoryEdit(IPublishingEdit):
840 new_phased_update_percentage=Int(848 new_phased_update_percentage=Int(
841 title=u"The new phased update percentage."))849 title=u"The new phased update percentage."))
842 @export_write_operation()850 @export_write_operation()
851 @call_with(creator=REQUEST_USER)
843 @operation_for_version("devel")852 @operation_for_version("devel")
844 def changeOverride(new_component=None, new_section=None,853 def changeOverride(new_component=None, new_section=None,
845 new_priority=None, new_phased_update_percentage=None):854 new_priority=None, new_phased_update_percentage=None,
855 creator=None):
846 """Change the component/section/priority/phase of this publication.856 """Change the component/section/priority/phase of this publication.
847857
848 It is changed only if the argument is not None.858 It is changed only if the argument is not None.
diff --git a/lib/lp/soyuz/model/publishing.py b/lib/lp/soyuz/model/publishing.py
index 3e73e98..ae7b414 100644
--- a/lib/lp/soyuz/model/publishing.py
+++ b/lib/lp/soyuz/model/publishing.py
@@ -1,4 +1,4 @@
1# Copyright 2009-2019 Canonical Ltd. This software is licensed under the1# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4__metaclass__ = type4__metaclass__ = type
@@ -471,7 +471,8 @@ class SourcePackagePublishingHistory(SQLBase, ArchivePublisherBase):
471471
472 self.supersededby = dominant.sourcepackagerelease472 self.supersededby = dominant.sourcepackagerelease
473473
474 def changeOverride(self, new_component=None, new_section=None):474 def changeOverride(self, new_component=None, new_section=None,
475 creator=None):
475 """See `ISourcePackagePublishingHistory`."""476 """See `ISourcePackagePublishingHistory`."""
476 # Check we have been asked to do something477 # Check we have been asked to do something
477 if (new_component is None and478 if (new_component is None and
@@ -516,6 +517,7 @@ class SourcePackagePublishingHistory(SQLBase, ArchivePublisherBase):
516 pocket=self.pocket,517 pocket=self.pocket,
517 component=new_component,518 component=new_component,
518 section=new_section,519 section=new_section,
520 creator=creator,
519 archive=self.archive)521 archive=self.archive)
520522
521 def copyTo(self, distroseries, pocket, archive, override=None,523 def copyTo(self, distroseries, pocket, archive, override=None,
@@ -629,6 +631,9 @@ class BinaryPackagePublishingHistory(SQLBase, ArchivePublisherBase):
629 phased_update_percentage = IntCol(631 phased_update_percentage = IntCol(
630 dbName='phased_update_percentage', notNull=False, default=None)632 dbName='phased_update_percentage', notNull=False, default=None)
631 scheduleddeletiondate = UtcDateTimeCol(default=None)633 scheduleddeletiondate = UtcDateTimeCol(default=None)
634 creator = ForeignKey(
635 dbName='creator', foreignKey='Person',
636 storm_validator=validate_public_person, notNull=False, default=None)
632 datepublished = UtcDateTimeCol(default=None)637 datepublished = UtcDateTimeCol(default=None)
633 datecreated = UtcDateTimeCol(default=UTC_NOW)638 datecreated = UtcDateTimeCol(default=UTC_NOW)
634 datesuperseded = UtcDateTimeCol(default=None)639 datesuperseded = UtcDateTimeCol(default=None)
@@ -794,7 +799,8 @@ class BinaryPackagePublishingHistory(SQLBase, ArchivePublisherBase):
794 dominated.supersede(dominant, logger)799 dominated.supersede(dominant, logger)
795800
796 def changeOverride(self, new_component=None, new_section=None,801 def changeOverride(self, new_component=None, new_section=None,
797 new_priority=None, new_phased_update_percentage=None):802 new_priority=None, new_phased_update_percentage=None,
803 creator=None):
798 """See `IBinaryPackagePublishingHistory`."""804 """See `IBinaryPackagePublishingHistory`."""
799805
800 # Check we have been asked to do something806 # Check we have been asked to do something
@@ -873,6 +879,7 @@ class BinaryPackagePublishingHistory(SQLBase, ArchivePublisherBase):
873 component=new_component,879 component=new_component,
874 section=new_section,880 section=new_section,
875 priority=new_priority,881 priority=new_priority,
882 creator=creator,
876 archive=debug.archive,883 archive=debug.archive,
877 phased_update_percentage=new_phased_update_percentage)884 phased_update_percentage=new_phased_update_percentage)
878885
@@ -888,6 +895,7 @@ class BinaryPackagePublishingHistory(SQLBase, ArchivePublisherBase):
888 section=new_section,895 section=new_section,
889 priority=new_priority,896 priority=new_priority,
890 archive=self.archive,897 archive=self.archive,
898 creator=creator,
891 phased_update_percentage=new_phased_update_percentage)899 phased_update_percentage=new_phased_update_percentage)
892900
893 def copyTo(self, distroseries, pocket, archive):901 def copyTo(self, distroseries, pocket, archive):
diff --git a/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt b/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
index 31e98b7..51a629b 100644
--- a/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
+++ b/lib/lp/soyuz/stories/soyuz/xx-packagepublishinghistory.txt
@@ -23,10 +23,35 @@ shows the complete history of a package in all series.
23 >>> print(extract_text(table))23 >>> print(extract_text(table))
24 Date Status Target Pocket Component Section Version24 Date Status Target Pocket Component Section Version
25 ... UTC Published Breezy ... release main base 66625 ... UTC Published Breezy ... release main base 666
26 Created ... ago by Foo Bar
26 Published ... ago27 Published ... ago
27 >>> print(table.findAll("tr")[2].td["colspan"])28 >>> print(table.findAll("tr")[2].td["colspan"])
28 829 8
2930
31A change-override request should show who made the request
32
33 >>> from lp.registry.interfaces.person import IPersonSet
34 >>> from zope.component import getUtility
35
36 >>> login('foo.bar@canonical.com')
37 >>> person = getUtility(IPersonSet).getByEmail('foo.bar@canonical.com')
38 >>> new_pub = source_pub.changeOverride(
39 ... new_component='universe', creator=person)
40 >>> logout()
41
42 >>> anon_browser.open(
43 ... 'http://launchpad.test/ubuntutest/+source/test-history/'
44 ... '+publishinghistory')
45 >>> table = find_tag_by_id(anon_browser.contents, 'publishing-summary')
46 >>> print(extract_text(table))
47 Date Status Target Pocket Component Section Version
48 ... UTC Pending Breezy ... release universe base 666
49 Created ... ago by Foo Bar
50 ... UTC Published Breezy ... release main base 666
51 Created ... ago by Foo Bar
52 Published ... ago
53
54
30A publishing record will be shown as deleted in the publishing history after a55A publishing record will be shown as deleted in the publishing history after a
31request for deletion by a user.56request for deletion by a user.
3257
@@ -42,6 +67,8 @@ request for deletion by a user.
42 >>> table = find_tag_by_id(anon_browser.contents, 'publishing-summary')67 >>> table = find_tag_by_id(anon_browser.contents, 'publishing-summary')
43 >>> print(extract_text(table))68 >>> print(extract_text(table))
44 Date Status Target Pocket Component Section Version69 Date Status Target Pocket Component Section Version
70 ... UTC Pending Breezy ... release universe base 666
71 Created ... ago by Foo Bar
45 Deleted Breezy ... release main base 66672 Deleted Breezy ... release main base 666
46 Deleted ... ago by ... fix bug 173 Deleted ... ago by ... fix bug 1
47 Published ... ago74 Published ... ago
diff --git a/lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt b/lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt
index 81482f2..722c4c0 100644
--- a/lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt
+++ b/lib/lp/soyuz/stories/webservice/xx-binary-package-publishing.txt
@@ -71,6 +71,7 @@ Each binary publication exposes a number of properties:
71 binary_package_version: u'1.0'71 binary_package_version: u'1.0'
72 build_link: u'http://.../~cprov/+archive/ubuntu/ppa/+build/28'72 build_link: u'http://.../~cprov/+archive/ubuntu/ppa/+build/28'
73 component_name: u'main'73 component_name: u'main'
74 creator_link: None
74 date_created: u'2007-08-10T13:00:00+00:00'75 date_created: u'2007-08-10T13:00:00+00:00'
75 date_made_pending: None76 date_made_pending: None
76 date_published: u'2007-08-10T13:00:01+00:00'77 date_published: u'2007-08-10T13:00:01+00:00'
diff --git a/lib/lp/soyuz/templates/packagepublishing-details.pt b/lib/lp/soyuz/templates/packagepublishing-details.pt
index 0b0102c..4c65323 100644
--- a/lib/lp/soyuz/templates/packagepublishing-details.pt
+++ b/lib/lp/soyuz/templates/packagepublishing-details.pt
@@ -4,6 +4,14 @@
4 xmlns:i18n="http://xml.zope.org/namespaces/i18n"4 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
5 omit-tag="">5 omit-tag="">
6 <ul>6 <ul>
7 <li tal:condition="python: context.creator
8 and not view.wasCopied()
9 and not view.wasDeleted()">
10 Created
11 <span tal:attributes="title context/datecreated/fmt:datetime"
12 tal:content="context/datecreated/fmt:displaydate" />
13 by <a tal:replace="structure context/creator/fmt:link"/>
14 </li>
7 <li tal:condition="view/isRemoved">15 <li tal:condition="view/isRemoved">
8 Removed from disk16 Removed from disk
9 <span tal:attributes="title context/dateremoved/fmt:datetime"17 <span tal:attributes="title context/dateremoved/fmt:datetime"
diff --git a/lib/lp/soyuz/tests/test_publishing.py b/lib/lp/soyuz/tests/test_publishing.py
index c29028e..e65003d 100644
--- a/lib/lp/soyuz/tests/test_publishing.py
+++ b/lib/lp/soyuz/tests/test_publishing.py
@@ -1,4 +1,4 @@
1# Copyright 2009-2019 Canonical Ltd. This software is licensed under the1# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Test native publication workflow for Soyuz. """4"""Test native publication workflow for Soyuz. """
@@ -62,6 +62,9 @@ from lp.soyuz.model.publishing import (
62 SourcePackagePublishingHistory,62 SourcePackagePublishingHistory,
63 )63 )
64from lp.testing import (64from lp.testing import (
65 login_admin,
66 person_logged_in,
67 record_two_runs,
65 StormStatementRecorder,68 StormStatementRecorder,
66 TestCaseWithFactory,69 TestCaseWithFactory,
67 )70 )
@@ -72,6 +75,7 @@ from lp.testing.dbuser import (
72from lp.testing.factory import LaunchpadObjectFactory75from lp.testing.factory import LaunchpadObjectFactory
73from lp.testing.layers import (76from lp.testing.layers import (
74 DatabaseFunctionalLayer,77 DatabaseFunctionalLayer,
78 LaunchpadFunctionalLayer,
75 LaunchpadZopelessLayer,79 LaunchpadZopelessLayer,
76 ZopelessDatabaseLayer,80 ZopelessDatabaseLayer,
77 )81 )
@@ -997,13 +1001,15 @@ class TestPublishingSetLite(TestCaseWithFactory):
997 debug_non_match_bpph.status, PackagePublishingStatus.PENDING)1001 debug_non_match_bpph.status, PackagePublishingStatus.PENDING)
9981002
999 def test_changeOverride_also_overrides_debug_package(self):1003 def test_changeOverride_also_overrides_debug_package(self):
1004 user = self.factory.makePerson()
1000 bpph, debug_bpph = self.factory.makeBinaryPackagePublishingHistory(1005 bpph, debug_bpph = self.factory.makeBinaryPackagePublishingHistory(
1001 pocket=PackagePublishingPocket.RELEASE, with_debug=True)1006 pocket=PackagePublishingPocket.RELEASE, with_debug=True)
1002 new_section = self.factory.makeSection()1007 new_section = self.factory.makeSection()
1003 new_bpph = bpph.changeOverride(new_section=new_section)1008 new_bpph = bpph.changeOverride(new_section=new_section, creator=user)
1004 publishing_set = getUtility(IPublishingSet)1009 publishing_set = getUtility(IPublishingSet)
1005 [new_debug_bpph] = publishing_set.findCorrespondingDDEBPublications(1010 [new_debug_bpph] = publishing_set.findCorrespondingDDEBPublications(
1006 [new_bpph])1011 [new_bpph])
1012 self.assertEqual(new_debug_bpph.creator, user)
1007 self.assertEqual(new_debug_bpph.section, new_section)1013 self.assertEqual(new_debug_bpph.section, new_section)
10081014
1009 def test_requestDeletion_forbids_debug_package(self):1015 def test_requestDeletion_forbids_debug_package(self):
@@ -1524,6 +1530,21 @@ class TestChangeOverride(TestNativePublishingBase):
1524 binary=True, new_component="universe", new_section="misc",1530 binary=True, new_component="universe", new_section="misc",
1525 new_priority="extra", new_phased_update_percentage=90)1531 new_priority="extra", new_phased_update_percentage=90)
15261532
1533 def test_change_binary_logged_in_user(self):
1534 person = self.factory.makePerson()
1535 new_pub = self.assertCanOverride(
1536 binary=True, new_component="universe", new_section="misc",
1537 new_priority="extra", new_phased_update_percentage=90,
1538 creator=person)
1539 self.assertEqual(person, new_pub.creator)
1540
1541 def test_change_source_logged_in_user(self):
1542 person = self.factory.makePerson()
1543 new_pub = self.assertCanOverride(
1544 binary=False, new_component="universe", new_section="misc",
1545 creator=person)
1546 self.assertEqual(person, new_pub.creator)
1547
1527 def test_set_and_clear_phased_update_percentage(self):1548 def test_set_and_clear_phased_update_percentage(self):
1528 # new_phased_update_percentage=<integer> sets a phased update1549 # new_phased_update_percentage=<integer> sets a phased update
1529 # percentage; new_phased_update_percentage=100 clears it.1550 # percentage; new_phased_update_percentage=100 clears it.
@@ -1572,3 +1593,47 @@ class TestChangeOverride(TestNativePublishingBase):
1572 # archive.1593 # archive.
1573 self.assertCannotOverride(new_component="partner")1594 self.assertCannotOverride(new_component="partner")
1574 self.assertCannotOverride(binary=True, new_component="partner")1595 self.assertCannotOverride(binary=True, new_component="partner")
1596
1597
1598class TestPublishingHistoryView(TestCaseWithFactory):
1599 layer = LaunchpadFunctionalLayer
1600
1601 def test_constant_query_counts_on_publishing_history_change_override(self):
1602 admin = self.factory.makeAdministrator()
1603 normal_user = self.factory.makePerson()
1604
1605 with person_logged_in(admin):
1606 test_publisher = SoyuzTestPublisher()
1607 test_publisher.prepareBreezyAutotest()
1608
1609 source_pub = test_publisher.getPubSource(
1610 "test-history", status=PackagePublishingStatus.PUBLISHED)
1611 url = ("http://launchpad.test/ubuntutest/+source/test-history"
1612 "/+publishinghistory")
1613
1614 def insert_more_publish_history():
1615 person1 = self.factory.makePerson()
1616 new_component = (
1617 'universe' if source_pub.component.name == 'main'
1618 else 'main')
1619 source_pub.changeOverride(
1620 new_component=new_component, creator=person1)
1621
1622 person2 = self.factory.makePerson()
1623 new_section = ('web' if source_pub.section.name == 'base'
1624 else 'base')
1625 source_pub.changeOverride(
1626 new_section=new_section, creator=person2)
1627
1628 def show_page():
1629 self.getUserBrowser(url, normal_user)
1630
1631 # Make sure to have all the history fitting in one page.
1632 self.pushConfig("launchpad", default_batch_size=50)
1633
1634 recorder1, recorder2 = record_two_runs(
1635 show_page, insert_more_publish_history,
1636 1, 10, login_method=login_admin)
1637
1638 self.assertThat(recorder1, HasQueryCount(Equals(26)))
1639 self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
diff --git a/lib/lp/testing/factory.py b/lib/lp/testing/factory.py
index 8248fa8..2bdac13 100644
--- a/lib/lp/testing/factory.py
+++ b/lib/lp/testing/factory.py
@@ -3989,7 +3989,8 @@ class BareLaunchpadObjectFactory(ObjectFactory):
3989 sourcepackagename=None,3989 sourcepackagename=None,
3990 version=None,3990 version=None,
3991 architecturespecific=False,3991 architecturespecific=False,
3992 with_debug=False, with_file=False):3992 with_debug=False, with_file=False,
3993 creator=None):
3993 """Make a `BinaryPackagePublishingHistory`."""3994 """Make a `BinaryPackagePublishingHistory`."""
3994 if distroarchseries is None:3995 if distroarchseries is None:
3995 if archive is None:3996 if archive is None:
@@ -4082,7 +4083,8 @@ class BareLaunchpadObjectFactory(ObjectFactory):
4082 binpackageformat=BinaryPackageFormat.DDEB,4083 binpackageformat=BinaryPackageFormat.DDEB,
4083 sourcepackagename=sourcepackagename,4084 sourcepackagename=sourcepackagename,
4084 architecturespecific=architecturespecific,4085 architecturespecific=architecturespecific,
4085 with_file=with_file)4086 with_file=with_file,
4087 creator=creator)
4086 removeSecurityProxy(bpph.binarypackagerelease).debug_package = (4088 removeSecurityProxy(bpph.binarypackagerelease).debug_package = (
4087 debug_bpph.binarypackagerelease)4089 debug_bpph.binarypackagerelease)
4088 return bpphs[0], debug_bpph4090 return bpphs[0], debug_bpph