Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions skills/ci/rhdh-base-images/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ until that path is migrated.
that same latest released 4.y (for example `/rhocp/4.21/` → `/rhocp/4.22/`).
Leave `ocp-tools` URLs unchanged. Do not rewrite when the life cycle fetch
fails.
- When the RPM Containerfile uses `dnf`/`microdnf install --installroot`
(operator empty rootfs), regenerate the lockfile with
`rpm-lockfile-prototype --bare` so the full closure (glibc, coreutils, bash)
is locked. Do not pass `-f`; that loads the UBI rpmdb and omits those
packages. Layered installs onto the base image still use `-f`. If the solve
fails (`nothing provides`, `conflicting requests`), restore
`rpms.lock.yaml` / `rpms.in.yaml` and do not push.
- On RHDH, update Node headers when the builder image changes Node. Then, when
those checkouts are in scope, pin plugin-catalog
`build/containerfiles/builder.Containerfile` FROM to the same UBI Node
Expand Down
2 changes: 1 addition & 1 deletion skills/ci/rhdh-base-images/references/repos.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
- Clone: `https://github.com/redhat-developer/rhdh-operator.git`
- Branches: `main`, `release-1.9`, `release-1.10`, …
- Base images: `.rhdh/docker/Dockerfile`, root `Dockerfile`
- RPM lock: `.rhdh/docker/Dockerfile` + `rpms.in.yaml` → `rpms.lock.yaml`
- RPM lock: root `Dockerfile` or `.rhdh/docker/Dockerfile` + `rpms.in.yaml` → `rpms.lock.yaml`. The `rpm-builder` stage uses `--installroot`; regenerate with `rpm-lockfile-prototype --bare` (not `-f`).
- Workflow reference: `.github/workflows/update-rpm-lockfile.yaml`

## GitLab rhidp/rhdh-plugin-catalog
Expand Down
36 changes: 32 additions & 4 deletions skills/ci/rhdh-base-images/scripts/base-images-and-rpms.sh
Original file line number Diff line number Diff line change
Expand Up @@ -540,21 +540,45 @@ bump_catalog_builder_rhocp() {
bump_rhocp_version_in_file "${catalog_cf}" "${new_ver}"
}

# Empty --installroot (operator rpm-builder) needs --bare so glibc/coreutils
# land in the lockfile. Layered installs onto the base image stay on -f.
containerfile_uses_installroot() {
local file="$1"
[[ -f "${file}" ]] || return 1
grep -qE -- '--installroot' "${file}"
}

# $1: file to inspect for --installroot
# $2: Containerfile path passed to -f (relative after cd into the repo)
# stdout: arguments after the rpm-lockfile-prototype binary.
rpm_lockfile_prototype_args() {
local inspect="$1"
local relative="$2"
if containerfile_uses_installroot "${inspect}"; then
printf '%s\n' "--bare rpms.in.yaml"
else
printf '%s\n' "-f ${relative} rpms.in.yaml"
fi
}

update_rpm_lockfile() {
local repo_dir="$1"
local kind="$2"
local rpm_tool="$3"
local branch="$4"
local containerfile rpm_err rpm_rc
local containerfile rpm_err rpm_rc proto_args
local -a proto_cmd=()
containerfile=$(rpm_containerfile_for "${repo_dir}" "${kind}" "${branch}")

[[ -f "${repo_dir}/${containerfile}" ]] || die "${repo_dir}: missing ${containerfile}"
[[ -f "${repo_dir}/rpms.in.yaml" ]] || die "${repo_dir}: missing rpms.in.yaml"

log "RPM lockfile: $(basename "${repo_dir}") using ${containerfile}"
proto_args=$(rpm_lockfile_prototype_args "${repo_dir}/${containerfile}" "${containerfile}")

log "RPM lockfile: $(basename "${repo_dir}") using ${containerfile} (${proto_args})"
if [[ ${DRY_RUN} -eq 1 ]]; then
echo " dry-run: bump OpenShift N-el9-beta URLs in ${repo_dir}/rpms.in.yaml when present"
echo " dry-run: (cd ${repo_dir} && ${rpm_tool} -f ${containerfile} rpms.in.yaml)"
echo " dry-run: (cd ${repo_dir} && ${rpm_tool} ${proto_args})"
echo " dry-run: commit and push rpms.in.yaml and rpms.lock.yaml to open base-images PR branch (or chore/automated-update-rpm-lockfile/${branch})"
return 0
fi
Expand All @@ -564,11 +588,15 @@ update_rpm_lockfile() {
pushd "${repo_dir}" >/dev/null
rpm_err=$(mktemp)
rpm_rc=0
"${rpm_tool}" -f "${containerfile}" rpms.in.yaml 2>"${rpm_err}" || rpm_rc=$?
read -r -a proto_cmd <<< "${proto_args}"
"${rpm_tool}" "${proto_cmd[@]}" 2>"${rpm_err}" || rpm_rc=$?
filter_rpm_lockfile_source_warnings <"${rpm_err}" >&2
rm -f "${rpm_err}"
if [[ ${rpm_rc} -ne 0 ]]; then
warn "rpm-lockfile-prototype failed for ${repo_dir}; keeping existing rpms.lock.yaml"
git checkout -- rpms.lock.yaml rpms.in.yaml 2>/dev/null || true
popd >/dev/null
return 0
fi
commit_push_rpm_lockfile "${branch}"
popd >/dev/null
Expand Down
4 changes: 4 additions & 0 deletions skills/ci/rhdh-base-images/workflows/update-base-images.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,10 @@ Matches each repo's GitHub Action, then commits and pushes to the automation PR:
# capped at the latest released 4.y (4.21-el9-beta 404s once 4.22-el9-beta
# is the newest released stream still on the mirror). Do not follow
# unreleased directories such as 4.23-el9-beta or 5.1-el9-beta.
# Layered install onto the base image:
rpm-lockfile-prototype -f CONTAINERFILE rpms.in.yaml
# Empty --installroot (operator rpm-builder): do not pass -f
rpm-lockfile-prototype --bare rpms.in.yaml
git add rpms.in.yaml rpms.lock.yaml
git commit -s -m "chore: update rpms.lock.yaml [skip-build]"
git push origin <chore/automated-update-base-images-*> # same PR as base images
Expand Down Expand Up @@ -203,6 +206,7 @@ Do not downgrade. If `go.mod` already pins a newer toolchain (for example `go1.2
- Omitting `registry.redhat.io` login before base image updates.
- Committing `rpms.lock.yaml` without checking the base image minor (e.g. UBI `9.8`) still matches `rpms.in.yaml` repo URLs.
- Regenerating `rpms.lock.yaml` while `rpms.in.yaml` still points at a vanished OpenShift `N-el9-beta` directory (hermeto FetchError on `openshift-clients`).
- Solving an `--installroot` Containerfile with `-f` (image rpmdb). openssl then lands without glibc/coreutils; hermetic `dnf install --installroot` fails with `nothing provides`. Use `--bare`.
- Bumping `rpms.in.yaml` or catalog `builder.Containerfile` `/rhocp/4.N/` to an unreleased OpenShift stream (`4.23`, `5.1`). Those RPMs are signed with a key UBI 9 microdnf cannot verify. Stay on the latest released 4.y.
- Treating `rpm-lockfile-prototype` `No sources found for` / "no matching sources" warnings as a failure or remaining risk. The source RPM is often unpublished; the lockfile is still valid.
- Lowering `go.mod` `toolchain` (or `go`) to match an older UBI Go toolset image. Keep the newer pin.
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/test_base_images_and_rpms.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,60 @@ def test_bump_rhocp_version_in_file_rewrites_rhocp_only(self, tmp_path: Path) ->
assert "/rhocp/4.21/" not in text
assert "/ocp-tools/4.22/os/" in text

def test_rpm_lockfile_prototype_args_bare_for_installroot(self, tmp_path: Path) -> None:
helpers = (
_extract_bash_function(MAIN_SCRIPT, "containerfile_uses_installroot")
+ "\n"
+ _extract_bash_function(MAIN_SCRIPT, "rpm_lockfile_prototype_args")
)
dockerfile = tmp_path / "Dockerfile"
dockerfile.write_text(
"RUN dnf install --installroot /mnt/rootfs openssl --releasever 10 -y\n",
encoding="utf-8",
)
result = subprocess.run(
[
"bash",
"-c",
f'{helpers}\nrpm_lockfile_prototype_args "$1" "$2"',
"bash",
str(dockerfile),
"Dockerfile",
],
capture_output=True,
text=True,
check=False,
)
assert result.returncode == 0, result.stderr
assert result.stdout.strip() == "--bare rpms.in.yaml"

def test_rpm_lockfile_prototype_args_layered_uses_containerfile(self, tmp_path: Path) -> None:
helpers = (
_extract_bash_function(MAIN_SCRIPT, "containerfile_uses_installroot")
+ "\n"
+ _extract_bash_function(MAIN_SCRIPT, "rpm_lockfile_prototype_args")
)
containerfile = tmp_path / "Containerfile"
containerfile.write_text(
"RUN microdnf install -y tar gzip jq\n",
encoding="utf-8",
)
result = subprocess.run(
[
"bash",
"-c",
f'{helpers}\nrpm_lockfile_prototype_args "$1" "$2"',
"bash",
str(containerfile),
"Containerfile",
],
capture_output=True,
text=True,
check=False,
)
assert result.returncode == 0, result.stderr
assert result.stdout.strip() == "-f Containerfile rpms.in.yaml"

def test_skill_covers_openshift_el9_beta_rpm_bump(self) -> None:
skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8")
assert "N-el9-beta" in skill
Expand All @@ -481,6 +535,10 @@ def test_skill_covers_openshift_el9_beta_rpm_bump(self) -> None:
script = MAIN_SCRIPT.read_text(encoding="utf-8")
assert "bump_openshift_rpm_repos" in script
assert "bump_catalog_builder_rhocp" in script
assert "rpm_lockfile_prototype_args" in script
assert "--bare rpms.in.yaml" in script
assert "keeping existing rpms.lock.yaml" in script
assert "rpm-lockfile-prototype --bare" in skill
unresolved = script.split(
'warn "plugin-catalog: could not resolve a Node headers version', 1
)[1][:500]
Expand Down
Loading