Merge ~cjwatson/launchpad:generic-artifactory-properties into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 01a8cbb40e6ded42f1d92e55cb166b2af7463e17
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:generic-artifactory-properties
Merge into: launchpad:master
Prerequisite: ~cjwatson/launchpad:artifactory-strip-trailing-backslashes
Diff against target: 483 lines (+85/-2)
4 files modified
lib/lp/archivepublisher/artifactory.py (+28/-1)
lib/lp/archivepublisher/tests/test_artifactory.py (+43/-0)
lib/lp/archivepublisher/tests/test_pool.py (+7/-1)
lib/lp/archivepublisher/tests/test_publisher.py (+7/-0)
Reviewer Review Type Date Requested Status
Jürgen Gmach Approve
Review via email: mp+434496@code.launchpad.net

Commit message

Add generic.name, generic.version, and soss.type Artifactory properties

Description of the change

For most artifact types, Artifactory sets "name" and "version" properties itself by scanning the artifact. However, for generic artifacts it obviously can't do this, since the content doesn't necessarily have any particular known structure. Since we already require generic artifacts to have "name" and "version" output properties set by the build job, fill in this gap by passing those on to Artifactory.

`soss.type` makes it easier for automation built on top of Artifactory to tell what any given artifact is meant to be, without having to look at the `launchpad.*` properties which we consider to be implementation details.

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

LGTM

I think it would be great to have some description of the properties in the docstring at least. Currently, it feels a bit that like we set some properties somehow and somewhere, but for unknown reasons.

I think it makes no sense to repeat the logic of the source code, but somehow give some spec, e.g. what properties are expected.

review: Approve
01a8cbb... by Colin Watson

Add some more commentary on additional properties

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

There's already a comment a bit further up (outside the patch context) linking to the internal spreadsheet with the property schema we intend to expose. I've added a bit more commentary now though, as this might indeed be a bit obscure if you haven't been in all the discussions ...

Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thank you!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/archivepublisher/artifactory.py b/lib/lp/archivepublisher/artifactory.py
2index 9fc4fc7..2d16d99 100644
3--- a/lib/lp/archivepublisher/artifactory.py
4+++ b/lib/lp/archivepublisher/artifactory.py
5@@ -22,9 +22,10 @@ from packaging import utils as packaging_utils
6 from zope.security.proxy import isinstance as zope_isinstance
7
8 from lp.archivepublisher.diskpool import FileAddActionEnum, poolify
9+from lp.registry.interfaces.sourcepackage import SourcePackageFileType
10 from lp.services.config import config
11 from lp.services.librarian.utils import copy_and_close
12-from lp.soyuz.enums import ArchiveRepositoryFormat
13+from lp.soyuz.enums import ArchiveRepositoryFormat, BinaryPackageFileType
14 from lp.soyuz.interfaces.archive import IArchive
15 from lp.soyuz.interfaces.files import (
16 IBinaryPackageFile,
17@@ -205,6 +206,10 @@ class ArtifactoryPoolEntry:
18 the AQL search via `ArtifactoryPool.getAllArtifacts`, and so
19 `updateProperties` will always try to update them even if there
20 aren't really any changes.
21+
22+ We also set an assortment of additional metadata items, specified in
23+ https://docs.google.com/spreadsheets/d/15Xkdi-CRu2NiQfLoclP5PKW63Zw6syiuao8VJG7zxvw
24+ (private).
25 """
26 properties = {}
27 properties["launchpad.release-id"] = [release_id]
28@@ -271,8 +276,14 @@ class ArtifactoryPoolEntry:
29 # (private).
30 if ISourcePackageReleaseFile.providedBy(self.pub_file):
31 release = self.pub_file.sourcepackagerelease
32+ # Allow automation built on top of Artifactory to tell that this
33+ # is a source package.
34+ properties["soss.type"] = ["source"]
35 elif IBinaryPackageFile.providedBy(self.pub_file):
36 release = self.pub_file.binarypackagerelease
37+ # Allow automation built on top of Artifactory to tell that this
38+ # is a binary package.
39+ properties["soss.type"] = ["binary"]
40 else:
41 # There are no other kinds of `IPackageReleaseFile` at the moment.
42 raise AssertionError("Unsupported file: %r" % self.pub_file)
43@@ -298,6 +309,22 @@ class ArtifactoryPoolEntry:
44 # likely that a path will begin with "spdx:" so there
45 # probably won't be significant confusion in practice.
46 properties["soss.license"] = [license_field["path"]]
47+ if self.pub_file.filetype in (
48+ SourcePackageFileType.GENERIC,
49+ BinaryPackageFileType.GENERIC,
50+ ):
51+ # For most artifact types, Artifactory sets "name" and "version"
52+ # properties itself by scanning the artifact. However, for
53+ # generic artifacts it obviously can't do this, since the
54+ # content doesn't necessarily have any particular known
55+ # structure. Since we already require generic artifacts to have
56+ # "name" and "version" output properties set by the build job,
57+ # fill in this gap by passing those on to Artifactory.
58+ package_name = release.getUserDefinedField("name")
59+ if package_name is None:
60+ package_name = self.source_name
61+ properties["generic.name"] = [package_name]
62+ properties["generic.version"] = [self.source_version]
63 return properties
64
65 def addFile(self):
66diff --git a/lib/lp/archivepublisher/tests/test_artifactory.py b/lib/lp/archivepublisher/tests/test_artifactory.py
67index 4179c2e..da1a31a 100644
68--- a/lib/lp/archivepublisher/tests/test_artifactory.py
69+++ b/lib/lp/archivepublisher/tests/test_artifactory.py
70@@ -192,6 +192,7 @@ class TestArtifactoryPool(TestCase):
71 "launchpad.release-id": ["binary:1"],
72 "launchpad.source-name": ["foo"],
73 "launchpad.source-version": ["1.0+1"],
74+ "soss.type": ["binary"],
75 },
76 foo.getProperties(),
77 )
78@@ -317,11 +318,13 @@ class TestArtifactoryPool(TestCase):
79 "launchpad.release-id": ["binary:1"],
80 "launchpad.source-name": ["foo"],
81 "launchpad.source-version": ["1.0"],
82+ "soss.type": ["binary"],
83 },
84 PurePath("pool/f/foo/foo-1.1.deb"): {
85 "launchpad.release-id": ["binary:2"],
86 "launchpad.source-name": ["foo"],
87 "launchpad.source-version": ["1.1"],
88+ "soss.type": ["binary"],
89 },
90 },
91 pool.getAllArtifacts(
92@@ -345,6 +348,7 @@ class TestArtifactoryPool(TestCase):
93 "launchpad.release-id": ["binary:3"],
94 "launchpad.source-name": ["bar"],
95 "launchpad.source-version": ["1.0"],
96+ "soss.type": ["binary"],
97 },
98 },
99 pool.getAllArtifacts(
100@@ -369,6 +373,7 @@ class TestArtifactoryPool(TestCase):
101 "launchpad.release-id": ["binary:4"],
102 "launchpad.source-name": ["qux"],
103 "launchpad.source-version": ["1.0"],
104+ "soss.type": ["binary"],
105 },
106 },
107 pool.getAllArtifacts(
108@@ -393,6 +398,7 @@ class TestArtifactoryPool(TestCase):
109 "launchpad.release-id": ["source:5"],
110 "launchpad.source-name": ["go-module"],
111 "launchpad.source-version": ["v0.0.1"],
112+ "soss.type": ["source"],
113 },
114 },
115 pool.getAllArtifacts(
116@@ -409,6 +415,7 @@ class TestArtifactoryPool(TestCase):
117 filename="bar-1.0.tar.gz",
118 release_type=FakeReleaseType.SOURCE,
119 release_id=1,
120+ filetype=SourcePackageFileType.GENERIC,
121 user_defined_fields=[
122 ("name", "bar"),
123 ("version", "1.0"),
124@@ -418,9 +425,12 @@ class TestArtifactoryPool(TestCase):
125 self.assertEqual(
126 {
127 PurePath("bar/1.0/bar-1.0.tar.gz"): {
128+ "generic.name": ["bar"],
129+ "generic.version": ["1.0"],
130 "launchpad.release-id": ["source:1"],
131 "launchpad.source-name": ["bar"],
132 "launchpad.source-version": ["1.0"],
133+ "soss.type": ["source"],
134 },
135 },
136 pool.getAllArtifacts(
137@@ -453,6 +463,7 @@ class TestArtifactoryPool(TestCase):
138 "launchpad.source-name": ["bar"],
139 "launchpad.source-version": ["1.0"],
140 "pypi.requires.python": [""],
141+ "soss.type": ["binary"],
142 },
143 },
144 pool.getAllArtifacts(
145@@ -521,6 +532,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
146 "launchpad.release-id": ["source:%d" % spr.id],
147 "launchpad.source-name": ["foo"],
148 "launchpad.source-version": ["1.0"],
149+ "soss.type": ["source"],
150 },
151 path.properties,
152 )
153@@ -535,6 +547,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
154 "deb.name": [spr.name],
155 "deb.version": [spr.version],
156 "soss.license": ["debian/copyright"],
157+ "soss.type": ["source"],
158 },
159 path.properties,
160 )
161@@ -594,6 +607,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
162 "launchpad.release-id": ["binary:%d" % bpr.id],
163 "launchpad.source-name": ["foo"],
164 "launchpad.source-version": ["1.0"],
165+ "soss.type": ["binary"],
166 },
167 path.properties,
168 )
169@@ -609,6 +623,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
170 "deb.component": ["main"],
171 "deb.architecture": [processor.name],
172 "soss.license": ["/usr/share/doc/foo/copyright"],
173+ "soss.type": ["binary"],
174 },
175 path.properties,
176 )
177@@ -662,6 +677,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
178 "launchpad.release-id": ["binary:%d" % bpr.id],
179 "launchpad.source-name": ["foo"],
180 "launchpad.source-version": ["1.0"],
181+ "soss.type": ["binary"],
182 },
183 path.properties,
184 )
185@@ -679,6 +695,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
186 sorted(das.architecturetag for das in dases)
187 ),
188 "soss.license": ["/usr/share/doc/foo/copyright"],
189+ "soss.type": ["binary"],
190 },
191 path.properties,
192 )
193@@ -738,6 +755,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
194 ci_build.git_repository.getCodebrowseUrl()
195 ],
196 "soss.commit_id": [ci_build.commit_sha1],
197+ "soss.type": ["source"],
198 },
199 path.properties,
200 )
201@@ -754,6 +772,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
202 ci_build.git_repository.getCodebrowseUrl()
203 ],
204 "soss.commit_id": [ci_build.commit_sha1],
205+ "soss.type": ["source"],
206 },
207 path.properties,
208 )
209@@ -814,6 +833,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
210 ci_build.git_repository.getCodebrowseUrl()
211 ],
212 "soss.commit_id": [ci_build.commit_sha1],
213+ "soss.type": ["source"],
214 },
215 path.properties,
216 )
217@@ -830,6 +850,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
218 ci_build.git_repository.getCodebrowseUrl()
219 ],
220 "soss.commit_id": [ci_build.commit_sha1],
221+ "soss.type": ["source"],
222 },
223 path.properties,
224 )
225@@ -889,6 +910,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
226 ci_build.git_repository.getCodebrowseUrl()
227 ],
228 "soss.commit_id": [ci_build.commit_sha1],
229+ "soss.type": ["source"],
230 },
231 path.properties,
232 )
233@@ -905,6 +927,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
234 ci_build.git_repository.getCodebrowseUrl()
235 ],
236 "soss.commit_id": [ci_build.commit_sha1],
237+ "soss.type": ["source"],
238 },
239 path.properties,
240 )
241@@ -981,6 +1004,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
242 ci_build.git_repository.getCodebrowseUrl()
243 ],
244 "soss.commit_id": [ci_build.commit_sha1],
245+ "soss.type": ["binary"],
246 },
247 path.properties,
248 )
249@@ -997,6 +1021,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
250 ci_build.git_repository.getCodebrowseUrl()
251 ],
252 "soss.commit_id": [ci_build.commit_sha1],
253+ "soss.type": ["binary"],
254 },
255 path.properties,
256 )
257@@ -1064,6 +1089,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
258 ci_build.git_repository.getCodebrowseUrl()
259 ],
260 "soss.commit_id": [ci_build.commit_sha1],
261+ "soss.type": ["binary"],
262 },
263 path.properties,
264 )
265@@ -1080,6 +1106,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
266 ci_build.git_repository.getCodebrowseUrl()
267 ],
268 "soss.commit_id": [ci_build.commit_sha1],
269+ "soss.type": ["binary"],
270 },
271 path.properties,
272 )
273@@ -1147,6 +1174,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
274 ci_build.git_repository.getCodebrowseUrl()
275 ],
276 "soss.commit_id": [ci_build.commit_sha1],
277+ "soss.type": ["binary"],
278 },
279 path.properties,
280 )
281@@ -1163,6 +1191,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
282 ci_build.git_repository.getCodebrowseUrl()
283 ],
284 "soss.commit_id": [ci_build.commit_sha1],
285+ "soss.type": ["binary"],
286 },
287 path.properties,
288 )
289@@ -1219,6 +1248,8 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
290 self.assertFalse(path.is_symlink())
291 self.assertEqual(
292 {
293+ "generic.name": ["foo"],
294+ "generic.version": ["1.0"],
295 "launchpad.release-id": ["source:%d" % spr.id],
296 "launchpad.source-name": ["foo-package"],
297 "launchpad.source-version": ["1.0"],
298@@ -1226,12 +1257,15 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
299 ci_build.git_repository.getCodebrowseUrl()
300 ],
301 "soss.commit_id": [ci_build.commit_sha1],
302+ "soss.type": ["source"],
303 },
304 path.properties,
305 )
306 pool.updateProperties(spr.name, spr.version, [sprf], spphs)
307 self.assertEqual(
308 {
309+ "generic.name": ["foo"],
310+ "generic.version": ["1.0"],
311 "launchpad.release-id": ["source:%d" % spr.id],
312 "launchpad.source-name": ["foo-package"],
313 "launchpad.source-version": ["1.0"],
314@@ -1242,6 +1276,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
315 ci_build.git_repository.getCodebrowseUrl()
316 ],
317 "soss.commit_id": [ci_build.commit_sha1],
318+ "soss.type": ["source"],
319 },
320 path.properties,
321 )
322@@ -1302,6 +1337,8 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
323 self.assertFalse(path.is_symlink())
324 self.assertEqual(
325 {
326+ "generic.name": ["foo"],
327+ "generic.version": ["1.0"],
328 "launchpad.release-id": ["binary:%d" % bpr.id],
329 "launchpad.source-name": ["foo"],
330 "launchpad.source-version": ["1.0"],
331@@ -1309,12 +1346,15 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
332 ci_build.git_repository.getCodebrowseUrl()
333 ],
334 "soss.commit_id": [ci_build.commit_sha1],
335+ "soss.type": ["binary"],
336 },
337 path.properties,
338 )
339 pool.updateProperties(bpph.pool_name, bpph.pool_version, [bpf], bpphs)
340 self.assertEqual(
341 {
342+ "generic.name": ["foo"],
343+ "generic.version": ["1.0"],
344 "launchpad.release-id": ["binary:%d" % bpr.id],
345 "launchpad.source-name": ["foo"],
346 "launchpad.source-version": ["1.0"],
347@@ -1325,6 +1365,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
348 ci_build.git_repository.getCodebrowseUrl()
349 ],
350 "soss.commit_id": [ci_build.commit_sha1],
351+ "soss.type": ["binary"],
352 },
353 path.properties,
354 )
355@@ -1377,6 +1418,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
356 "launchpad.source-name": ["foo"],
357 "launchpad.source-version": ["1.0"],
358 "deb.version": ["1.0"],
359+ "soss.type": ["binary"],
360 },
361 path.properties,
362 )
363@@ -1393,6 +1435,7 @@ class TestArtifactoryPoolFromLibrarian(TestCaseWithFactory):
364 "deb.architecture": [das.architecturetag],
365 "deb.version": ["1.0"],
366 "soss.license": ["/usr/share/doc/foo/copyright"],
367+ "soss.type": ["binary"],
368 },
369 path.properties,
370 )
371diff --git a/lib/lp/archivepublisher/tests/test_pool.py b/lib/lp/archivepublisher/tests/test_pool.py
372index a4d4cf5..6e515ad 100644
373--- a/lib/lp/archivepublisher/tests/test_pool.py
374+++ b/lib/lp/archivepublisher/tests/test_pool.py
375@@ -10,8 +10,9 @@ from lazr.enum import EnumeratedType, Item
376 from zope.interface import alsoProvides, implementer
377
378 from lp.archivepublisher.diskpool import DiskPool, poolify, unpoolify
379+from lp.registry.interfaces.sourcepackage import SourcePackageFileType
380 from lp.services.log.logger import BufferLogger
381-from lp.soyuz.enums import ArchiveRepositoryFormat
382+from lp.soyuz.enums import ArchiveRepositoryFormat, BinaryPackageFileType
383 from lp.soyuz.interfaces.files import (
384 IBinaryPackageFile,
385 IPackageReleaseFile,
386@@ -78,11 +79,13 @@ class FakePackageReleaseFile:
387 filename,
388 release_type=FakeReleaseType.BINARY,
389 release_id=1,
390+ filetype=None,
391 user_defined_fields=None,
392 ci_build=None,
393 ):
394 self.libraryfile = FakeLibraryFileAlias(contents, filename)
395 if release_type == FakeReleaseType.SOURCE:
396+ self.filetype = filetype or SourcePackageFileType.DSC
397 self.sourcepackagereleaseID = release_id
398 self.sourcepackagerelease = FakePackageRelease(
399 release_id,
400@@ -91,6 +94,7 @@ class FakePackageReleaseFile:
401 )
402 alsoProvides(self, ISourcePackageReleaseFile)
403 elif release_type == FakeReleaseType.BINARY:
404+ self.filetype = filetype or BinaryPackageFileType.DEB
405 self.binarypackagereleaseID = release_id
406 self.binarypackagerelease = FakePackageRelease(
407 release_id, user_defined_fields=user_defined_fields
408@@ -107,6 +111,7 @@ class PoolTestingFile:
409 filename,
410 release_type=FakeReleaseType.BINARY,
411 release_id=1,
412+ filetype=None,
413 user_defined_fields=None,
414 ):
415 self.pool = pool
416@@ -117,6 +122,7 @@ class PoolTestingFile:
417 filename,
418 release_type=release_type,
419 release_id=release_id,
420+ filetype=filetype,
421 user_defined_fields=user_defined_fields,
422 )
423
424diff --git a/lib/lp/archivepublisher/tests/test_publisher.py b/lib/lp/archivepublisher/tests/test_publisher.py
425index e52d5a3..44f54c3 100644
426--- a/lib/lp/archivepublisher/tests/test_publisher.py
427+++ b/lib/lp/archivepublisher/tests/test_publisher.py
428@@ -4221,6 +4221,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
429 "launchpad.source-name": ["hello"],
430 "launchpad.source-version": ["1.0"],
431 "soss.license": ["debian/copyright"],
432+ "soss.type": ["source"],
433 },
434 source_path.properties,
435 )
436@@ -4241,6 +4242,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
437 "launchpad.source-name": ["hello"],
438 "launchpad.source-version": ["1.0"],
439 "soss.license": ["/usr/share/doc/hello/copyright"],
440+ "soss.type": ["binary"],
441 },
442 binary_path.properties,
443 )
444@@ -4318,6 +4320,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
445 "launchpad.source-name": ["hello"],
446 "launchpad.source-version": ["1.0"],
447 "soss.license": ["debian/copyright"],
448+ "soss.type": ["source"],
449 },
450 dsc_path.properties,
451 )
452@@ -4333,6 +4336,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
453 "launchpad.source-name": ["hello"],
454 "launchpad.source-version": ["1.0"],
455 "soss.license": ["debian/copyright"],
456+ "soss.type": ["source"],
457 },
458 tar_path.properties,
459 )
460@@ -4347,6 +4351,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
461 "launchpad.source-name": ["hello"],
462 "launchpad.source-version": ["1.0"],
463 "soss.license": ["/usr/share/doc/hello/copyright"],
464+ "soss.type": ["binary"],
465 },
466 binary_path.properties,
467 )
468@@ -4408,6 +4413,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
469 "launchpad.source-name": ["hello"],
470 "launchpad.source-version": ["1.0"],
471 "soss.license": ["debian/copyright"],
472+ "soss.type": ["source"],
473 },
474 source_path.properties,
475 )
476@@ -4419,6 +4425,7 @@ class TestArtifactoryPublishing(TestPublisherBase):
477 "launchpad.source-name": ["hello"],
478 "launchpad.source-version": ["1.0"],
479 "soss.license": ["/usr/share/doc/hello/copyright"],
480+ "soss.type": ["binary"],
481 },
482 binary_path.properties,
483 )

Subscribers

People subscribed via source and target branches

to status/vote changes: