Skip to content

Commit 4f32bf6

Browse files
committed
testing: litevm: allow a missing latest RPM in CI
When a new kernel-ueknext is released, it is not uncommon that the debuginfo is either forgotten, or delayed. It's fine to have this happen: I will report it and ensure we upload our debuginfo. I'd rather I encounter this than a customer. However, in the meantime, this means that drgn-tools PRs cannot be merged. This isn't a great situation. So, allow the CI latest version detection to skip the most recent version if an RPM is missing. Signed-off-by: Stephen Brennan <[email protected]>
1 parent 9e3483f commit 4f32bf6

File tree

3 files changed

+83
-13
lines changed

3 files changed

+83
-13
lines changed

.github/workflows/litevm.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ on:
55
branches:
66
- main
77
pull_request:
8+
types:
9+
- opened
10+
- synchronize
11+
- reopened
12+
- labeled
813

914
jobs:
1015
commit-hooks:
@@ -61,5 +66,7 @@ jobs:
6166
cd drgn
6267
../drgn-tools/venv/bin/pip install .
6368
- name: Run tests
69+
env:
70+
DRGN_TOOLS_ALLOW_MISSING_LATEST: ${{ contains(github.event.pull_request.labels.*.name, 'allow-missing-latest') && '1' || '0' }}
6471
run: |
6572
venv/bin/python -m testing.litevm.vm --delete-after-test --with-ctf

drgn_tools/util.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import typing as t
77
from contextlib import contextmanager
88
from enum import IntEnum
9+
from urllib.error import HTTPError
10+
from urllib.request import Request
911
from urllib.request import urlopen
1012

1113
from drgn import NULL
@@ -307,6 +309,15 @@ def complete(self):
307309
print()
308310

309311

312+
def head_file(url: str) -> bool:
313+
request = Request(url, method="HEAD")
314+
try:
315+
urlopen(request)
316+
return True
317+
except HTTPError:
318+
return False
319+
320+
310321
def download_file(
311322
url: str,
312323
f: t.BinaryIO,

testing/litevm/rpm.py

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import argparse
77
import fnmatch
88
import io
9+
import os
910
import shlex
1011
import shutil
1112
import sqlite3
@@ -19,6 +20,7 @@
1920
from urllib.error import HTTPError
2021

2122
from drgn_tools.util import download_file
23+
from drgn_tools.util import head_file
2224
from testing.util import BASE_DIR
2325

2426

@@ -92,6 +94,18 @@ def download_file_cached(
9294
return cached_file
9395

9496

97+
def check_file_cached(
98+
url: str, cache: Optional[Path], cache_key: Optional[str]
99+
) -> bool:
100+
if not cache:
101+
cache = YUM_CACHE_DIR
102+
if cache_key:
103+
cache = cache / cache_key
104+
cached_file = cache / url.split("/")[-1]
105+
rv = cached_file.is_file() or head_file(url)
106+
return rv
107+
108+
95109
class TestKernel:
96110
ol_ver: int
97111
uek_ver: Union[int, str]
@@ -192,20 +206,58 @@ def _getlatest(self) -> None:
192206
def key(t):
193207
return tuple(map(int, t[0].split(".") + t[1].split(".")[:-1]))
194208

195-
rows.sort(key=key)
196-
ver, rel, href = rows[-1]
197-
198-
# Now set the final values as output
199-
self._rpm_urls = []
200-
rpm_url = yumbase + href
201-
for final_pkg in self.pkgs:
202-
self._rpm_urls.append(rpm_url.replace(self.pkgbase, final_pkg))
203-
self._release = f"{ver}-{rel}.{self.arch}"
204-
self._dbinfo_url = DEBUGINFO_URL.format(
205-
ol_ver=self.ol_ver,
206-
release=self._release,
207-
pkgbase=self.pkgbase,
209+
allow_missing = bool(
210+
int(os.environ.get("DRGN_TOOLS_ALLOW_MISSING_LATEST", 0))
208211
)
212+
rows.sort(key=key, reverse=True)
213+
versions_tried = []
214+
for ver, rel, href in rows[:2]:
215+
# Check whether all RPMs are either cached or available via HTTP
216+
rpm_urls: List[str] = []
217+
rpm_url = yumbase + href
218+
missing_urls = []
219+
release = f"{ver}-{rel}.{self.arch}"
220+
for final_pkg in self.pkgs:
221+
url = rpm_url.replace(self.pkgbase, final_pkg)
222+
if not check_file_cached(
223+
url, self.cache_dir, self._cache_key("rpm")
224+
):
225+
missing_urls.append(url)
226+
rpm_urls.append(url)
227+
dbinfo_url = DEBUGINFO_URL.format(
228+
ol_ver=self.ol_ver,
229+
release=release,
230+
pkgbase=self.pkgbase,
231+
)
232+
if not check_file_cached(
233+
dbinfo_url, self.cache_dir, self._cache_key("rpm")
234+
):
235+
missing_urls.append(dbinfo_url)
236+
237+
# If some RPMs are available, we have two options:
238+
# 1. Try the next older RPM (if the environment variable is set)
239+
# 2. Ignore the error and let the HTTP 404 handling below report the
240+
# issue.
241+
if missing_urls and allow_missing:
242+
print(
243+
f"warning: {release} had missing RPMs:\n"
244+
+ "\n".join(missing_urls)
245+
+ "\nTrying an older release..."
246+
)
247+
versions_tried.append(release)
248+
continue
249+
250+
self._rpm_urls = rpm_urls
251+
self._dbinfo_url = dbinfo_url
252+
self._release = release
253+
return
254+
else:
255+
# This is the case where we checked both candidates, but neither had
256+
# all files available. Report an error.
257+
sys.exit(
258+
"error: no release had all files available. Tried: "
259+
+ ", ".join(versions_tried)
260+
)
209261

210262
def _get_rpms(self) -> None:
211263
if not self._release:

0 commit comments

Comments
 (0)