Skip to content

ci: support testing from brew builds and compose repositories - #239

Closed
mcattamoredhat wants to merge 5 commits into
fido-device-onboard:mainfrom
mcattamoredhat:test-brew-builds
Closed

ci: support testing from brew builds and compose repositories#239
mcattamoredhat wants to merge 5 commits into
fido-device-onboard:mainfrom
mcattamoredhat:test-brew-builds

Conversation

@mcattamoredhat

@mcattamoredhat mcattamoredhat commented Jun 3, 2026

Copy link
Copy Markdown

Summary

This PR extends the test infrastructure to allow installing RPM packages from two new sources — internal brew builds and compose repositories — for test/rpm and test/bootc deployments. It also includes three follow-up fixes for bugs found during review and manual/CI testing of that new support.


Commit 1 — test: allow testing brew builds

Introduces support for installing pre-built RPMs from an internal brew server by pointing at a specific build's version/release directory.

Usage:

SERVER_RPM_URL="http://brew.host/packages/go-fdo-server/1.0.0/1.el10/x86_64" \
CLIENT_RPM_URL="http://brew.host/packages/go-fdo-client/1.0.0/1.el10/x86_64" \
  sudo ./test/rpm/test-onboarding.sh

Commit 2 — ci: add compose repository support for RPM and bootc tests

Introduces support for installing RPM packages from a compose repository URL, targeting a specific compose snapshot.

Usage:

# RPM deployment
sudo COMPOSE_BASE_URL="http://<host>/.../RHEL-10.2-<date>/compose/" \
     ./test/rpm/test-onboarding.sh
# bootc deployment
sudo COMPOSE_BASE_URL="http://<host>/.../RHEL-10.2-<date>/compose/" \
     ./test/bootc/test-onboarding.sh
# Override streams if needed (default: BaseOS AppStream for RHEL/CentOS)
sudo COMPOSE_BASE_URL="..." COMPOSE_STREAMS="BaseOS AppStream CRB" \
     ./test/rpm/test-onboarding.sh

Commit 3 — fix: avoid unbound _brew_* vars in parse_brew_url callers

parse_brew_url() set _brew_ver/_brew_rel/_brew_arch as side effects, but every caller captured it via url=$(parse_brew_url ...). Command substitution runs the function in a subshell, so those assignments never reached the calling scope — under set -u, the first reference to _brew_arch in install_client()/install_server() (test/ci, test/rpm, test/bootc) crashed with "unbound variable" whenever SERVER_RPM_URL or CLIENT_RPM_URL was actually set.

Fix: have parse_brew_url() set _brew_url directly instead of echoing it, and call it as a plain statement (no command substitution) so all four variables land in the caller's scope.

No behavior change for any path that doesn't set SERVER_RPM_URL/CLIENT_RPM_URL: PACKIT_COPR_RPMS-driven Packit/Testing Farm runs and the GitHub Actions test/ci matrix never touch parse_brew_url() at all — this only affects the manual brew-build testing path introduced in Commit 1.


Commit 4 — fix: strip trailing slash from COMPOSE_BASE_URL and drop dead repo file

  • install_from_compose() (test/rpm/utils.sh) and the bootc client compose branch (test/bootc/utils.sh) now strip a trailing slash from the compose base URL before building baseurl=..., avoiding a double slash if the caller passes COMPOSE_BASE_URL with one.
  • Removed files/rhel-10-2.repo: an unused static template with unreplaced REPLACE_ME_HERE placeholders. The real RHEL repo file is generated at runtime as files/rhel-${VERSION_ID}.repo (test/bootc/utils.sh), so this static file was dead weight.

Commit 5 — fix(bootc): wait for firewalld D-Bus before starting libvirt network

configure_service_firewalld() returned right after systemctl start firewalld, but firewalld ≥ 2.4.1 (e.g. on Fedora 44) no longer blocks until its D-Bus interface is ready. configure_service_libvirtd() runs immediately afterward and calls virsh net-start integration on a network with zone='trusted', which requires firewalld's D-Bus API — racing it produces:

error: internal error: zone trusted requested for network integration but firewalld is not active

Fix: poll firewall-cmd --state (up to 30s) after starting firewalld, bailing out with diagnostics if the unit dies or the timeout is hit. Same root cause/fix as virt-s1/rhel-edge#12261.

@mcattamoredhat

Copy link
Copy Markdown
Author

Opened as draft PR for testing purposes only.
This PR will be opened again in the proper repository go-fdo-ci, after making sure it is useful for local testing.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for RHEL 10 and introduces features to install go-fdo-client and go-fdo-server from specific Brew build URLs or compose repositories. The review feedback identifies a critical bug where calling parse_brew_url in a subshell prevents its global variables from propagating back to the parent shell, which breaks the RPM installation paths. Additionally, the feedback recommends removing the redundant static files/rhel-10-2.repo file and stripping trailing slashes from COMPOSE_BASE_URL to avoid malformed repository URLs.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread test/ci/utils.sh
Comment on lines +399 to +409
# Parse a brew build base URL into its components.
# The URL must point to the version/release directory of the package in brew.
# Sets _brew_ver, _brew_rel, _brew_arch and returns the trailing-slash-stripped
# URL on stdout so callers can capture it with: local url; url=$(parse_brew_url …)
parse_brew_url() {
local url="${1%/}" # strip any trailing slash to prevent empty basename
_brew_ver=$(basename "$(dirname "${url}")")
_brew_rel=$(basename "${url}")
_brew_arch=$(uname -m)
echo "${url}"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The parse_brew_url function is designed to set global variables (_brew_ver, _brew_rel, _brew_arch) as side effects. However, because it is called using command substitution (url=$(parse_brew_url ...)), it runs in a subshell. In Bash, variables set inside a subshell do not propagate back to the parent shell, leaving these variables empty when used later.

To fix this, redefine parse_brew_url to set a global _brew_url variable directly and avoid command substitution entirely.

Suggested change
# Parse a brew build base URL into its components.
# The URL must point to the version/release directory of the package in brew.
# Sets _brew_ver, _brew_rel, _brew_arch and returns the trailing-slash-stripped
# URL on stdout so callers can capture it with: local url; url=$(parse_brew_url …)
parse_brew_url() {
local url="${1%/}" # strip any trailing slash to prevent empty basename
_brew_ver=$(basename "$(dirname "${url}")")
_brew_rel=$(basename "${url}")
_brew_arch=$(uname -m)
echo "${url}"
}
# Parse a brew build base URL into its components.
# The URL must point to the version/release directory of the package in brew.
# Sets _brew_url, _brew_ver, _brew_rel, and _brew_arch globally.
parse_brew_url() {
_brew_url="${1%/}" # strip any trailing slash to prevent empty basename
_brew_ver=$(basename "$(dirname "${_brew_url}")")
_brew_rel=$(basename "${_brew_url}")
_brew_arch=$(uname -m)
}

Comment thread test/ci/utils.sh
Comment on lines 411 to 424
install_client() {
go install github.com/fido-device-onboard/go-fdo-client@main
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
else
go install github.com/fido-device-onboard/go-fdo-client@main
fi
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Since parse_brew_url runs in a subshell when called via $(parse_brew_url ...), the global variables _brew_ver, _brew_rel, and _brew_arch are not set in the parent shell, causing the RPM filename construction to fail. Call parse_brew_url directly and use the global _brew_url variable instead.

Suggested change
install_client() {
go install github.com/fido-device-onboard/go-fdo-client@main
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
else
go install github.com/fido-device-onboard/go-fdo-client@main
fi
}
install_client() {
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
parse_brew_url "${CLIENT_RPM_URL}"
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${_brew_url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
else
go install github.com/fido-device-onboard/go-fdo-client@main
fi
}

Comment thread test/bootc/utils.sh
Comment on lines +73 to +84
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install go-fdo-client from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
tee Containerfile >/dev/null <<EOF
FROM ${base_image_url}
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
RUN dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
EOF

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Since parse_brew_url runs in a subshell when called via $(parse_brew_url ...), the global variables _brew_ver, _brew_rel, and _brew_arch are not set in the parent shell, causing the RPM filename construction to fail. Call parse_brew_url directly and use the global _brew_url variable instead.

Suggested change
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install go-fdo-client from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
tee Containerfile >/dev/null <<EOF
FROM ${base_image_url}
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
RUN dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
EOF
if [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install go-fdo-client from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
parse_brew_url "${CLIENT_RPM_URL}"
tee Containerfile >/dev/null <<EOF
FROM ${base_image_url}
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
RUN dnf install -y --nogpgcheck --setopt=sslverify=false \
"${_brew_url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
EOF

Comment thread test/bootc/utils.sh Outdated
Comment on lines +184 to +195
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${SERVER_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Since parse_brew_url runs in a subshell when called via $(parse_brew_url ...), the global variables _brew_ver, _brew_rel, and _brew_arch are not set in the parent shell, causing the RPM filename construction to fail. Call parse_brew_url directly and use the global _brew_url variable instead.

Suggested change
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${SERVER_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
parse_brew_url "${SERVER_RPM_URL}"
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${_brew_url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${_brew_url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${_brew_url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${_brew_url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"

Comment thread test/rpm/utils.sh Outdated
Comment on lines +276 to +284
elif [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Since parse_brew_url runs in a subshell when called via $(parse_brew_url ...), the global variables _brew_ver, _brew_rel, and _brew_arch are not set in the parent shell, causing the RPM filename construction to fail. Call parse_brew_url directly and use the global _brew_url variable instead.

Suggested change
elif [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${CLIENT_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"
elif [ -n "${CLIENT_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# CLIENT_RPM_URL should point to the version/release directory of the package in brew.
parse_brew_url "${CLIENT_RPM_URL}"
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${_brew_url}/${_brew_arch}/go-fdo-client-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm"

Comment thread test/rpm/utils.sh Outdated
Comment on lines +308 to +319
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${SERVER_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Since parse_brew_url runs in a subshell when called via $(parse_brew_url ...), the global variables _brew_ver, _brew_rel, and _brew_arch are not set in the parent shell, causing the RPM filename construction to fail. Call parse_brew_url directly and use the global _brew_url variable instead.

Suggested change
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
local url
url=$(parse_brew_url "${SERVER_RPM_URL}")
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"
elif [ -n "${SERVER_RPM_URL:-}" ]; then
# Install from a specific brew build base path.
# SERVER_RPM_URL should point to the version/release directory of the package in brew.
parse_brew_url "${SERVER_RPM_URL}"
# --nogpgcheck and sslverify=false are intentional: internal brew servers
# use self-signed certificates and builds may not be GPG-signed.
sudo dnf install -y --nogpgcheck --setopt=sslverify=false \
"${_brew_url}/${_brew_arch}/go-fdo-server-${_brew_ver}-${_brew_rel}.${_brew_arch}.rpm" \
"${_brew_url}/noarch/go-fdo-server-manufacturer-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${_brew_url}/noarch/go-fdo-server-owner-${_brew_ver}-${_brew_rel}.noarch.rpm" \
"${_brew_url}/noarch/go-fdo-server-rendezvous-${_brew_ver}-${_brew_rel}.noarch.rpm"

Comment thread files/rhel-10-2.repo Outdated
Comment on lines +1 to +12
[RHEL-10.2-NIGHTLY-BaseOS]
name=baseos
baseurl=http://REPLACE_ME_HERE/rhel-10/nightly/RHEL-10/latest-RHEL-10.2/compose/BaseOS/$basearch/os
enabled=1
# Nightly compose builds are not GPG-signed; gpgcheck=0 is intentional.
gpgcheck=0
[RHEL-10.2-NIGHTLY-AppStream]
name=appstream
baseurl=http://REPLACE_ME_HERE/rhel-10/nightly/RHEL-10/latest-RHEL-10.2/compose/AppStream/$basearch/os/
enabled=1
# Nightly compose builds are not GPG-signed; gpgcheck=0 is intentional.
gpgcheck=0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The file files/rhel-10-2.repo is redundant and unused. In test/bootc/utils.sh, the repository configuration is dynamically generated at runtime as files/rhel-${VERSION_ID}.repo (which resolves to files/rhel-10.2.repo with a dot, whereas this file uses a hyphen rhel-10-2.repo). Furthermore, this file contains unreplaced placeholders (REPLACE_ME_HERE). This file should be removed from the repository.

Comment thread test/rpm/utils.sh
Comment on lines +256 to +268
local arch
arch=$(uname -m)
for stream in ${compose_streams}; do
local repo_name="compose-${ID}-${VERSION_ID}-${stream}"
sudo tee "/etc/yum.repos.d/${repo_name}.repo" >/dev/null <<EOF
[${repo_name}]
name=${repo_name}
baseurl=${compose_base_url}/${stream}/${arch}/os/
enabled=1
gpgcheck=0
sslverify=0
EOF
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If COMPOSE_BASE_URL is provided with a trailing slash, constructing the baseurl as ${compose_base_url}/${stream}/${arch}/os/ will result in double slashes (e.g., .../compose//BaseOS/...). It is safer to strip any trailing slash from compose_base_url before constructing the repository configuration.

Suggested change
local arch
arch=$(uname -m)
for stream in ${compose_streams}; do
local repo_name="compose-${ID}-${VERSION_ID}-${stream}"
sudo tee "/etc/yum.repos.d/${repo_name}.repo" >/dev/null <<EOF
[${repo_name}]
name=${repo_name}
baseurl=${compose_base_url}/${stream}/${arch}/os/
enabled=1
gpgcheck=0
sslverify=0
EOF
done
local arch
arch=$(uname -m)
compose_base_url="${compose_base_url%/}"
for stream in ${compose_streams}; do
local repo_name="compose-${ID}-${VERSION_ID}-${stream}"
sudo tee "/etc/yum.repos.d/${repo_name}.repo" >/dev/null <<EOF
[${repo_name}]
name=${repo_name}
baseurl=${compose_base_url}/${stream}/${arch}/os/
enabled=1
gpgcheck=0
sslverify=0
EOF
done

Comment thread test/bootc/utils.sh
Comment on lines +85 to +105
elif [ -n "${COMPOSE_BASE_URL:-}" ]; then
# Install go-fdo-client from a compose repository.
# Generate per-stream repo files, copy them into the image, install, then remove them.
local compose_streams="${COMPOSE_STREAMS:-BaseOS AppStream}"
local arch
arch=$(uname -m)
mkdir -p files
local repo_args=""
for stream in ${compose_streams}; do
local repo_name="compose-${ID}-${VERSION_ID}-${stream}"
local repo_file="files/${repo_name}.repo"
cat > "${repo_file}" <<EOF
[${repo_name}]
name=${repo_name}
baseurl=${COMPOSE_BASE_URL}/${stream}/${arch}/os/
enabled=1
gpgcheck=0
sslverify=0
EOF
repo_args+="COPY ${repo_file} /etc/yum.repos.d/${repo_name}.repo"$'\n'
done

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If COMPOSE_BASE_URL is provided with a trailing slash, constructing the baseurl as ${COMPOSE_BASE_URL}/${stream}/${arch}/os/ will result in double slashes. It is safer to strip any trailing slash from COMPOSE_BASE_URL before constructing the repository configuration.

  elif [ -n "${COMPOSE_BASE_URL:-}" ]; then
    # Install go-fdo-client from a compose repository.
    # Generate per-stream repo files, copy them into the image, install, then remove them.
    local compose_streams="${COMPOSE_STREAMS:-BaseOS AppStream}"
    local arch
    arch=$(uname -m)
    local compose_base_url="${COMPOSE_BASE_URL%/}"
    mkdir -p files
    local repo_args=""
    for stream in ${compose_streams}; do
      local repo_name="compose-${ID}-${VERSION_ID}-${stream}"
      local repo_file="files/${repo_name}.repo"
      cat > "${repo_file}" <<EOF
[${repo_name}]
name=${repo_name}
baseurl=${compose_base_url}/${stream}/${arch}/os/
enabled=1
gpgcheck=0
sslverify=0
EOF
      repo_args+="COPY ${repo_file} /etc/yum.repos.d/${repo_name}.repo"$'\n'
    done

@mcattamoredhat
mcattamoredhat force-pushed the test-brew-builds branch 2 times, most recently from aa88912 to 64cd690 Compare June 3, 2026 11:40
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
`parse_brew_url()` set `_brew_ver`/`_brew_rel`/`_brew_arch` as side
effects, but every caller captured it via `url=$(parse_brew_url ...)`.
Command substitution runs the function in a subshell, so those
assignments never reached the calling scope — under `set -u`, the
first reference to `_brew_arch` in install_client()/install_server()
(test/ci, test/rpm, test/bootc) crashed with "unbound variable"
whenever SERVER_RPM_URL or CLIENT_RPM_URL was actually set.

Fix: have parse_brew_url() set _brew_url directly instead of echoing
it, and call it as a plain statement (no command substitution) so all
four variables land in the caller's scope.

No behavior change for any path that doesn't set SERVER_RPM_URL /
CLIENT_RPM_URL: PACKIT_COPR_RPMS-driven Packit/Testing Farm runs and
the GitHub Actions test/ci matrix never touch parse_brew_url() at all
(they short-circuit on PACKIT_COPR_RPMS or don't set these vars),
so this only affects the manual brew-build testing path introduced
in daf355b.

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
- install_from_compose() (test/rpm/utils.sh) and the bootc client
  compose branch (test/bootc/utils.sh) now strip a trailing slash
  from the compose base URL before building baseurl=..., avoiding
  a double slash if the caller passes COMPOSE_BASE_URL with one.
- Remove files/rhel-10-2.repo: unused static template with
  unreplaced REPLACE_ME_HERE placeholders. The real RHEL repo file
  is generated at runtime as files/rhel-${VERSION_ID}.repo
  (test/bootc/utils.sh), so this static file was dead weight.

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
configure_service_firewalld() returned right after `systemctl start
firewalld`, but firewalld >= 2.4.1 (e.g. on Fedora 44) no longer
blocks until its D-Bus interface is ready. configure_service_libvirtd()
runs immediately afterward and calls `virsh net-start integration` on
a network with zone='trusted', which requires firewalld's D-Bus API —
racing it produces:

  error: internal error: zone trusted requested for network
  integration but firewalld is not active

Poll `firewall-cmd --state` (up to 30s) after starting firewalld,
bailing out with diagnostics if the unit dies or the timeout is hit.

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
@mcattamoredhat
mcattamoredhat marked this pull request as ready for review July 22, 2026 14:10
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

mcattamoredhat added a commit to mcattamoredhat/go-fdo-ci that referenced this pull request Jul 27, 2026
Port brew-build and compose-repository install support from
fido-device-onboard/go-fdo-server#239 into the shared
test/{ci,rpm,bootc}/utils.sh, so test/rpm and test/bootc can
install go-fdo-client/go-fdo-server from a brew build
(CLIENT_RPM_URL/SERVER_RPM_URL) or a compose snapshot
(COMPOSE_BASE_URL/COMPOSE_STREAMS), on top of the existing
COPR/Packit/local-build paths.

Also carries over the upstream follow-up fixes: parse_brew_url()
sets its output vars directly to survive subshell calls, trailing
slashes are stripped from COMPOSE_BASE_URL, and test/bootc waits
for firewalld's D-Bus interface before starting the libvirt
network (firewalld >= 2.4.1 no longer blocks on it at startup).

parse_brew_url() is added to test/ci/utils.sh since both
test/rpm/utils.sh and test/bootc/utils.sh source down to it; it
isn't used by ci/utils.sh's own git-source-based install functions.
No behavior change for PACKIT_COPR_RPMS-driven or local-build runs.

Ports: fido-device-onboard/go-fdo-server#239

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
@mcattamoredhat

Copy link
Copy Markdown
Author

Closing this PR and opening fido-device-onboard/go-fdo-ci#20

mcattamoredhat added a commit to mcattamoredhat/go-fdo-ci that referenced this pull request Jul 30, 2026
Port brew-build and compose-repository install support from
fido-device-onboard/go-fdo-server#239 into the shared
test/{ci,rpm,bootc}/utils.sh, so test/rpm and test/bootc can
install go-fdo-client/go-fdo-server from a brew build
(CLIENT_RPM_URL/SERVER_RPM_URL) or a compose snapshot
(COMPOSE_BASE_URL/COMPOSE_STREAMS), on top of the existing
COPR/Packit/local-build paths.

Also carries over the upstream follow-up fixes: parse_brew_url()
sets its output vars directly to survive subshell calls, trailing
slashes are stripped from COMPOSE_BASE_URL, and test/bootc waits
for firewalld's D-Bus interface before starting the libvirt
network (firewalld >= 2.4.1 no longer blocks on it at startup).

parse_brew_url() is added to test/ci/utils.sh since both
test/rpm/utils.sh and test/bootc/utils.sh source down to it; it
isn't used by ci/utils.sh's own git-source-based install functions.
No behavior change for PACKIT_COPR_RPMS-driven or local-build runs.

Ports: fido-device-onboard/go-fdo-server#239

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
mcattamoredhat added a commit to mcattamoredhat/go-fdo-ci that referenced this pull request Aug 3, 2026
Port brew-build and compose-repository install support from
fido-device-onboard/go-fdo-server#239 into the shared
test/{ci,rpm,bootc}/utils.sh, so test/rpm and test/bootc can
install go-fdo-client/go-fdo-server from a brew build
(BREW_CLIENT_RPMS_URL/BREW_SERVER_RPMS_URL) or a compose snapshot
(COMPOSE_BASE_URL/COMPOSE_STREAMS), on top of the existing
COPR/Packit/local-build paths.

rpms_from_brew_url() (test/ci/utils.sh) lists the RPM URLs actually
published under a brew build's ${arch}/ and noarch/ directories,
rather than hardcoding each sub-package's name, so it doesn't need
to be kept in sync whenever brew's package layout changes.

Also carries over the upstream follow-up fixes: trailing slashes
are stripped from COMPOSE_BASE_URL, and test/bootc waits for
firewalld's D-Bus interface before starting the libvirt network
(firewalld >= 2.4.1 no longer blocks on it at startup).

rpms_from_brew_url() is added to test/ci/utils.sh since both
test/rpm/utils.sh and test/bootc/utils.sh source down to it; it
isn't used by ci/utils.sh's own git-source-based install functions.
No behavior change for PACKIT_COPR_RPMS-driven or local-build runs.

Assisted-by: Claude (claude-sonnet-5)
Signed-off-by: Mario Cattamo <mcattamo@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant