Merge ppa-dev-tools:trigger-action-urls into ppa-dev-tools:main

Proposed by Bryce Harrington
Status: Merged
Merge reported by: Bryce Harrington
Merged at revision: 6c02046c2d30b1f59b30cb5485c57d806de3afaa
Proposed branch: ppa-dev-tools:trigger-action-urls
Merge into: ppa-dev-tools:main
Diff against target: 237 lines (+84/-29)
4 files modified
ppa/ppa.py (+6/-7)
ppa/trigger.py (+31/-5)
scripts/ppa (+19/-4)
tests/test_trigger.py (+28/-13)
Reviewer Review Type Date Requested Status
Christian Ehrhardt  (community) Approve
Canonical Server Pending
Canonical Server Reporter Pending
Review via email: mp+431541@code.launchpad.net

Description of the change

Starts integrating Trigger objects into the `ppa tests` command, and adds the action urls (the urls that actually cause autopkgtest to fire up the tests). Also adds the PPA element to the Triggers, which for now are required but later I think I could make that optional in order to make this code work for triggering directly against -proposed.

For now this just dumps the action urls to the output.

To post a comment you must log in.
Revision history for this message
Christian Ehrhardt  (paelzer) wrote :

I'm generally +1 this is small and a good step forward.
One question on URL escaping and testing it below.
Feel free to add it here or putting it onto your known-todo-list.

review: Approve
Revision history for this message
Bryce Harrington (bryce) wrote :

Thanks, I'll get the encoding added for the urls, and accompanying tests, then will land.

Revision history for this message
Bryce Harrington (bryce) wrote :

I did a minor reimplementation of action_url() to use urlencode, updated test cases, and landed the branch. Thanks again!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/ppa/ppa.py b/ppa/ppa.py
2index 763ed7f..f26a1ea 100755
3--- a/ppa/ppa.py
4+++ b/ppa/ppa.py
5@@ -108,13 +108,12 @@ class Ppa:
6 f'ppa_name={self.ppa_name!r}, team_name={self.team_name!r})')
7
8 def __str__(self):
9- s = ''
10- s += "ppa: {}\n".format(self.name)
11- s += "address: {}\n".format(self.address)
12- s += "url: {}\n".format(self.url)
13- s += "description:\n"
14- s += indent(self.description, 4)
15- return s
16+ """Returns a displayable string identifying the PPA.
17+
18+ :rtype: str
19+ :returns: Displayable representation of the PPA.
20+ """
21+ return f"{self.team_name}/{self.name}"
22
23 @property
24 def archive(self):
25diff --git a/ppa/trigger.py b/ppa/trigger.py
26index 79276da..42e4d00 100755
27--- a/ppa/trigger.py
28+++ b/ppa/trigger.py
29@@ -26,18 +26,20 @@ class Trigger:
30 package and/or architectures, but all such Triggers must be against
31 the same series as the Job itself.
32 """
33- def __init__(self, package, version, arch, series):
34+ def __init__(self, package, version, arch, series, ppa):
35 """Initializes a new Trigger for a given package and version.
36
37 :param str package: The source package name.
38 :param str version: The version of the source package to install.
39 :param str arch: The architecture for the trigger.
40 :param str series: The distro release series codename.
41+ :param Ppa ppa: (Optional) PPA wrapper object to run tests against.
42 """
43 self.package = package
44 self.version = version
45 self.arch = arch
46 self.series = series
47+ self.ppa = ppa
48
49 def __repr__(self) -> str:
50 """Machine-parsable unique representation of object.
51@@ -47,7 +49,7 @@ class Trigger:
52 """
53 return (f'{self.__class__.__name__}('
54 f'package={self.package!r}, version={self.version!r}, '
55- f'arch={self.arch!r}, series={self.series!r})')
56+ f'arch={self.arch!r}, series={self.series!r}, ppa={self.ppa!r})')
57
58 def __str__(self) -> str:
59 """Human-readable summary of the object.
60@@ -58,11 +60,11 @@ class Trigger:
61 return f"{self.package}/{self.version}"
62
63 @cached_property
64- def autopkgtest_url(self) -> str:
65+ def history_url(self) -> str:
66 """Renders the trigger as a URL to the job history.
67
68 :rtype: str
69- :returns: tbd
70+ :returns: Job history URL
71 """
72 if self.package.startswith('lib'):
73 prefix = self.package[0:4]
74@@ -71,10 +73,34 @@ class Trigger:
75 pkg_str = f"{prefix}/{self.package}"
76 return f"{URL_AUTOPKGTEST}/packages/{pkg_str}/{self.series}/{self.arch}"
77
78+ @cached_property
79+ def action_url(self) -> str:
80+ """Renders the trigger as a URL to start running the test.
81+
82+ :rtype: str
83+ :returns: Trigger action URL
84+ """
85+ elements = [
86+ f"release={self.series}",
87+ f"package={self.package}",
88+ f"arch={self.arch}",
89+ ]
90+
91+ # Trigger for the source package itself
92+ elements.append(f"trigger={self.package}/{self.version}")
93+
94+ # TODO: Additional triggers...
95+
96+ # The PPA, if one is defined for this trigger
97+ if self.ppa:
98+ elements.append(f"ppa={self.ppa}")
99+
100+ return f"{URL_AUTOPKGTEST}/request.cgi?" + "&".join(elements)
101+
102
103 if __name__ == "__main__":
104 print("### Trigger class smoke test ###")
105
106 trigger = Trigger('my-package', '1.2.3', 'amd64', 'kinetic')
107 print(trigger)
108- print(trigger.autopkgtest_url)
109+ print(trigger.history_url)
110diff --git a/scripts/ppa b/scripts/ppa
111index 1607342..55a6211 100755
112--- a/scripts/ppa
113+++ b/scripts/ppa
114@@ -83,6 +83,7 @@ from ppa.result import (
115 get_results
116 )
117 from ppa.text import o2str
118+from ppa.trigger import Trigger
119
120 import ppa.debug
121 from ppa.debug import dbg, die, warn
122@@ -373,7 +374,12 @@ def command_show(lp, config):
123 arch = None
124 try:
125 ppa = get_ppa(lp, config)
126- print(ppa)
127+ print(f"ppa: {self.name}")
128+ print(f"address: {self.address}")
129+ print(f"url: {self.url}")
130+ print(f"description:")
131+ print(indent(self.description, 4))
132+
133 print("sources:")
134 for source in ppa.get_source_publications(distro, series, arch):
135 print(" %s (%s) %s" % (
136@@ -486,7 +492,16 @@ def command_tests(lp, config):
137
138 try:
139 ppa = get_ppa(lp, config)
140- target = "%s/%s" % (ppa.team_name, ppa.name)
141+ for source_pub in ppa.get_source_publications():
142+ # Triggers
143+ for arch in ARCHES_AUTOPKGTEST:
144+ trigger = Trigger(
145+ package=source_pub.source_package_name,
146+ version=source_pub.source_package_version,
147+ arch=arch,
148+ series=source_pub.distro_series.name,
149+ ppa=ppa)
150+ print(trigger.action_url)
151
152 # Results
153 base_results_fmt = f"{URL_AUTOPKGTEST}/results/autopkgtest-%s-%s-%s/"
154@@ -507,13 +522,13 @@ def command_tests(lp, config):
155 # Running Queue
156 response = open_url(f"{URL_AUTOPKGTEST}/static/running.json", "running autopkgtests")
157 if response:
158- show_running(sorted(get_running(response, series=release, ppa=target),
159+ show_running(sorted(get_running(response, series=release, ppa=str(ppa)),
160 key=lambda k: str(k.submit_time)))
161
162 # Waiting Queue
163 response = open_url(f"{URL_AUTOPKGTEST}/queues.json", "waiting autopkgtests")
164 if response:
165- show_waiting(get_waiting(response, series=release, ppa=target))
166+ show_waiting(get_waiting(response, series=release, ppa=str(ppa)))
167
168 return os.EX_OK
169 except KeyboardInterrupt:
170diff --git a/tests/test_trigger.py b/tests/test_trigger.py
171index c6b6a6b..318f034 100644
172--- a/tests/test_trigger.py
173+++ b/tests/test_trigger.py
174@@ -21,35 +21,50 @@ from ppa.trigger import Trigger
175
176 def test_object():
177 """Checks that Trigger objects can be instantiated."""
178- trigger = Trigger('a', 'b', 'c', 'd')
179+ trigger = Trigger('a', 'b', 'c', 'd', 'e')
180 assert trigger
181
182
183 def test_repr():
184 """Checks Trigger object representation."""
185- trigger = Trigger('a', 'b', 'c', 'd')
186- assert repr(trigger) == "Trigger(package='a', version='b', arch='c', series='d')"
187+ trigger = Trigger('a', 'b', 'c', 'd', 'e')
188+ assert repr(trigger) == "Trigger(package='a', version='b', arch='c', series='d', ppa='e')"
189
190
191 def test_str():
192 """Checks Trigger object textual presentation."""
193- trigger = Trigger('a', 'b', 'c', 'd')
194+ trigger = Trigger('a', 'b', 'c', 'd', 'e')
195 assert f"{trigger}" == 'a/b'
196
197- trigger = Trigger('dovecot', '1:2.3.19.1+dfsg1-2ubuntu2', 'i386', 'kinetic')
198+ trigger = Trigger('dovecot', '1:2.3.19.1+dfsg1-2ubuntu2', 'i386', 'kinetic', None)
199 assert f"{trigger}" == 'dovecot/1:2.3.19.1+dfsg1-2ubuntu2'
200
201
202-def test_autopkgtest_url():
203- """Checks that Trigger objects generate valid autopkgtest urls"""
204- trigger = Trigger('a', 'b', 'c', 'd')
205+def test_history_url():
206+ """Checks that Trigger objects generate valid autopkgtest history urls"""
207+ trigger = Trigger('a', 'b', 'c', 'd', 'e')
208 expected = "https://autopkgtest.ubuntu.com/packages/a/a/d/c"
209- assert trigger.autopkgtest_url == expected
210+ assert trigger.history_url == expected
211
212- trigger = Trigger('apache2', '2.4', 'amd64', 'kinetic')
213+ trigger = Trigger('apache2', '2.4', 'amd64', 'kinetic', None)
214 expected = "https://autopkgtest.ubuntu.com/packages/a/apache2/kinetic/amd64"
215- assert trigger.autopkgtest_url == expected
216+ assert trigger.history_url == expected
217
218- trigger = Trigger('libwebsockets', '4.1.6-3', 'armhf', 'jammy')
219+ trigger = Trigger('libwebsockets', '4.1.6-3', 'armhf', 'jammy', None)
220 expected = "https://autopkgtest.ubuntu.com/packages/libw/libwebsockets/jammy/armhf"
221- assert trigger.autopkgtest_url == expected
222+ assert trigger.history_url == expected
223+
224+
225+def test_action_url():
226+ """Checks that Trigger objects generate valid autopkgtest action urls"""
227+ trigger = Trigger('a', 'b', 'c', 'd', 'e')
228+ expected = "https://autopkgtest.ubuntu.com/request.cgi?release=d&package=a&arch=c&trigger=a/b&ppa=e"
229+ assert trigger.action_url == expected
230+
231+ trigger = Trigger('apache2', '2.4', 'amd64', 'kinetic', None)
232+ expected = "https://autopkgtest.ubuntu.com/request.cgi?release=kinetic&package=apache2&arch=amd64&trigger=apache2/2.4"
233+ assert trigger.action_url == expected
234+
235+ trigger = Trigger('libwebsockets', '4.1.6-3', 'armhf', 'jammy', None)
236+ expected = "https://autopkgtest.ubuntu.com/request.cgi?release=jammy&package=libwebsockets&arch=armhf&trigger=libwebsockets/4.1.6-3"
237+ assert trigger.action_url == expected

Subscribers

People subscribed via source and target branches

to all changes: