RFC [KT] Add content-release command for kernel release automation#57
RFC [KT] Add content-release command for kernel release automation#57bmastbergen wants to merge 1 commit intomainlinefrom
Conversation
76083c0 to
b286616
Compare
There was a problem hiding this comment.
Pull request overview
This PR extends the kt vm command with a --content_release workflow that automates building and installing LTS kernels in a VM from dist-git, then running kselftests. It introduces configuration fields and YAML metadata needed to drive the per-kernel mock builds and depot authentication.
Changes:
- Extend
KernelInfo/kernels.yamlto track a per-kernelmock_configused for mock builds. - Extend
Configwithuser,email,depot_user, anddepot_tokenand adjustfrom_str_dictto only treat specific keys as paths. - Add
VmInstance.content_release, a--content_releaseCLI flag, and additional VM dependencies (mock,python3-GitPython) plus a few supporting wiring changes.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
kt/ktlib/kernels.py |
Adds a required mock_config field to KernelInfo to match new kernels.yaml entries and support selecting the proper mock config for each kernel. |
kt/ktlib/config.py |
Adds user/depot-related config fields and refines from_str_dict to convert only specific keys to Path, changing how JSON configs must be structured. |
kt/data/kernels.yaml |
Annotates each kernel entry with its corresponding mock_config filename to be used by the content release workflow. |
kt/commands/vm/impl.py |
Implements the VmInstance.content_release orchestration, wires it into main, and consumes configuration/kernels metadata to run mkdistgitdiff, mock builds, install RPMs, and run kselftests. |
kt/commands/vm/command.py |
Exposes the new --content_release flag on the kt vm CLI and forwards it to the implementation. |
kernel_install_dep.sh |
Ensures mock and python3-GitPython are installed for supported Rocky versions and adds the invoking user to the mock group to allow mock builds within the VM. |
Comments suppressed due to low confidence (1)
kt/commands/vm/impl.py:375
- In the
content_releasepath we log “Waiting for the deps to be installed” but the actualtime.sleep(Constants.VM_DEPS_INSTALL_WAIT_SECONDS)call is commented out, unlike thetestpath above. This means that on a freshly created VM the content release workflow may start beforekernel_install_dep.shhas finished installingmock,python3-GitPython, and other dependencies, leading to sporadic failures; either restore the sleep or otherwise ensure dependency installation has completed before invokingcontent_release.
vm = Vm.load(config=config, kernel_workspace=kernel_workspace)
if destroy:
vm.destroy()
return
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b286616 to
e63daa0
Compare
roxanan1996
left a comment
There was a problem hiding this comment.
I left some comments inline.
I think this needs a separate kt command.
Since building the kernel package can be done locally (not in a vm).
And reuse some vm functionality to test the kernel. The current state could be refactored a bit to "export" some functionality to other kt commands. I would put those into kt/ktlib.
kt/commands/vm/impl.py
Outdated
|
|
||
| ssh_cmd = ( | ||
| f"cd {self.kernel_workspace.dist_worktree.folder.absolute()} && " | ||
| f"mock -v -r ../${{USER}}_{mock_config} --resultdir={self.kernel_workspace.folder.absolute()}/build_files --buildsrpm " |
There was a problem hiding this comment.
Do we need to run mock in the vm? I think this is already using a chroot or sth similar.
So why not running this on the host?
And use the vm just for testing. I believe the content_release original script is like this.
There was a problem hiding this comment.
you are absolutely right that the rpms could be built on the host. And I probably prefer it that way (which is why content_release.sh does it that way). The one nice thing about them being built in the vm is that the system running kt doesn't even have to care about mock, which is kind of nice from the perspective of minimizing the requirements for automation.
There was a problem hiding this comment.
Yeah, but it kt won't run locally. It will run in a container in jenkins or idk. I think it's not an issue if we have more requiremements, as long as they are nicely installable. I will add support to install other packages than through pip to fix this issue.
There was a problem hiding this comment.
you are absolutely right
We're all LLMs now
e63daa0 to
e31845d
Compare
e31845d to
a18a453
Compare
|
I have revamped this to introduce a new content-release command that does the mkdistgitdiff and mock builds locally, and only spins up the vm to test. This is much closer to what content_release.sh does today, with the added flexibility of splitting the task up into prepare, build and test steps taht can be run individually if needed. See what you think. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
kt/commands/vm/impl.py:308
setup_and_spinup_vmalways destroys and recreates the VM whenoverride=Truewithout checking if it exists, which can cause an unnecessary failure if the VM name has never been created. It would be more robust to checkVirtHelper.exists(vm_name=...)before callingdestroy()so--overrideworks both for existing and first-time VMs.
vm, config = load_vm_from_workspace(kernel_workspace_name)
if override:
vm.destroy()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
a18a453 to
9de1e07
Compare
9de1e07 to
a35829a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
kt/commands/content_release/impl.py
Outdated
| srpm_files = list(build_files_dir.glob("*.src.rpm")) | ||
| if not srpm_files: | ||
| raise RuntimeError(f"No SRPM found in {build_files_dir}") | ||
| srpm_file = srpm_files[0] |
There was a problem hiding this comment.
When selecting the SRPM to use for the binary RPM build, this code takes the first *.src.rpm it finds in build_files_dir. If there are multiple SRPMs present (e.g., from previous runs), this can end up rebuilding from a stale SRPM instead of the one just produced by the current mock --buildsrpm invocation. Consider either cleaning build_files_dir before the SRPM build, or selecting the SRPM deterministically (for example by using the most recently modified file or parsing the SRPM path from the mock_buildsrpm.log).
| srpm_file = srpm_files[0] | |
| # Select the most recently modified SRPM to avoid using a stale file | |
| srpm_file = max(srpm_files, key=lambda p: p.stat().st_mtime) |
kt/commands/content_release/impl.py
Outdated
| # Verify DEPOT_USER and DEPOT_TOKEN environment variables are set | ||
| depot_user = os.environ.get("DEPOT_USER") | ||
| depot_token = os.environ.get("DEPOT_TOKEN") | ||
|
|
||
| if not depot_user: | ||
| raise RuntimeError( | ||
| "DEPOT_USER environment variable is not set. Please set it:\n export DEPOT_USER=your_username" | ||
| ) | ||
| if not depot_token: | ||
| raise RuntimeError( | ||
| "DEPOT_TOKEN environment variable is not set. Please set it:\n export DEPOT_TOKEN=your_token" | ||
| ) | ||
| logging.info("DEPOT_USER and DEPOT_TOKEN environment variables are set") |
There was a problem hiding this comment.
DEPOT_USER and DEPOT_TOKEN are validated unconditionally, even though the subsequent logic treats CBR workspaces (cbr-*) as not needing depot credentials and uses a non-depot mock config in that case. As written, run_build will still fail for CBR workspaces if these environment variables are unset, which both contradicts the intent described by the is_cbr comment and forces users to provide unused credentials. You may want to short-circuit the depot credential checks for CBR workspaces (or otherwise conditionally enforce them only for configurations that actually require depot).
kt/commands/content_release/impl.py
Outdated
| logging.info("Depot client installed") | ||
|
|
||
| # Register depot with credentials | ||
| SshCommand.run(domain=vm_instance.domain, command=[f"sudo depot register -u {depot_user} -t {depot_token}"]) |
There was a problem hiding this comment.
The depot registration command is built by interpolating depot_user and depot_token into a single shell string (f"sudo depot register -u {depot_user} -t {depot_token}") that is passed through SSH. If either value contains spaces or shell metacharacters, this can lead to command failures or, in the worst case, shell injection. It would be safer and more robust to pass these as separate arguments (e.g., command=["sudo", "depot", "register", "-u", depot_user, "-t", depot_token]) so that they are not subject to shell parsing on the remote side.
| SshCommand.run(domain=vm_instance.domain, command=[f"sudo depot register -u {depot_user} -t {depot_token}"]) | |
| SshCommand.run( | |
| domain=vm_instance.domain, | |
| command=["sudo", "depot", "register", "-u", depot_user, "-t", depot_token], | |
| ) |
a35829a to
e5ee2d7
Compare
e5ee2d7 to
434b595
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
kt/commands/content_release/impl.py
Outdated
| # Load kernel workspace | ||
| kernel_workspace_obj, config = KernelWorkspace.load_from_name(kernel_workspace) | ||
|
|
||
| # Setup and spin up the VM (reuses common code from vm command) | ||
| vm_instance, config = setup_and_spinup_vm(kernel_workspace_name=kernel_workspace) |
There was a problem hiding this comment.
run_test calls KernelWorkspace.load_from_name(kernel_workspace) to obtain kernel_workspace_obj and config, and then calls setup_and_spinup_vm(kernel_workspace_name=kernel_workspace), which internally reloads Config and the same workspace. This double-loading is redundant and can cause subtle inconsistencies if Config.load() ever gains side effects; consider reusing the already-loaded config and workspace (e.g., by refactoring setup_and_spinup_vm to accept preloaded objects) or centralizing the loading in a single helper.
kt/commands/content_release/impl.py
Outdated
| if is_cbr: | ||
| mock_config_name = f"{mock_config_base}-x86_64.cfg" | ||
| else: | ||
| mock_config_name = f"{mock_config_base}-depot-x86_64.cfg" |
There was a problem hiding this comment.
The construction of mock_config_name appends the -depot suffix unconditionally for all non-CBR workspaces, but some entries in release_map already include -depot in the mock_config value (e.g. fips-8.10 uses "rocky-fips810-553-depot", fips-8.6 uses "rocky-fips86-553-depot"). This results in filenames like rocky-fips810-553-depot-depot-x86_64.cfg, which likely do not exist and will cause the mock config lookup to fail. Either remove the -depot suffix from those release_map entries or adjust this logic to only append -depot when it is not already present in mock_config_base.
| mock_config_name = f"{mock_config_base}-depot-x86_64.cfg" | |
| # For non-CBR workspaces, ensure we only have a single '-depot' suffix | |
| mock_config_with_depot = ( | |
| mock_config_base | |
| if mock_config_base.endswith("-depot") | |
| else f"{mock_config_base}-depot" | |
| ) | |
| mock_config_name = f"{mock_config_with_depot}-x86_64.cfg" |
kt/commands/content_release/impl.py
Outdated
| download_config = SOURCE_DOWNLOAD_CONFIG.get(kernel_workspace) | ||
|
|
||
| if download_config: | ||
| # Direct download for special cases | ||
| logging.info(f"Downloading {kernel_workspace} source files directly...") | ||
| for hash_or_id, filename in download_config["files"]: | ||
| url = f"{download_config['base_url']}/{hash_or_id}" | ||
| run_command( | ||
| ["curl", url, "-o", str(sources_dir / filename)], | ||
| error_msg=f"Failed to download {filename}", | ||
| ) |
There was a problem hiding this comment.
For the direct download path in download_sources, the URL is built as <base_url>/<hash_or_id> and the filename is only used on the curl -o side. For the cbr-7.9 entry (and generally for git.centos.org source URLs), the canonical layout is <base_url>/<hash>/<filename>, so omitting the /filename portion from the URL means curl will not fetch the actual tarball contents and the saved file will be invalid for later RPM builds. Please include the filename component in the URL for these hashed-source downloads (or otherwise confirm and encode the expected URL pattern per entry).
roxanan1996
left a comment
There was a problem hiding this comment.
I left some comments.
Nitpick about the commit message.
Since I use
kt: Add <> command
I would keep a similar format for the new commands.
kt/ktlib/util.py
Outdated
| import subprocess | ||
|
|
||
|
|
||
| def run_command(cmd: list, error_msg: str, cwd=None, success_msg: str = None): |
There was a problem hiding this comment.
Hmm, we already have a command_runner.py. Is that useful for you?
If not, just add your stuff there. This file is just for Contants at the moment, I would not add this here.
kt/ktlib/repo.py
Outdated
| from pathlib3x import Path | ||
|
|
||
|
|
||
| def check_git_config_value(repo, section, option): |
There was a problem hiding this comment.
Could not this be part of RepoInfo?
Everything is implemented in its own data structure (even if it contains only classmethods). I like it to keep it that way.
kt/ktlib/kernel_workspace.py
Outdated
| config = Config.load() | ||
| kernel_workpath = config.kernels_dir / kernel_workspace_name | ||
| workspace = cls.load_from_filepath(folder=kernel_workpath) | ||
| return workspace, config |
There was a problem hiding this comment.
This is not correct. config should not be returned here.
Otherwise it is a useful helper.
kt/commands/content_release/impl.py
Outdated
| raise RuntimeError(f"Kselftests failed. See {kselftest_log} for details") | ||
|
|
||
| # Count passed tests | ||
| try: |
There was a problem hiding this comment.
If this is added in VmInstance.kselftests(), it could be reused when running kselftests from the keernel source. Another reason to move this logic there.
kt/commands/vm/impl.py
Outdated
| if list_all: | ||
| VmCommand.list_all() | ||
| return | ||
| def load_vm_from_workspace(kernel_workspace_name: str): |
There was a problem hiding this comment.
This should be a classmethod for Vm. And it should not return config. Just a Vm object
kt/commands/vm/impl.py
Outdated
| return vm, config | ||
|
|
||
|
|
||
| def setup_and_spinup_vm(kernel_workspace_name: str, override: bool = False): |
There was a problem hiding this comment.
Same, it should be a method for Vm.
kt/commands/vm/impl.py
Outdated
| VmCommand.list_all() | ||
| return | ||
|
|
||
| if not name: |
There was a problem hiding this comment.
Useful just be sure, but this is a required param for kt vm.
kt/commands/vm/impl.py
Outdated
| # If this behavior is not desired, consider requiring at least one action flag. | ||
|
|
||
| if destroy: | ||
| vm, config = load_vm_from_workspace(name) |
There was a problem hiding this comment.
I would keep the old implementation here. If you want to change it, do it in a separate commit as this is not related to kt content release.
434b595 to
1f31726
Compare
roxanan1996
left a comment
There was a problem hiding this comment.
Some small things, but I think it's ready to be merged.
patch
Outdated
| @@ -0,0 +1,23 @@ | |||
| diff --git a/kt/commands/content_release/impl.py b/kt/commands/content_release/impl.py | |||
There was a problem hiding this comment.
'this' being impl.py ?
There was a problem hiding this comment.
I see a patch file here
There was a problem hiding this comment.
kt/ktlib/repo.py
Outdated
| url: str | ||
|
|
||
| @classmethod | ||
| def check_git_config_value(cls, repo, section, option): |
There was a problem hiding this comment.
Maybe this is better under RepoWorktree based on how you use this method?
There was a problem hiding this comment.
yes, I think it would. will move. thanks!
1f31726 to
2d82374
Compare
2d82374 to
0919547
Compare
Introduces a new 'content-release' command that automates the complete
kernel content release workflow through three stages: prepare, build,
and test. The command can run all stages sequentially (default) or
execute individual stages via --prepare, --build, and --test flags.
Prepare Stage:
- Validates git user.name and user.email configuration in dist-git repo
- Executes mkdistgitdiff.py to generate staging branch and release files
- Staging branch format: {automation_tmp}_<src_branch>
- Checks out the newly created staging branch
- Extracts and displays the new release tag from script output
Build Stage:
- Verifies mock command availability and user membership in mock group
- Validates DEPOT_USER and DEPOT_TOKEN environment variables
- Creates temporary mock config with depot credentials injected
- Downloads kernel sources using getsrc.sh script
- Builds source RPM with mock in build_files directory
- Builds binary RPMs from the SRPM
- Lists all created RPM packages
- Cleans up temporary mock configuration
Test Stage:
- Spins up VM for the kernel workspace (creates if needed)
- Installs built kernel RPMs excluding .src.rpm, kernel-rt*, kernel-debug*
- Reboots VM and verifies running kernel version matches installed version
- Executes kselftests using /usr/libexec/kselftests/run_kselftest.sh
- Counts and reports number of tests passed
- Outputs logs: install.log, selftest-<version>.log
Additional Changes:
- Refactored VM implementation to extract reusable functions:
* load_vm_from_workspace(): Load config and VM from workspace name
* setup_and_spinup_vm(): Common VM setup and spinup logic
- Increased VM disk size to 30GB during creation to accommodate kernel
packages and debug symbols
- Updated KT.md with comprehensive documentation for the new command
The content-release command streamlines the kernel release process by
automating previously manual steps, ensuring consistency and reducing
the potential for human error in the release workflow.
kt: Fix grubenv symlink issue preventing kernel boot
On lts-8.6, /boot/grub2/grubenv is a symlink to /boot/efi/EFI/rocky/grubenv
and grub can't follow the symlink when reading the default boot entry.
Replace the symlink with a real file before using grubby to set the
default kernel. The symlink check must run with sudo permissions to
access the grubenv file. This ensures grub can read the saved_entry
and boot the correct kernel.
0919547 to
b950de7
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated 20 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| logging.info(f"RPM install output will be written to {install_log}") | ||
|
|
||
| try: | ||
| SshCommand.run_with_output(output_file=install_log, domain=vm_instance.domain, command=[install_cmd]) |
There was a problem hiding this comment.
Type inconsistency: The run_with_output method expects output_file: str parameter but here a Path object is passed. While Python's open() can handle Path objects, for consistency with other calls in the codebase (lines 126, 199, 236 in other files convert Path to str), this should be str(install_log).
| SshCommand.run_with_output(output_file=install_log, domain=vm_instance.domain, command=[install_cmd]) | |
| SshCommand.run_with_output(output_file=str(install_log), domain=vm_instance.domain, command=[install_cmd]) |
| SshCommand.run_with_output(output_file=output_file, domain=self.domain, command=[ssh_cmd]) | ||
|
|
||
| def kselftests_internal(self, output_file: Path): | ||
| """ | ||
| Run installed kselftests from /usr/libexec/kselftests (for official releases). | ||
|
|
||
| Args: | ||
| output_file: Path to write kselftest output | ||
|
|
||
| Raises: | ||
| RuntimeError: If kselftests fail | ||
| """ | ||
| logging.info("Running kernel selftests...") | ||
| logging.info(f"Kselftest output will be written to {output_file}") | ||
|
|
||
| kselftest_cmd = "sudo /usr/libexec/kselftests/run_kselftest.sh" | ||
|
|
||
| try: | ||
| SshCommand.run_with_output(output_file=output_file, domain=self.domain, command=[kselftest_cmd]) |
There was a problem hiding this comment.
Type inconsistency: The run_with_output method expects output_file: str parameter, but these methods are passing Path objects. While Python's open() can handle Path objects, for consistency with the pattern established in mock.py (lines 199, 236) and content_release impl.py (line 126) which use str(output_log), these should be converted to strings.
| config_content = config_content.replace("DEPOT_USER", depot_user) | ||
| config_content = config_content.replace("DEPOT_TOKEN", depot_token) | ||
|
|
||
| with open(temp_mock_config, "w") as dest: |
There was a problem hiding this comment.
Security: The temporary mock config file containing credentials is created without restrictive permissions. This could allow other users on the system to read the credentials. Consider setting restrictive file permissions (e.g., 0o600) immediately after creating the file using temp_mock_config.chmod(0o600) to ensure only the owner can read the credentials.
| with open(temp_mock_config, "w") as dest: | |
| with open(temp_mock_config, "w") as dest: | |
| os.chmod(temp_mock_config, 0o600) |
| # Register depot with credentials | ||
| SshCommand.run( | ||
| domain=vm_instance.domain, command=[f"sudo depot register -u {depot_user} -t {depot_token}"] |
There was a problem hiding this comment.
Security: The credentials from environment variables are directly embedded in the command string that gets executed via SSH. If command logging is enabled or if there are errors, these credentials could be exposed in logs. Consider using a more secure method such as passing credentials through stdin or using a credential file with restricted permissions.
| # Register depot with credentials | |
| SshCommand.run( | |
| domain=vm_instance.domain, command=[f"sudo depot register -u {depot_user} -t {depot_token}"] | |
| # Register depot with credentials. | |
| # Use remote environment variables to avoid embedding credentials in the local command string. | |
| SshCommand.run( | |
| domain=vm_instance.domain, | |
| command=['sudo depot register -u "$DEPOT_USER" -t "$DEPOT_TOKEN"'], |
| "lts-8.6": { | ||
| "base_url": "https://rocky-linux-sources-staging.a1.rockylinux.org", | ||
| "files": [ | ||
| ("cd67969ef0be82516b144066d3897b071f59f2a2", "kernel-abi-stablelists-4.18.0-372.tar.bz2"), | ||
| ("89ce72b86bacc9c2cd712784e9053d9c36f37c23", "kernel-kabi-dw-4.18.0-372.tar.bz2"), | ||
| ("c48b00ba5e77fcf4bc9e2dd5e58f1791ae71e8c8", "linux-4.18.0-372.32.1.el8_6.tar.xz"), | ||
| ], | ||
| }, | ||
| "fipslegacy-8.6": { | ||
| "base_url": "https://rocky-linux-sources-staging.a1.rockylinux.org", | ||
| "files": [ | ||
| ("feac61524ad00b8b03f2985f8ac330c7939ba425", "kernel-abi-stablelists-4.18.0-425.tar.bz2"), | ||
| ("f2fb49be6e6fe2782bc58e2914d8dcc7b2948764", "kernel-kabi-dw-4.18.0-425.tar.bz2"), | ||
| ("57cc7ba600df4d74be3a1b8c2324ea69b92699e4", "linux-4.18.0-425.13.1.el8_7.tar.xz"), | ||
| ], | ||
| }, | ||
| "cbr-7.9": { | ||
| "base_url": "https://git.centos.org/sources/kernel/c7", | ||
| "files": [ | ||
| ("ba5599148e52ecd126ebcf873672e26d3288323e", "kernel-abi-whitelists-1160.tar.bz2"), | ||
| ("5000b85c42ef87b6835dd8eef063e4623c2e0fa9", "kernel-kabi-dw-1160.tar.bz2"), | ||
| ("83cf85ab62fc9dca6d34175c60cc17cb917d7e0d", "linux-3.10.0-1160.119.1.el7.tar.xz"), | ||
| ], | ||
| }, | ||
| } | ||
|
|
There was a problem hiding this comment.
Maintainability: The hardcoded download URLs and file hashes for special kernel workspaces create a maintenance burden. These values would need to be manually updated whenever sources change. Consider moving this configuration to an external file (e.g., kernels.yaml or a separate sources.yaml) to make updates easier and more discoverable.
| try: | ||
| LocalCommand.run( | ||
| command=[ | ||
| "curl", |
There was a problem hiding this comment.
The curl command for downloading getsrc.sh doesn't follow redirects, which could cause failures if GitHub redirects the raw content URL. Consider adding the -L flag to follow redirects: ["curl", "-L", "-O", "https://..."].
| "curl", | |
| "curl", | |
| "-L", |
| - Verifying mock is installed and user is in mock group | ||
| - Checking DEPOT_USER and DEPOT_TOKEN environment variables are set | ||
| - Creating a temporary mock config with depot credentials | ||
| - Downloading sources using getsrc.sh |
There was a problem hiding this comment.
The documentation states that the --build step uses "getsrc.sh" for downloading sources, but the implementation actually has special handling for certain kernel workspaces (lts-8.6, fipslegacy-8.6, cbr-7.9) that download files directly via curl instead. The documentation should mention this special handling or at least indicate that the download method varies by kernel workspace.
| - Downloading sources using getsrc.sh | |
| - Downloading sources (typically via getsrc.sh; for some kernel workspaces such as lts-8.6, fipslegacy-8.6, and cbr-7.9, sources are fetched directly via curl as implemented) |
|
|
||
| repo = Repo(dist_git_path) | ||
| try: | ||
| repo.git.checkout(staging_branch) |
There was a problem hiding this comment.
The variable repo is used here but never defined in this function. This will cause a NameError at runtime when trying to checkout the staging branch. You need to create a Repo object from the dist_git_path before this line.
| rpm_name = kernel_rpms[0].name | ||
| # Use regex to extract version (more robust than string replacement) | ||
| # Pattern: kernel-VERSION.ARCH.rpm where VERSION includes everything up to .x86_64 | ||
| version_match = re.match(r"kernel-(.*?)\.rpm$", rpm_name) |
There was a problem hiding this comment.
The regex pattern r"kernel-(.*?)\.rpm$" will incorrectly match RPM filenames because it extracts everything between "kernel-" and ".rpm", but the filename is "kernel-5.14.0-284.30.1+23.1.el9_2_ciq.x86_64.rpm", which includes ".x86_64" before ".rpm". The pattern should be r"kernel-(.*?)\.x86_64\.rpm$" to correctly extract just the version string without the architecture suffix.
| version_match = re.match(r"kernel-(.*?)\.rpm$", rpm_name) | |
| version_match = re.match(r"kernel-(.*?)\.x86_64\.rpm$", rpm_name) |
| import re | ||
| import time | ||
|
|
||
| from git import GitCommandError, Repo |
There was a problem hiding this comment.
Import of 'Repo' is not used.
| from git import GitCommandError, Repo | |
| from git import GitCommandError |

Introduces a new 'content-release' command that automates the complete
kernel content release workflow through three stages: prepare, build,
and test. The command can run all stages sequentially (default) or
execute individual stages via --prepare, --build, and --test flags.
Prepare Stage:
Build Stage:
Test Stage:
Additional Changes:
packages and debug symbols
The content-release command streamlines the kernel release process by
automating previously manual steps, ensuring consistency and reducing
the potential for human error in the release workflow.
And since its not in the diff, this requires the mock-configs and kernel-tools repos checked out in the kt workspace.
This works for lts-9.2. That is all I tested. More testing will be needed. This is really just an RFC at the moment.