Merge lp:~cjwatson/launchpad/delay-ppa-publication into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 17703
Proposed branch: lp:~cjwatson/launchpad/delay-ppa-publication
Merge into: lp:launchpad
Diff against target: 157 lines (+62/-2)
5 files modified
lib/lp/archivepublisher/scripts/publishdistro.py (+1/-1)
lib/lp/archivepublisher/tests/test_publishdistro.py (+38/-1)
lib/lp/services/config/schema-lazr.conf (+5/-0)
lib/lp/soyuz/interfaces/archive.py (+5/-0)
lib/lp/soyuz/model/archive.py (+13/-0)
To merge this branch: bzr merge lp:~cjwatson/launchpad/delay-ppa-publication
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+269090@code.launchpad.net

Commit message

Only publish PPAs once their signing key has been generated.

Description of the change

Only publish PPAs once their signing key has been generated. Going ahead and publishing them unsigned has been confusing people for years.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

This will make dogfood and dev testing annoying, so I'd possibly consider using a config flag to apply it only on prod.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archivepublisher/scripts/publishdistro.py'
2--- lib/lp/archivepublisher/scripts/publishdistro.py 2015-03-18 17:49:57 +0000
3+++ lib/lp/archivepublisher/scripts/publishdistro.py 2015-08-28 08:39:32 +0000
4@@ -291,7 +291,7 @@
5
6 if archive.status == ArchiveStatus.DELETING:
7 work_done = self.deleteArchive(archive, publisher)
8- elif archive.publish:
9+ elif archive.can_be_published:
10 for suite in self.options.dirty_suites:
11 distroseries, pocket = self.findSuite(
12 distribution, suite)
13
14=== modified file 'lib/lp/archivepublisher/tests/test_publishdistro.py'
15--- lib/lp/archivepublisher/tests/test_publishdistro.py 2015-03-20 07:49:14 +0000
16+++ lib/lp/archivepublisher/tests/test_publishdistro.py 2015-08-28 08:39:32 +0000
17@@ -1,4 +1,4 @@
18-# Copyright 2009-2013 Canonical Ltd. This software is licensed under the
19+# Copyright 2009-2015 Canonical Ltd. This software is licensed under the
20 # GNU Affero General Public License version 3 (see the file LICENSE).
21
22 """Functional tests for publish-distro.py script."""
23@@ -16,6 +16,7 @@
24
25 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
26 from lp.archivepublisher.config import getPubConfig
27+from lp.archivepublisher.interfaces.archivesigningkey import IArchiveSigningKey
28 from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
29 from lp.archivepublisher.publishing import Publisher
30 from lp.archivepublisher.scripts.publishdistro import PublishDistro
31@@ -39,6 +40,8 @@
32 from lp.testing.dbuser import switch_dbuser
33 from lp.testing.fakemethod import FakeMethod
34 from lp.testing.faketransaction import FakeTransaction
35+from lp.testing.gpgkeys import gpgkeysdir
36+from lp.testing.keyserver import KeyServerTac
37 from lp.testing.layers import ZopelessDatabaseLayer
38
39
40@@ -195,6 +198,24 @@
41 os.path.join("%s" % distsroot, distroseries, 'Release'))
42 shutil.rmtree(tmp_path)
43
44+ def setUpRequireSigningKeys(self):
45+ config.push('ppa-require-signing-keys', """
46+ [personalpackagearchive]
47+ require_signing_keys: true
48+ """)
49+ self.addCleanup(config.pop, 'ppa-require-signing-keys')
50+
51+ def testForPPAWithoutSigningKey(self):
52+ """publish-distro skips PPAs that do not yet have a signing key."""
53+ self.setUpRequireSigningKeys()
54+ cprov = getUtility(IPersonSet).getByName('cprov')
55+ pub_source = self.getPubSource(archive=cprov.archive)
56+ removeSecurityProxy(cprov.archive).distribution = self.ubuntutest
57+ self.layer.txn.commit()
58+ self.runPublishDistro(['--ppa'])
59+ pub_source.sync()
60+ self.assertEqual(PackagePublishingStatus.PENDING, pub_source.status)
61+
62 def testForPPA(self):
63 """Try to run publish-distro in PPA mode.
64
65@@ -219,6 +240,14 @@
66 naked_archive = removeSecurityProxy(name16.archive)
67 naked_archive.distribution = self.ubuntutest
68
69+ self.setUpRequireSigningKeys()
70+ tac = KeyServerTac()
71+ tac.setUp()
72+ self.addCleanup(tac.tearDown)
73+ key_path = os.path.join(gpgkeysdir, 'ppa-sample@canonical.com.sec')
74+ IArchiveSigningKey(cprov.archive).setSigningKey(key_path)
75+ name16.archive.signing_key = cprov.archive.signing_key
76+
77 self.layer.txn.commit()
78
79 self.runPublishDistro(['--ppa'])
80@@ -261,6 +290,13 @@
81 sourcename='baz', filecontent='baz', archive=private_ppa)
82 self.layer.txn.commit()
83
84+ self.setUpRequireSigningKeys()
85+ tac = KeyServerTac()
86+ tac.setUp()
87+ self.addCleanup(tac.tearDown)
88+ key_path = os.path.join(gpgkeysdir, 'ppa-sample@canonical.com.sec')
89+ IArchiveSigningKey(private_ppa).setSigningKey(key_path)
90+
91 # Try a plain PPA run, to ensure the private one is NOT published.
92 self.runPublishDistro(['--ppa'])
93
94@@ -358,6 +394,7 @@
95 """A very simple fake `Archive`."""
96 def __init__(self, purpose=ArchivePurpose.PRIMARY):
97 self.publish = True
98+ self.can_be_published = True
99 self.purpose = purpose
100 self.status = ArchiveStatus.ACTIVE
101
102
103=== modified file 'lib/lp/services/config/schema-lazr.conf'
104--- lib/lp/services/config/schema-lazr.conf 2015-08-04 11:03:04 +0000
105+++ lib/lp/services/config/schema-lazr.conf 2015-08-28 08:39:32 +0000
106@@ -1411,6 +1411,11 @@
107 # datatype: string
108 signing_keys_root: /var/tmp/ppa-signing-keys
109
110+# If true, PPAs will only be published once their signing-keys have been
111+# generated.
112+# datatype: boolean
113+require_signing_keys: false
114+
115
116 [ppa_apache_log_parser]
117 logs_root: /srv/ppa.launchpad.net-logs
118
119=== modified file 'lib/lp/soyuz/interfaces/archive.py'
120--- lib/lp/soyuz/interfaces/archive.py 2015-08-03 14:47:25 +0000
121+++ lib/lp/soyuz/interfaces/archive.py 2015-08-28 08:39:32 +0000
122@@ -406,6 +406,11 @@
123 description=_("Whether or not to update the apt repository. If "
124 "disabled, nothing will be published. If the archive is "
125 "private then additionally no builds will be dispatched."))
126+ can_be_published = Bool(
127+ title=_("Can be published"), required=True,
128+ description=_(
129+ "True if this archive can be published, considering both the "
130+ "explicit publish flag and any other constraints."))
131 series_with_sources = Attribute(
132 "DistroSeries to which this archive has published sources")
133 signing_key = Object(
134
135=== modified file 'lib/lp/soyuz/model/archive.py'
136--- lib/lp/soyuz/model/archive.py 2015-07-08 16:05:11 +0000
137+++ lib/lp/soyuz/model/archive.py 2015-08-28 08:39:32 +0000
138@@ -413,6 +413,19 @@
139 return self.status == ArchiveStatus.ACTIVE
140
141 @property
142+ def can_be_published(self):
143+ """See `IArchive`."""
144+ # The explicit publish flag must be set.
145+ if not self.publish:
146+ return False
147+ # In production configurations, PPAs can only be published once
148+ # their signing key has been generated.
149+ return (
150+ not config.personalpackagearchive.require_signing_keys or
151+ not self.is_ppa or
152+ self.signing_key is not None)
153+
154+ @property
155 def reference(self):
156 template = ARCHIVE_REFERENCE_TEMPLATES.get(self.purpose)
157 if template is None: