Merge lp:~jtv/launchpad/bug-836743 into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 13823
Proposed branch: lp:~jtv/launchpad/bug-836743
Merge into: lp:launchpad
Diff against target: 131 lines (+55/-9)
4 files modified
lib/lp/archivepublisher/config.py (+3/-1)
lib/lp/archivepublisher/scripts/publish_ftpmaster.py (+23/-8)
lib/lp/archivepublisher/tests/test_config.py (+19/-0)
lib/lp/archivepublisher/tests/test_publish_ftpmaster.py (+10/-0)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-836743
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+73267@code.launchpad.net

Commit message

[r=wgrant][bug=836743] Make publish_ftpmaster resistant to configless archives.

Description of the change

= Summary =

The publish-ftpmaster script broke when it encountered a distribution archive without a publisher config. Could be a bit of a handicap when iterating over all derived distributions, including any that haven't had their configuration set up.

== Proposed fix ==

Have getPubConfig return None for archives that have no configuration in the database. Have publish_ftpmaster ignore distros without archive configs.

== Pre-implementation notes ==

This came up while trying out the publisher's --all-derived option on dogfood. Apparently the publisher config needs to be set up in the UI; distros that don't have it set up yet evidently aren't ready for publishing.

== Implementation details ==

You'll note that I made getConfigs() skip missing configs _per archive_, but main() check for and skip missing configs _per distro_. A distro can have multiple archives.

But the publisher config in the database is keyed off the distro's main archive. So there seems to be no middle ground between "distro without configs" and "distro with configs," unless it's a distro without archives.

== Tests ==

{{{
./bin/test -vvc lp.archivepublisher.tests.test_publish_ftpmaster
}}}

== Demo and Q/A ==

Run "cronscripts/publish-ftpmaster.py --all-derived" on dogfood. It should get further than the previous attempt, which broke after a few seconds (i.e. ZCML processing, sigh) during getConfigs very early in the script.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/archivepublisher/scripts/publish_ftpmaster.py
  lib/lp/archivepublisher/tests/test_config.py
  lib/lp/archivepublisher/config.py
  lib/lp/archivepublisher/tests/test_publish_ftpmaster.py

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) :
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/config.py'
2--- lib/lp/archivepublisher/config.py 2011-03-30 04:51:49 +0000
3+++ lib/lp/archivepublisher/config.py 2011-08-29 17:16:29 +0000
4@@ -13,8 +13,8 @@
5 from canonical.config import config
6 from lp.archivepublisher.interfaces.publisherconfig import IPublisherConfigSet
7 from lp.soyuz.enums import (
8+ archive_suffixes,
9 ArchivePurpose,
10- archive_suffixes,
11 )
12
13
14@@ -32,6 +32,8 @@
15 ppa_config = config.personalpackagearchive
16 db_pubconf = getUtility(
17 IPublisherConfigSet).getByDistribution(archive.distribution)
18+ if db_pubconf is None:
19+ return None
20
21 pubconf.temproot = os.path.join(
22 db_pubconf.root_dir, '%s-temp' % archive.distribution.name)
23
24=== modified file 'lib/lp/archivepublisher/scripts/publish_ftpmaster.py'
25--- lib/lp/archivepublisher/scripts/publish_ftpmaster.py 2011-08-22 08:03:13 +0000
26+++ lib/lp/archivepublisher/scripts/publish_ftpmaster.py 2011-08-29 17:16:29 +0000
27@@ -148,6 +148,21 @@
28 return None
29
30
31+def map_distro_pubconfigs(distro):
32+ """Return dict mapping archive purpose for distro's pub configs.
33+
34+ :param distro: `Distribution` to get publisher configs for.
35+ :return: Dict mapping archive purposes to publisher configs, insofar as
36+ they have publisher configs.
37+ """
38+ candidates = [
39+ (archive.purpose, getPubConfig(archive))
40+ for archive in get_publishable_archives(distro)]
41+ return dict(
42+ (purpose, config)
43+ for purpose, config in candidates if config is not None)
44+
45+
46 class PublishFTPMaster(LaunchpadCronScript):
47 """Publish a distro (update).
48
49@@ -241,9 +256,7 @@
50 So: getConfigs[distro][purpose] gives you a config.
51 """
52 return dict(
53- (distro, dict(
54- (archive.purpose, getPubConfig(archive))
55- for archive in get_publishable_archives(distro)))
56+ (distro, map_distro_pubconfigs(distro))
57 for distro in self.distributions)
58
59 def locateIndexesMarker(self, distribution, suite):
60@@ -536,9 +549,10 @@
61 """Publish the distro's complete uploads."""
62 self.logger.debug("Full publication. This may take some time.")
63 for archive in get_publishable_archives(distribution):
64- # This, for the main archive, is where the script spends
65- # most of its time.
66- self.publishDistroArchive(distribution, archive)
67+ if archive.purpose in self.configs[distribution]:
68+ # This, for the main archive, is where the script spends
69+ # most of its time.
70+ self.publishDistroArchive(distribution, archive)
71
72 def publish(self, distribution, security_only=False):
73 """Do the main publishing work.
74@@ -622,5 +636,6 @@
75 self.setUpDirs()
76
77 for distribution in self.distributions:
78- self.processDistro(distribution)
79- self.txn.commit()
80+ if len(self.configs[distribution]) > 0:
81+ self.processDistro(distribution)
82+ self.txn.commit()
83
84=== added file 'lib/lp/archivepublisher/tests/test_config.py'
85--- lib/lp/archivepublisher/tests/test_config.py 1970-01-01 00:00:00 +0000
86+++ lib/lp/archivepublisher/tests/test_config.py 2011-08-29 17:16:29 +0000
87@@ -0,0 +1,19 @@
88+# Copyright 2011 Canonical Ltd. This software is licensed under the
89+# GNU Affero General Public License version 3 (see the file LICENSE).
90+
91+"""Test publisher configs handling."""
92+
93+__metaclass__ = type
94+
95+from canonical.testing.layers import ZopelessDatabaseLayer
96+from lp.archivepublisher.config import getPubConfig
97+from lp.testing import TestCaseWithFactory
98+
99+
100+class TestGetPubConfig(TestCaseWithFactory):
101+
102+ layer = ZopelessDatabaseLayer
103+
104+ def test_getPubConfig_returns_None_if_no_publisherconfig_found(self):
105+ archive = self.factory.makeDistribution(no_pubconf=True).main_archive
106+ self.assertEqual(None, getPubConfig(archive))
107
108=== modified file 'lib/lp/archivepublisher/tests/test_publish_ftpmaster.py'
109--- lib/lp/archivepublisher/tests/test_publish_ftpmaster.py 2011-08-19 02:34:11 +0000
110+++ lib/lp/archivepublisher/tests/test_publish_ftpmaster.py 2011-08-29 17:16:29 +0000
111@@ -310,10 +310,20 @@
112 script.setUp()
113 self.assertEqual([distro], script.getConfigs().keys())
114
115+ def test_getConfigs_skips_configless_distros(self):
116+ distro = self.factory.makeDistribution(no_pubconf=True)
117+ script = self.makeScript(distro)
118+ script.setUp()
119+ self.assertEqual({}, script.getConfigs()[distro])
120+
121 def test_script_is_happy_with_no_publications(self):
122 distro = self.makeDistroWithPublishDirectory()
123 self.makeScript(distro).main()
124
125+ def test_script_is_happy_with_no_pubconfigs(self):
126+ distro = self.factory.makeDistribution(no_pubconf=True)
127+ self.makeScript(distro).main()
128+
129 def test_produces_listings(self):
130 distro = self.makeDistroWithPublishDirectory()
131 self.makeScript(distro).main()