Modernize build/test Dockerfiles: fail-fast scripts, rvm->mise, OpenVox - #925
Merged
Conversation
The build-container scripts ran without `set -e`, so a failing command masked by a later success (or a blanket `||:`) let the build complete as though it had succeeded. The AlmaLinux 8/9/10 Beaker images shipped broken this way (e.g. redhat-lsb-core does not exist on EL9/10 and silently no-op'd). Make every script fail-fast and modernize the toolchain. Reliability: - Add `set -euo pipefail` and a purpose/usage header to every script; standardize shebangs to bash. - beaker_packages.sh: drop the blanket `||:` so a missing package fails the build; remove redhat-lsb-core (retired on EL9/10, unused). - container_safe_services.sh: guard `systemctl daemon-reload`, which legitimately fails offline during the image build. - user.sh: fix single-quoted sudoers lines that wrote a literal "$user_id" instead of the username. Toolchain (build images): - Replace rvm with mise. Add per-EL install_mise.sh (EL8 rpm repo, EL9/10 COPR) and common mise.sh provisioning Ruby 3.2 (OpenVox 8) and 4.0 (OpenVox 9); default 3.2 via the ruby_version build arg. - Pin bundler to 2.7.2 (simp-rake-helpers requires < 3.0). - Add libyaml-devel on EL8/EL9 so Ruby's psych extension compiles. - Build dockerfiles: default ruby_version=3.2; call install_mise.sh + mise.sh instead of rvm.sh. Docs/CI: - README: document the two image families and per-script purpose table; reframe build args around OpenVox; fix stale Dockerhub -> ghcr.io note. - build_containers.yml: Ruby choices 2.7/3.1/3.3 -> 3.2/4.0, default 3.2. All six images (EL8/9/10 Beaker + Build) build and smoke-test clean locally with podman. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add CI to build the build/Dockerfiles images automatically, complementing the existing manual workflow. - build_container.yml: new reusable (workflow_call) workflow that builds one image and optionally pushes it to ghcr.io, tagged `latest` and a UTC `YYYYMMDD` date tag so it is clear when an image was built. - containers.yml: builds all six images (EL8/9/10 Beaker + Build) via a matrix. Pull requests touching the Dockerfiles build without pushing (pre-merge validation, which the fail-fast scripts make meaningful); push to master (path-filtered), a weekly schedule, and manual dispatch build and push. The schedule keeps images current with upstream updates. - build_containers.yml: refactored to call the reusable workflow; retained for ad-hoc single-image rebuilds (specific Ruby version, ref, extra tag). - AGENTS.md: document the three container workflows. Validated with actionlint (clean). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR modernizes the SIMP build/test container infrastructure by making build scripts fail-fast, replacing RVM with mise for Ruby provisioning, updating the default Ruby/toolchain expectations for OpenVox, and adding CI workflows to validate and publish container images built from build/Dockerfiles/.
Changes:
- Switch ISO build images from
rvm.shto per-ELinstall_mise.sh+ commonmise.sh, and bump defaultruby_versionto 3.2. - Make container build scripts consistent and fail-fast (
bash+set -euo pipefail), and fix Beaker/base package installation behavior. - Add/reshape GitHub Actions workflows to build all images on relevant PRs and publish them on push/schedule/manual runs.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| build/Dockerfiles/SIMP_EL8_Build.dockerfile | Default Ruby build arg to 3.2 and switch Ruby provisioning to mise. |
| build/Dockerfiles/SIMP_EL9_Build.dockerfile | Default Ruby build arg to 3.2 and switch Ruby provisioning to mise. |
| build/Dockerfiles/SIMP_EL10_Build.dockerfile | Default Ruby build arg to 3.2 and switch Ruby provisioning to mise. |
| build/Dockerfiles/scripts/el8/install_mise.sh | Install mise system-wide on EL8 via upstream repo. |
| build/Dockerfiles/scripts/el9/install_mise.sh | Install mise system-wide on EL9 via COPR. |
| build/Dockerfiles/scripts/el10/install_mise.sh | Install mise system-wide on EL10 via COPR. |
| build/Dockerfiles/scripts/el8/00_system_prep.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el9/00_system_prep.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el10/00_system_prep.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el8/00_setup_vault.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el9/00_setup_vault.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el10/00_setup_vault.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el8/05_selinux.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el9/05_selinux.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el10/05_selinux.sh | Standardize script header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/el8/10_dev_packages.sh | Add libyaml-devel and standardize script header/fail-fast behavior. |
| build/Dockerfiles/scripts/el9/10_dev_packages.sh | Add libyaml-devel and standardize script header/fail-fast behavior. |
| build/Dockerfiles/scripts/el10/10_dev_packages.sh | Standardize script header/fail-fast behavior (and includes libyaml-devel). |
| build/Dockerfiles/scripts/common/rvm.sh | Remove legacy RVM-based Ruby provisioning script. |
| build/Dockerfiles/scripts/common/mise.sh | New: provision Ruby via mise and pin bundler version. |
| build/Dockerfiles/scripts/common/user.sh | Standardize header/fail-fast behavior and fix sudoers variable expansion. |
| build/Dockerfiles/scripts/common/prime_ruby.sh | Standardize header/fail-fast behavior and tighten quoting/commands. |
| build/Dockerfiles/scripts/common/minimize_package_installs.sh | Add header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/common/package_cleanup.sh | Add header and enforce fail-fast shell settings. |
| build/Dockerfiles/scripts/common/container_safe_services.sh | Add header and guard systemctl daemon-reload during image build. |
| build/Dockerfiles/scripts/common/beaker_packages.sh | Make Beaker package installs fail-fast and drop redhat-lsb-core. |
| build/Dockerfiles/README.md | Document image families, scripts, and mise/OpenVox-focused build args. |
| AGENTS.md | Update CI workflow documentation to include new container workflows. |
| .github/workflows/containers.yml | New: build all Dockerfiles on relevant PRs; publish on push/schedule/manual runs. |
| .github/workflows/build_container.yml | New reusable workflow to build/push a single image with consistent tagging. |
| .github/workflows/build_containers.yml | Refactor manual workflow to call the reusable build workflow and update Ruby choices. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Two fixes from PR review: - mise.sh: always install both supported Rubies (3.2 + 4.0) and reject any ruby_version other than 3.2/4.0, instead of letting an unexpected value drop Ruby 3.2 and fail the later `mise exec ruby@3.2` bundler install. The build arg now only selects which Ruby is the global default. - user.sh: write sudo config to a 0440 /etc/sudoers.d/<user> drop-in (idempotent across rebuilds) and validate it with `visudo -cf` instead of appending to /etc/sudoers, so a malformed line can't break sudo for the whole image. sudo is installed in 05_selinux.sh, before user.sh. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The static workflow name "Containers: build + publish" mislabeled PR runs, which build images but never publish them (push: false on pull_request). - Rename the workflow to the neutral "Containers" and add a dynamic run-name that reads "build (no publish)" on PRs and "build + publish" otherwise. - Rename the caller job containers -> build so the PR check reads "Containers / build / <image>" instead of "containers / containers". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nick-markowski
approved these changes
Jun 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The build-container scripts ran without
set -e, so a failing command masked by a later success — or a blanket||:— let the image build complete as though it had succeeded. The AlmaLinux 8/9/10 Beaker images (ghcr.io/simp/simp-el<N>-beaker) shipped broken this way:redhat-lsb-coredoes not exist on EL9/10, so its install silently no-op'd and the resulting images were missing packages with no build-time signal.This PR makes every script fail-fast, modernizes the toolchain (rvm → mise, Puppet → OpenVox, Ruby 3.2/4.0), and adds CI to build and publish the images automatically.
Changes
Reliability
set -euo pipefailand a purpose/usage header to every script; standardize shebangs tobash.beaker_packages.sh: drop the blanket||:so a missing package fails the build; removeredhat-lsb-core(retired on EL9/10, unused by the acceptance stack).container_safe_services.sh: guardsystemctl daemon-reload, which legitimately fails offline during the image build.user.sh: fix single-quoted sudoers lines that wrote a literal$user_idinstead of the username.Toolchain (build images)
install_mise.sh(EL8 rpm repo, EL9/10 COPR) and a commonmise.shthat provisions Ruby 3.2 (OpenVox 8) and 4.0 (OpenVox 9); default selectable via theruby_versionbuild arg (default3.2).2.7.2(simp-rake-helpersrequires< 3.0).libyaml-develon EL8/EL9 so Ruby'spsychextension compiles.ruby_version=3.2; callinstall_mise.sh+mise.shinstead ofrvm.sh.CI automation
build_container.yml(new) — reusable (workflow_call) workflow that builds one image and optionally pushes it toghcr.io, taggedlatestand a UTCYYYYMMDDdate tag so it is clear when an image was built. It only logs into the registry when actually pushing, so fork PRs (read-onlyGITHUB_TOKEN) still validate cleanly.containers.yml(new) — builds all six images (EL8/9/10 Beaker + Build) via a matrix calling the reusable workflow:build/Dockerfiles/**build every image without pushing — pre-merge validation that the now-fail-fast scripts make meaningful.ghcr.io. The schedule keeps images current with upstream base/package updates even when the Dockerfiles are unchanged.build_containers.yml— refactored to call the reusable workflow; retained for ad-hoc single-image rebuilds (specific Ruby version, git ref, or extra tag).Docs
README: document the two image families (Beaker SUT vs. ISO build) and a per-script purpose table; reframe build args around OpenVox; fix the stale Dockerhub → ghcr.io note.AGENTS.md: document the three container workflows.Bugs surfaced by fail-fast (would have shipped broken before)
Because the scripts now abort on error, building the Build images locally exposed two real problems the old silent scripts hid:
libyamlbut notlibyaml-devel, so thepsychextension failed (noyaml.h). Fixed by addinglibyaml-devel.simp-rake-helpers(< 3.0) rejects. Pinned to2.7.2(matches simp-core'sGemfile.lock).Testing
All six images built and smoke-tested locally with
podman build(AlmaLinux 8/9/10):simp-el{8,9,10}-beakercontainer_safe_servicesunit enabled,redhat-lsb-corecorrectly absentsimp-el{8,9,10}-buildsimp-corebundle satisfiedThe CI workflows were validated with
actionlint(clean).Notes for reviewers
https://mise.en.dev/rpm/mise.repo, taken from the official mise docs; it resolves as a mirror ofmise.jdx.dev(GPG keyrelease@mise.jdx.dev). EL9/10 use thejdxcode/miseCOPR.ruby_versionbuild arg (Docker emits a harmless "build-arg not consumed" warning).