Merge ~cjwatson/launchpad:publish-single-archive-option into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: fe7e2924511b316b6a177feb664a4ebaa098da49
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:publish-single-archive-option
Merge into: launchpad:master
Diff against target: 129 lines (+84/-2)
2 files modified
lib/lp/archivepublisher/scripts/publishdistro.py (+18/-2)
lib/lp/archivepublisher/tests/test_publishdistro.py (+66/-0)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+435203@code.launchpad.net

Commit message

publish-distro: Add an --archive option

Description of the change

This fixes an annoyance when performing QA: `publish-distro` already had `--ppas` options and similar to tell it to run over all archives of a particular kind, but previously the only way to get it to run over a single archive was to hack the `is_ppa_public` etc. functions in place. This option should make publisher QA a little more convenient in future.

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) wrote :

LGTM 👍

P.S. I do not understand the usage of `defer.inlineCallbacks` and the `yield` statements in a test method even after reading https://docs.twisted.org/en/twisted-20.3.0/core/howto/defer-intro.html#inline-callbacks-using-yield. But as the assertions made at the end of that test look okay to me, I approved this MP.

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

The `inlineCallbacks`/`yield` stuff is because we need to run some Twisted code to set up an in-process key server and set up signing keys for test archives. That code is asynchronous - i.e. it returns a `Deferred`, which is a promise to eventually deliver either a result or an error, rather than directly returning a result, because it's doing network communication that might block.

However, in the case of this test we essentially just want to convert that asynchronous code into synchronous code by waiting for each deferred result to appear. `yield` within `inlineCallbacks` does that. Technically this is a generator, but it's best not to think of it as generating a sequence of values: just think of each `yield` as a point where we stop and wait for some asynchronous code to complete, and you'll be pretty close.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/archivepublisher/scripts/publishdistro.py b/lib/lp/archivepublisher/scripts/publishdistro.py
2index 85511be..6c93a6e 100644
3--- a/lib/lp/archivepublisher/scripts/publishdistro.py
4+++ b/lib/lp/archivepublisher/scripts/publishdistro.py
5@@ -202,6 +202,13 @@ class PublishDistro(PublisherScript):
6 help="Only run over the copy archives.",
7 )
8
9+ self.parser.add_option(
10+ "--archive",
11+ dest="archive",
12+ metavar="REFERENCE",
13+ help="Only run over the archive identified by this reference.",
14+ )
15+
16 def isCareful(self, option):
17 """Is the given "carefulness" option enabled?
18
19@@ -243,6 +250,7 @@ class PublishDistro(PublisherScript):
20 self.options.ppa,
21 self.options.private_ppa,
22 self.options.copy_archive,
23+ self.options.archive,
24 ]
25 return len(list(filter(None, exclusive_options)))
26
27@@ -271,7 +279,7 @@ class PublishDistro(PublisherScript):
28 if self.countExclusiveOptions() > 1:
29 raise OptionValueError(
30 "Can only specify one of partner, ppa, private-ppa, "
31- "copy-archive."
32+ "copy-archive, archive."
33 )
34
35 if self.options.all_derived and self.options.distribution is not None:
36@@ -342,7 +350,15 @@ class PublishDistro(PublisherScript):
37
38 def getTargetArchives(self, distribution):
39 """Find the archive(s) selected by the script's options."""
40- if self.options.partner:
41+ if self.options.archive:
42+ archive = getUtility(IArchiveSet).getByReference(
43+ self.options.archive
44+ )
45+ if archive.distribution == distribution:
46+ return [archive]
47+ else:
48+ return []
49+ elif self.options.partner:
50 return [distribution.getArchiveByComponent("partner")]
51 elif self.options.ppa:
52 return filter(is_ppa_public, self.getPPAs(distribution))
53diff --git a/lib/lp/archivepublisher/tests/test_publishdistro.py b/lib/lp/archivepublisher/tests/test_publishdistro.py
54index 96ade8e..f99ee6e 100644
55--- a/lib/lp/archivepublisher/tests/test_publishdistro.py
56+++ b/lib/lp/archivepublisher/tests/test_publishdistro.py
57@@ -445,6 +445,72 @@ class TestPublishDistro(TestNativePublishingBase):
58 pool_path = os.path.join(repo_path, "pool/main/b/baz/baz_666.dsc")
59 self.assertExists(pool_path)
60
61+ @defer.inlineCallbacks
62+ def testForSingleArchive(self):
63+ """Run publish-distro over a single archive specified by reference."""
64+ ubuntutest = getUtility(IDistributionSet)["ubuntutest"]
65+ name16 = getUtility(IPersonSet).getByName("name16")
66+ archives = [
67+ getUtility(IArchiveSet).new(
68+ purpose=ArchivePurpose.PPA,
69+ owner=name16,
70+ name=name,
71+ distribution=ubuntutest,
72+ )
73+ for name in (
74+ self.factory.getUniqueUnicode(),
75+ self.factory.getUniqueUnicode(),
76+ )
77+ ]
78+ archive_references = [archive.reference for archive in archives]
79+ pub_source_ids = [
80+ self.getPubSource(archive=archive).id for archive in archives
81+ ]
82+
83+ self.setUpRequireSigningKeys()
84+ yield self.useFixture(InProcessKeyServerFixture()).start()
85+ key_path = os.path.join(gpgkeysdir, "ppa-sample@canonical.com.sec")
86+ for archive in archives:
87+ yield IArchiveGPGSigningKey(archive).setSigningKey(
88+ key_path, async_keyserver=True
89+ )
90+
91+ self.layer.txn.commit()
92+
93+ self.assertEqual(
94+ [PackagePublishingStatus.PENDING, PackagePublishingStatus.PENDING],
95+ [
96+ self.loadPubSource(pub_source_id).status
97+ for pub_source_id in pub_source_ids
98+ ],
99+ )
100+
101+ self.runPublishDistro(["--archive", archive_references[0]])
102+
103+ self.assertEqual(
104+ [
105+ PackagePublishingStatus.PUBLISHED,
106+ PackagePublishingStatus.PENDING,
107+ ],
108+ [
109+ self.loadPubSource(pub_source_id).status
110+ for pub_source_id in pub_source_ids
111+ ],
112+ )
113+
114+ self.runPublishDistro(["--archive", archive_references[1]])
115+
116+ self.assertEqual(
117+ [
118+ PackagePublishingStatus.PUBLISHED,
119+ PackagePublishingStatus.PUBLISHED,
120+ ],
121+ [
122+ self.loadPubSource(pub_source_id).status
123+ for pub_source_id in pub_source_ids
124+ ],
125+ )
126+
127 def testPublishToArtifactory(self):
128 """Publishing to Artifactory doesn't require generated signing keys."""
129 self.setUpRequireSigningKeys()

Subscribers

People subscribed via source and target branches

to status/vote changes: