You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#80 fixed release_rpms.yml to pull builders from ghcr.io/simp/simp-<os>-build with build_container_os defaulting to el8. That rolled out to ~70 repos — but RPM builds are still failing fleet-wide, because the workflows that dispatchrelease_rpms.yml override the default with a hardcoded centos7/centos8 matrix.
Every tag push therefore fires two builds, both explicitly requesting retired container OSes, and both die on:
NameError: uninitialized constant JSON::Fragment
#80's new default is never reached.
Root cause
All four caller templates hardcode the same matrix:
Proposed fix — drop the caller matrix, move it into release_rpms.yml
Decision (2026-08-12): build el8, el9, and el10 RPMs per tag, and express that in exactly one place.
Two goals that pull in opposite directions unless the matrix moves:
the build-OS list must not be duplicated across 4 templates × 79 repos, and
one tag must produce three RPMs.
A caller-side matrix can only satisfy the second by reintroducing the first. So:
1. Callers dispatch once and say nothing about the OS. Remove the strategy: block and drop build_container_os from the dispatch inputs in all four templates. The matrix is referenced 5 times in pupmod/.../tag_deploy.yml but only one is functional:
Line
Use
Kind
136-139
strategy.matrix.os: [centos7, centos8]
definition
141
step name Trigger RPM release workflow (${{ matrix.os }})
cosmetic
149
console.log(... for os '${{ matrix.os }}')
cosmetic
160
build_container_os: '${{ matrix.os }}'
functional
163
console.log(... from ${{ matrix.os }}: status ...)
cosmetic
2. release_rpms.yml gains the matrix. It currently has a single job, create-and-attach-rpms-to-github-release (line 93), with no strategy: — so add one driven by a single input, e.g.:
That keeps one source of truth, still lets a manual run narrow the set ('["el9"]'), and makes "which EL versions do we ship RPMs for" a one-line answer.
RPM filenames do not collide — dist tags .el8 / .el9 / .el10 differ — so all three attach to the same release cleanly.
Split the job in two while adding the matrix
Both of the fan-out hazards below come from the same structural issue: the single job create-and-attach-rpms-to-github-release mixes per-release work (resolve/create the release,
optionally wipe its assets) with per-OS work (build, sign, upload). Harmless while it runs once;
racy the moment it runs three times. Rather than guard each symptom, separate the concerns:
jobs:
resolve-release: # runs ONCE# - GET release by tag, create on 404 when autocreate_release == 'yes'# - wipe assets when clean == 'yes'outputs:
release_id: ...build-and-attach: # matrix: el8, el9, el10needs: [resolve-release]strategy:
matrix:
os: ${{ fromJSON(github.event.inputs.build_container_oses) }}# - build + sign + upload for one OS, using needs.resolve-release.outputs.release_id
This is barely more work than adding the matrix to the existing job, and it removes both hazards
structurally instead of patching them:
clean: 'yes' asset-wipe race. The "Wipe all previous assets from GitHub Release" step
(line 264) deletes all assets on the release. With three parallel legs, one can wipe what
another just uploaded. The alternative to splitting — gating the wipe with if: matrix.os == 'el8' — is fragile: it silently stops running the moment someone narrows the
matrix to '["el9"]'.
Autocreate race. The release-api step (lines 124-198) GETs the release by tag and creates
it on 404. Three parallel legs against a missing release all attempt the create; two lose. The
alternative to splitting is 422 already_exists retry logic in the script.
Severity note: neither hazard is reachable from the tag-triggered path — callers pass clean: 'no', and create-github-release runs first via needs:, so the release always exists.
Both only bite manual release_rpms.yml dispatches. That makes this important but not urgent; the
reason to do it now is that the matrix change touches this job anyway, and clean: 'yes' deleting
release assets is a poor footgun to leave armed.
Also required: make the inputs non-required
build_container_os and build_container_tag are currently required: true (with defaults). Once
callers omit them, behaviour depends on GitHub applying defaults to omitted workflow_dispatch
inputs. It does, and required is effectively a UI-form concern — but if that were ever untrue, every tag-triggered release would fail at the dispatch call, which is worse than today (no run
at all rather than a visibly failing one). Flip both to required: false; they have defaults, so
nothing else changes.
Consequence to state plainly
Output changes from two RPMs per tag (centos7, centos8) to three (el8, el9, el10). Intended — but worth noting so the change in artifact count is not read as a regression either way.
Also settle while here
tag_deploy_github-rpms-el7-el8.yml is EL7/EL8-specific by name. With EL7 gone fleet-wide, decide whether it still has a purpose or should be retired rather than updated.
Scope
79 repos have a tag_deploy.yml naming centos7/centos8 — all of them with exactly that pair. Because this is template-owned, it is a sync rollout, not per-repo edits.
Once fixed, the affected releases above should be re-buildable by re-dispatching release_rpms.yml — no re-tagging required, since the tags already exist.
Immediate workaround for anyone releasing before this lands: dispatch release_rpms.yml manually with build_container_os=el8 rather than relying on the tag-triggered path.
Summary
#80 fixed
release_rpms.ymlto pull builders fromghcr.io/simp/simp-<os>-buildwithbuild_container_osdefaulting toel8. That rolled out to ~70 repos — but RPM builds are still failing fleet-wide, because the workflows that dispatchrelease_rpms.ymloverride the default with a hardcodedcentos7/centos8matrix.Every tag push therefore fires two builds, both explicitly requesting retired container OSes, and both die on:
#80's new default is never reached.Root cause
All four caller templates hardcode the same matrix:
modules/profile/files/pupmod/_github/workflows/tag_deploy.ymlmodules/profile/files/_github/workflows/tag_deploy_github-rpms.ymlmodules/profile/files/_github/workflows/tag_deploy_github-rpms-el7-el8.ymlmodules/profile/files/_github/workflows/tag_deploy_rubygem__github-rpms.ymlEvidence
14
release_rpms.ymlruns since 2026-07-28 — every one failed, exactly 2 per tag:pupmod-simp-auditdpupmod-simp-simppupmod-simp-pampupmod-simp-sssdpupmod-simp-simplibpupmod-simp-svckillpupmod-voxpupuli-selinuxSample job names, showing the override in action on repos that do have #80's fix:
simp/pupmod-simp-svckill 5.1.0 (build os: centos7)— itsrelease_rpms.ymlhasdefault: 'el8'and the ghcr image linesimp/pupmod-simp-simplib 7.0.0 (build os: centos8)— samesimp/pupmod-voxpupuli-selinux simp-6.0.0 (build os: centos8)— this repo has not received Pull RPM build containers from ghcr.io/simp/simp-<os>-build (fixes fleet-wide RPM build failures) #80 yet, so it is failing for both reasonsProposed fix — drop the caller matrix, move it into
release_rpms.ymlDecision (2026-08-12): build
el8,el9, andel10RPMs per tag, and express that in exactly one place.Two goals that pull in opposite directions unless the matrix moves:
A caller-side matrix can only satisfy the second by reintroducing the first. So:
1. Callers dispatch once and say nothing about the OS. Remove the
strategy:block and dropbuild_container_osfrom the dispatchinputsin all four templates. The matrix is referenced 5 times inpupmod/.../tag_deploy.ymlbut only one is functional:strategy.matrix.os: [centos7, centos8]Trigger RPM release workflow (${{ matrix.os }})console.log(... for os '${{ matrix.os }}')build_container_os: '${{ matrix.os }}'console.log(... from ${{ matrix.os }}: status ...)2.
release_rpms.ymlgains the matrix. It currently has a single job,create-and-attach-rpms-to-github-release(line 93), with nostrategy:— so add one driven by a single input, e.g.:That keeps one source of truth, still lets a manual run narrow the set (
'["el9"]'), and makes "which EL versions do we ship RPMs for" a one-line answer.RPM filenames do not collide — dist tags
.el8/.el9/.el10differ — so all three attach to the same release cleanly.Split the job in two while adding the matrix
Both of the fan-out hazards below come from the same structural issue: the single job
create-and-attach-rpms-to-github-releasemixes per-release work (resolve/create the release,optionally wipe its assets) with per-OS work (build, sign, upload). Harmless while it runs once;
racy the moment it runs three times. Rather than guard each symptom, separate the concerns:
This is barely more work than adding the matrix to the existing job, and it removes both hazards
structurally instead of patching them:
clean: 'yes'asset-wipe race. The "Wipe all previous assets from GitHub Release" step(line 264) deletes all assets on the release. With three parallel legs, one can wipe what
another just uploaded. The alternative to splitting — gating the wipe with
if: matrix.os == 'el8'— is fragile: it silently stops running the moment someone narrows thematrix to
'["el9"]'.release-apistep (lines 124-198) GETs the release by tag and createsit on 404. Three parallel legs against a missing release all attempt the create; two lose. The
alternative to splitting is 422
already_existsretry logic in the script.Severity note: neither hazard is reachable from the tag-triggered path — callers pass
clean: 'no', andcreate-github-releaseruns first vianeeds:, so the release always exists.Both only bite manual
release_rpms.ymldispatches. That makes this important but not urgent; thereason to do it now is that the matrix change touches this job anyway, and
clean: 'yes'deletingrelease assets is a poor footgun to leave armed.
Also required: make the inputs non-required
build_container_osandbuild_container_tagare currentlyrequired: true(with defaults). Oncecallers omit them, behaviour depends on GitHub applying defaults to omitted
workflow_dispatchinputs. It does, and
requiredis effectively a UI-form concern — but if that were ever untrue,every tag-triggered release would fail at the dispatch call, which is worse than today (no run
at all rather than a visibly failing one). Flip both to
required: false; they have defaults, sonothing else changes.
Consequence to state plainly
Output changes from two RPMs per tag (
centos7,centos8) to three (el8,el9,el10). Intended — but worth noting so the change in artifact count is not read as a regression either way.Also settle while here
tag_deploy_github-rpms-el7-el8.ymlis EL7/EL8-specific by name. With EL7 gone fleet-wide, decide whether it still has a purpose or should be retired rather than updated.Scope
79 repos have a
tag_deploy.ymlnamingcentos7/centos8— all of them with exactly that pair. Because this is template-owned, it is a sync rollout, not per-repo edits.Notes
pupmod/_github/workflows/tag_deploy.ymlbut does not fix this — it only coverspdk→rake pupmod:build, action/Ruby version bumps, and module-archive artifact upload. No matrix change.release_rpms.yml— no re-tagging required, since the tags already exist.release_rpms.ymlmanually withbuild_container_os=el8rather than relying on the tag-triggered path.Affected repos (79)
pupmod-simp-acpidpupmod-simp-aidepupmod-simp-atpupmod-simp-auditdpupmod-simp-autofspupmod-simp-clamavpupmod-simp-compliance_markuppupmod-simp-cronpupmod-simp-crypto_policypupmod-simp-dconfpupmod-simp-deferred_resourcespupmod-simp-dhcppupmod-simp-ds389pupmod-simp-fipspupmod-simp-freeradiuspupmod-simp-gdmpupmod-simp-gnomepupmod-simp-havegedpupmod-simp-imapupmod-simp-iptablespupmod-simp-issuepupmod-simp-krb5pupmod-simp-libreswanpupmod-simp-libvirtpupmod-simp-logrotatepupmod-simp-matepupmod-simp-mockuppupmod-simp-mozillapupmod-simp-namedpupmod-simp-nfspupmod-simp-oathpupmod-simp-oddjobpupmod-simp-openscappupmod-simp-pampupmod-simp-pkipupmod-simp-polkitpupmod-simp-postfixpupmod-simp-pupmodpupmod-simp-resolvpupmod-simp-rsyncpupmod-simp-rsyslogpupmod-simp-selinuxpupmod-simp-simp_apachepupmod-simp-simp_authselectpupmod-simp-simp_bannerspupmod-simp-simp_ds389pupmod-simp-simp_firewalldpupmod-simp-simp_gitlabpupmod-simp-simp_grubpupmod-simp-simpkvpupmod-simp-simplibpupmod-simp-simp_nfspupmod-simp-simp_optionspupmod-simp-simp_rsyslogpupmod-simp-simp_snmpdpupmod-simp-simppupmod-simp-sitepupmod-simp-sshpupmod-simp-sssdpupmod-simp-stunnelpupmod-simp-sudopupmod-simp-svckillpupmod-simp-swappupmod-simp-tftpbootpupmod-simp-tlogpupmod-simp-tpm2pupmod-simp-tunedpupmod-simp-useraddpupmod-simp-vncpupmod-simp-vsftpdpupmod-simp-x2gopupmod-voxpupuli-selinuxpuppet-gpasswdsimp-docsimp-environment-skeletonsimp-gpgkeyssimp-rsync-skeletonsimp-selinux-policysimp-utils