Skip to content

Commit 1d3a94d

Browse files
committed
[ULS]: Add --bump mode to update_lt_spec.py for non-rebase spec updates
Adds a --bump flag for updating the spec when commits have been added without rebasing to a new upstream kernel version. Bump mode (--bump): - Parses N from the current ciq_kernel-X.Y.Z-N tag and increments it - Updates %define pkgrelease from N to N+1 and resets %define buildid to .1, so the tarball name changes (e.g. linux-6.18.21-2.1.el9) - Prepends a new changelog entry above existing ones using commits since the last ciq_kernel tag as the log range; the changelog version uses .1 directly since buildid is always reset to .1 on bump - Optionally commits (--commit) and creates the new ciq_kernel-X.Y.Z-N+1 tag (--tag); --tag requires --commit, prints a warning if used without --bump, and is skipped with a warning if --commit made no changes Rebase mode now also resets %define pkgrelease back to 1%{?buildid} so the release counter returns to 1 for the new kernel version. New helpers in ciq_helpers.py: - parse_ciq_tag_release(): extracts N from ciq_kernel-X.Y.Z-N tags - parse_kernel_tag(): extended to accept ciq_kernel-X.Y.Z-N format - prepend_spec_changelog(): inserts a new entry at the top of %changelog - replace_spec_changelog(), prepend_spec_changelog(): raise ValueError instead of silently no-oping when %changelog is not found - read_spec_el_version(): reads %define values from spec lines; delegates to private _read_spec_define() which builds the regex from name + a value-capture pattern to avoid duplication - _set_spec_pkgrelease(): updates the numeric base of a %define pkgrelease line; shared by update_spec_file() and bump_spec_file()
1 parent 202f727 commit 1d3a94d

2 files changed

Lines changed: 304 additions & 65 deletions

File tree

ciq_helpers.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,16 +357,36 @@ def get_git_user(repo):
357357
return name, email
358358

359359

360+
def parse_ciq_tag_release(tag):
361+
"""Extract the release counter N from a CIQ tag like 'ciq_kernel-6.18.21-1'.
362+
363+
Returns the integer N.
364+
Raises ValueError if the tag is not in ciq_kernel-X.Y.Z-N format.
365+
"""
366+
m = re.match(r"^ciq_kernel-\d+\.\d+\.\d+-(\d+)$", tag)
367+
if not m:
368+
raise ValueError(
369+
f"Cannot parse CIQ release from tag: {tag!r} (expected 'ciq_kernel-X.Y.Z-N', e.g. 'ciq_kernel-6.18.21-1')"
370+
)
371+
return int(m.group(1))
372+
373+
360374
def parse_kernel_tag(tag):
361-
"""Validate and parse a kernel version tag like 'v6.12.74' or '6.12.74'.
375+
"""Validate and parse a kernel version tag.
362376
363-
Returns the version string without the 'v' prefix (e.g., '6.12.74').
377+
Accepts: 'v6.12.74', '6.12.74', or 'ciq_kernel-6.12.74-N'.
378+
379+
Returns the version string (e.g., '6.12.74').
364380
Raises ValueError if the tag format is invalid.
365381
"""
366-
tag_without_v = tag.lstrip("v")
382+
m = re.match(r"^ciq_kernel-(\d+\.\d+\.\d+)-\d+$", tag)
383+
if m:
384+
return m.group(1)
385+
386+
tag_without_v = tag.removeprefix("v")
367387
tag_parts = tag_without_v.split(".")
368388
if len(tag_parts) != 3:
369-
raise ValueError(f"Invalid kernel tag format: {tag} (expected vX.Y.Z or X.Y.Z, e.g., v6.12.74)")
389+
raise ValueError(f"Invalid kernel tag format: {tag} (expected vX.Y.Z, X.Y.Z, or ciq_kernel-X.Y.Z-N)")
370390
try:
371391
for part in tag_parts:
372392
int(part)
@@ -380,6 +400,7 @@ def replace_spec_changelog(spec_lines, new_changelog_lines):
380400
381401
Preserves any trailing comment lines (starting with #) from the original changelog.
382402
Returns a new list of lines.
403+
Raises ValueError if %changelog is not found.
383404
"""
384405
# Collect trailing comments from the original changelog section
385406
trailing_comments = []
@@ -393,12 +414,65 @@ def replace_spec_changelog(spec_lines, new_changelog_lines):
393414

394415
# Build new spec, replacing everything from %changelog onward
395416
new_spec = []
417+
found = False
396418
for line in spec_lines:
397419
if line.startswith("%changelog"):
420+
found = True
398421
new_spec.append(line)
399422
new_spec.extend(new_changelog_lines)
400423
new_spec.extend(trailing_comments)
401424
break
402425
new_spec.append(line)
403426

427+
if not found:
428+
raise ValueError("Could not find %changelog section in spec file")
429+
404430
return new_spec
431+
432+
433+
def prepend_spec_changelog(spec_lines, new_entry_lines):
434+
"""Prepend new_entry_lines at the top of the %changelog section.
435+
436+
The existing changelog entries are preserved below the new entry.
437+
Returns a new list of lines.
438+
Raises ValueError if %changelog is not found.
439+
"""
440+
new_spec = []
441+
found = False
442+
for i, line in enumerate(spec_lines):
443+
if line.startswith("%changelog"):
444+
found = True
445+
new_spec.append(line)
446+
new_spec.extend(new_entry_lines)
447+
new_spec.extend(spec_lines[i + 1 :])
448+
break
449+
new_spec.append(line)
450+
451+
if not found:
452+
raise ValueError("Could not find %changelog section in spec file")
453+
454+
return new_spec
455+
456+
457+
def _read_spec_define(spec_lines, name, value_pattern):
458+
"""Return the value of a %define directive from spec file lines.
459+
460+
Builds a regex from name and value_pattern (a raw regex string matching the value),
461+
scans spec_lines for the first match, and returns the captured value string.
462+
Raises ValueError if the directive is not found.
463+
"""
464+
pattern = re.compile(rf"^%define {re.escape(name)}\s+({value_pattern})")
465+
for line in spec_lines:
466+
m = pattern.match(line)
467+
if m:
468+
return m.group(1)
469+
raise ValueError(f"Could not find %define {name} in spec file")
470+
471+
472+
def read_spec_el_version(spec_lines):
473+
"""Read the EL version number from spec file lines.
474+
475+
Returns the el_version string (e.g., '9').
476+
Raises ValueError if not found.
477+
"""
478+
return _read_spec_define(spec_lines, "el_version", r"\d+")

0 commit comments

Comments
 (0)