Skip to content

Commit f2eda5b

Browse files
committed
linters: add ppa-version-string linter
Checks that "~ppa" is not present in uploads to the archive, or that it is present for uploads to a PPA. Also added a test for the new linter, including mock profiles to use when testing. Added a new profile for ppa uploads, which only contains the new hook for now.
1 parent a65e41e commit f2eda5b

File tree

9 files changed

+199
-1
lines changed

9 files changed

+199
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"description": "check that ppa is not present in the version string for uploads to the archive or vice versa",
3+
"path": "ubuntu_lint.dput.dput_ppa_version_string",
4+
"pre": true
5+
}

dput.d/profiles/ppa.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"+hooks": [
3+
"ppa-version-string"
4+
]
5+
}

dput.d/profiles/ubuntu.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"missing-launchpad-bugs-fixed",
55
"missing-pending-changelog-entry",
66
"missing-ubuntu-maintainer",
7+
"ppa-version-string",
78
"sru-bug-missing-release-tasks",
89
"sru-bug-missing-template",
910
"sru-version-string-breaks-upgrades"

tests/test_linters.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,39 @@
7272
Vcs-Git-Ref: refs/heads/testing
7373
""")
7474

75+
basic_changes_ppa = deb822.Changes("""
76+
Format: 1.8
77+
Date: Thu, 19 Mar 2026 19:53:17 -0700
78+
Source: hello
79+
Built-For-Profiles: derivative.ubuntu noudeb
80+
Architecture: source
81+
Version: 2.10-5ubuntu1~ppa1
82+
Distribution: resolute
83+
Urgency: medium
84+
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
85+
Changed-By: John Doe <john.doe@example.com>
86+
Changes:
87+
hello (2.10-5ubuntu1~ppa1) resolute; urgency=medium
88+
.
89+
* Testing
90+
Checksums-Sha1:
91+
93d36eb50575b7520ef1c83b9bb710e47b173485 1090 hello_2.10-5ubuntu1~ppa1.dsc
92+
f7bebf6f9c62a2295e889f66e05ce9bfaed9ace3 725946 hello_2.10.orig.tar.gz
93+
68e569d38607b4a6c49855157a7e088e7cbd29b5 13280 hello_2.10-5ubuntu1~ppa1.debian.tar.xz
94+
710b6fda80d0db1662bb1be900e16d36778e4e0c 6488 hello_2.10-5ubuntu1~ppa1_source.buildinfo
95+
Checksums-Sha256:
96+
b13071d9b7f4e7d5940cec73b21efe640894d135d8b959dac6bc77fff878728b 1090 hello_2.10-5ubuntu1~ppa1.dsc
97+
31e066137a962676e89f69d1b65382de95a7ef7d914b8cb956f41ea72e0f516b 725946 hello_2.10.orig.tar.gz
98+
8b1e3f6da54c3fc390e49cb5ee2e8079793496b0488465822754abbc91f0af27 13280 hello_2.10-5ubuntu1~ppa1.debian.tar.xz
99+
ef2fd9b53c0058c85c0b6c35752e6df068f4fa2267622a93ef922275a045ad0e 6488 hello_2.10-5ubuntu1~ppa1_source.buildinfo
100+
Files:
101+
3f9815521e1d422171f47ae52122bf81 1090 devel optional hello_2.10-5ubuntu1~ppa1.dsc
102+
6cd0ffea3884a4e79330338dcc2987d6 725946 devel optional hello_2.10.orig.tar.gz
103+
bf2ddaa879860206e8d7f93a08e148a5 13280 devel optional hello_2.10-5ubuntu1~ppa1.debian.tar.xz
104+
e7210718902f4ef005852d3b484e4eeb 6488 devel optional hello_2.10-5ubuntu1~ppa1_source.buildinfo
105+
Original-Maintainer: Santiago Vila <sanvila@debian.org>
106+
""")
107+
75108
basic_changes_sru = deb822.Changes("""
76109
Format: 1.8
77110
Date: Wed, 11 Mar 2026 16:01:41 -0400
@@ -103,6 +136,107 @@
103136
Original-Maintainer: Santiago Vila <sanvila@debian.org>
104137
""")
105138

139+
archive_upload_profile = {
140+
"name": "ubuntu",
141+
"allow_dcut": False,
142+
"allow_unsigned_uploads": False,
143+
"allowed_distributions": "(?!UNRELEASED)",
144+
"default_host_main": "ssh-ubuntu",
145+
"full_upload_log": False,
146+
"hash": "md5",
147+
"interface": "cli",
148+
"login": "anonymous",
149+
"meta": "ubuntu",
150+
"method": "ftp",
151+
"passive_ftp": True,
152+
"post_upload_command": "",
153+
"pre_upload_command": "",
154+
"run_lintian": False,
155+
"scp_compress": False,
156+
"allowed-distribution": {},
157+
"codenames": "ubuntu",
158+
"hooks": [
159+
"badauthor",
160+
"updatemaintainer",
161+
"ppaforppaonly",
162+
"badcontent",
163+
"nobug",
164+
"sure",
165+
"gitubuntu",
166+
"placeholderbug",
167+
"checksum",
168+
"suite-mismatch",
169+
"releasemismatch",
170+
"supported-distribution",
171+
"required-fields",
172+
"check-debs",
173+
"gpg",
174+
],
175+
"run_dinstall": False,
176+
"check_version": False,
177+
"progress_indicator": "2",
178+
"fqdn": "upload.ubuntu.com",
179+
"incoming": "/ubuntu",
180+
"supported-distribution": {
181+
"allowed": ["release", "proposed", "backports", "security"],
182+
"known": ["release", "proposed", "updates", "backports", "security"],
183+
},
184+
"check-debs": {"enforce": "source", "skip": False},
185+
"required-fields": {
186+
"skip": False,
187+
"fields": ["Launchpad-Bugs-Fixed"],
188+
"suites": ["any-stable"],
189+
},
190+
"valid_commands": [],
191+
}
192+
193+
ppa_upload_profile = {
194+
"name": "ppa",
195+
"allow_dcut": False,
196+
"allow_unsigned_uploads": False,
197+
"allowed_distributions": "(?!UNRELEASED)",
198+
"default_host_main": "ssh-ubuntu",
199+
"full_upload_log": False,
200+
"hash": "md5",
201+
"interface": "cli",
202+
"login": "anonymous",
203+
"meta": "ubuntu",
204+
"method": "ftp",
205+
"passive_ftp": True,
206+
"post_upload_command": "",
207+
"pre_upload_command": "",
208+
"run_lintian": False,
209+
"scp_compress": False,
210+
"allowed-distribution": {},
211+
"codenames": "ubuntu",
212+
"hooks": [
213+
"check-debs",
214+
"nobug",
215+
"badcontent",
216+
"checksum",
217+
"required-fields",
218+
"ppaforppaonly",
219+
"suite-mismatch",
220+
"badauthor",
221+
"placeholderbug",
222+
"gpg",
223+
"releasemismatch",
224+
],
225+
"run_dinstall": False,
226+
"check_version": False,
227+
"progress_indicator": "2",
228+
"fqdn": "ppa.launchpad.net",
229+
"incoming": "~johndoe/testing",
230+
"required-fields": {"skip": True},
231+
"supported-distribution": {
232+
"allowed": ["release"],
233+
"known": ["release", "proposed", "updates", "backports", "security"],
234+
},
235+
"check-debs": {"enforce": "source", "skip": False},
236+
"valid_commands": [],
237+
"ppa": "johndoe/testing",
238+
}
239+
106240

107241
def test_check_missing_ubuntu_maintainer():
108242
ubuntu_lint.check_missing_ubuntu_maintainer(
@@ -221,6 +355,26 @@ def test_check_distribution_invalid():
221355
)
222356

223357

358+
def test_check_ppa_version_string():
359+
ubuntu_lint.check_ppa_version_string(
360+
context=ubuntu_lint.Context(changes=basic_changes_ubuntu_delta, profile=archive_upload_profile)
361+
)
362+
363+
with pytest.raises(ubuntu_lint.LintFailure):
364+
ubuntu_lint.check_ppa_version_string(
365+
context=ubuntu_lint.Context(changes=basic_changes_ubuntu_delta, profile=ppa_upload_profile)
366+
)
367+
368+
ubuntu_lint.check_ppa_version_string(
369+
context=ubuntu_lint.Context(changes=basic_changes_ppa, profile=ppa_upload_profile)
370+
)
371+
372+
with pytest.raises(ubuntu_lint.LintFailure):
373+
ubuntu_lint.check_ppa_version_string(
374+
context=ubuntu_lint.Context(changes=basic_changes_ppa, profile=archive_upload_profile)
375+
)
376+
377+
224378
def test_check_sru_version_string_breaks_upgrades(requests_mock):
225379
package = basic_changes_sru.get("Source")
226380

ubuntu_lint/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
check_distribution_invalid,
1414
check_missing_git_ubuntu_references,
1515
check_missing_pending_changelog_entry,
16+
check_ppa_version_string,
1617
check_sru_bug_missing_template,
1718
check_sru_bug_missing_release_tasks,
1819
check_sru_version_string_breaks_upgrades,
@@ -29,6 +30,7 @@
2930
"check_distribution_invalid",
3031
"check_missing_git_ubuntu_references",
3132
"check_missing_pending_changelog_entry",
33+
"check_ppa_version_string",
3234
"check_sru_bug_missing_template",
3335
"check_sru_bug_missing_release_tasks",
3436
"check_sru_version_string_breaks_upgrades",

ubuntu_lint/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class Runner:
1616
"missing-launchpad-bugs-fixed": ubuntu_lint.check_missing_launchpad_bugs_fixed,
1717
"missing-pending-changelog-entry": ubuntu_lint.check_missing_pending_changelog_entry,
1818
"missing-ubuntu-maintainer": ubuntu_lint.check_missing_ubuntu_maintainer,
19+
"ppa-version-string": ubuntu_lint.check_ppa_version_string,
1920
"sru-bug-missing-template": ubuntu_lint.check_sru_bug_missing_template,
2021
"sru-bug-missing-release-tasks": ubuntu_lint.check_sru_bug_missing_release_tasks,
2122
"sru-version-string-breaks-upgrades": ubuntu_lint.check_sru_version_string_breaks_upgrades,
@@ -30,6 +31,7 @@ class Runner:
3031
"missing-launchpad-bugs-fixed": "warn",
3132
"missing-pending-changelog-entry": "warn",
3233
"missing-ubuntu-maintainer": "fail",
34+
"ppa-version-string": "fail",
3335
"sru-bug-missing-template": "off",
3436
"sru-bug-missing-release-tasks": "off",
3537
"sru-version-string-breaks-upgrades": "off",
@@ -44,6 +46,7 @@ class Runner:
4446
"missing-launchpad-bugs-fixed": "fail",
4547
"missing-pending-changelog-entry": "fail",
4648
"missing-ubuntu-maintainer": "fail",
49+
"ppa-version-string": "fail",
4750
"sru-bug-missing-template": "warn",
4851
"sru-bug-missing-release-tasks": "warn",
4952
"sru-version-string-breaks-upgrades": "warn",

ubuntu_lint/context.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def changes(self) -> deb822.Changes:
8888
assert self._changes is not None
8989

9090
return self._changes
91-
91+
9292
@property
9393
def profile(self) -> dict:
9494
if not self._profile:

ubuntu_lint/dput.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ def call_lint_as_hook(
2626
raise HookException(f"ERROR: {msg}")
2727

2828

29+
def dput_ppa_version_string(
30+
changes: Changes, profile: dict, interface: CLInterface
31+
):
32+
"""
33+
Hook wrapper around ubuntu_lint.check_ppa_version_string.
34+
"""
35+
call_lint_as_hook(
36+
ubuntu_lint.check_ppa_version_string,
37+
changes,
38+
profile,
39+
interface,
40+
)
41+
42+
2943
def dput_missing_launchpad_bugs_fixed(
3044
changes: Changes, profile: dict, interface: CLInterface
3145
):

ubuntu_lint/linters.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ def check_missing_pending_changelog_entry(context: Context):
133133
)
134134

135135

136+
def check_ppa_version_string(context: Context):
137+
"""
138+
For any upload to the archive, check that ~ppa is not present in the
139+
version string. For uploads to PPAs, check that ~ppa is present.
140+
"""
141+
version = context.changes.get_as_string("Version")
142+
target = context.profile.get("name")
143+
144+
if target == "ppa" and "~ppa" not in version:
145+
context.lint_fail("upload to ppa does not include ~ppa in version string")
146+
elif target == "ubuntu" and "~ppa" in version:
147+
context.lint_fail("upload to archive includes ~ppa in version string")
148+
149+
136150
def check_sru_bug_missing_template(context: Context):
137151
"""
138152
For uploads to stable releases, checks that bugs referenced in the changes

0 commit comments

Comments
 (0)