Skip to content

Rework tag_deploy/release_rpms: surface Forge errors, fix tag-triggered RPM builds (el8/el9/el10) - #44

Merged
silug merged 7 commits into
mainfrom
robust-forge-deploy
Aug 13, 2026
Merged

Rework tag_deploy/release_rpms: surface Forge errors, fix tag-triggered RPM builds (el8/el9/el10)#44
silug merged 7 commits into
mainfrom
robust-forge-deploy

Conversation

@silug

@silug silug commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Closes #84.

This started as the Forge-deploy robustness work (first three commits) and grew into the full tag-and-release rework, per our convention of combining the template change and the workflow-run session config in one PR so they're tested together:

  1. Surface the Forge API responsecurl --fail discarded the response body, so a failed Forge publish reported only a bare HTTP status (the simp-gpasswd 2.0.0 release died with an unexplained 403). The deploy step now prints the response body and status and fails on any non-2xx result.
  2. Preserve the built module archive — uploaded as a workflow artifact and attached to the GitHub release, so the exact bytes sent to the Forge are always recoverable.
  3. Reconcile tag_deploy.yml with the deployed fleet — the template still described the Puppet-7/PDK era (PUPPET_VERSION '~> 7', Ruby 2.7, checkout@v5, pdk build); deployed copies have long since moved to '~> 8', Ruby 3.4.9, checkout@v7, and rake pupmod:build. Reconciling first keeps the rollout diff down to the intended changes (verified: the merged diff on a real clone touches nothing else).
  4. Fix tag-triggered RPM builds (tag_deploy workflows hardcode centos7/centos8 RPM builds; move the OS matrix into release_rpms.yml (el8/el9/el10) #84) — every tag push dispatched two release_rpms.yml runs hardcoded to the retired centos7/centos8 containers, overriding Pull RPM build containers from ghcr.io/simp/simp-<os>-build (fixes fleet-wide RPM build failures) #80's el8 default; all 14 tag-triggered RPM builds since 2026-07-28 failed. All three caller templates now dispatch once with no OS override, and release_rpms.yml owns the build-OS list via a build_container_oses input (default '["el8","el9","el10"]', narrowable on manual runs). Per-release work is split into a resolve-release job so the parallel per-OS legs can't race on release autocreation or the clean asset wipe; both build inputs are now required: false. Output changes from two RPMs per tag to three (el8/el9/el10) — intended.
  5. Fix broken prerelease detectionvalidate-inputs wrote {name}={value} to GITHUB_OUTPUT (invalid syntax), so prebuild_suffix/build_semver never populated: prerelease tags were treated as full releases and the RPM release-tag customization never ran. Now name=value.
  6. Retire the EL7/EL8 tag_deploy variant (tag_deploy workflows hardcode centos7/centos8 RPM builds; move the OS matrix into release_rpms.yml (el8/el9/el10) #84) — with EL7 gone and the OS choice living in release_rpms.yml, it had no remaining purpose; pkg-r10k and simp-adapter fall back to the standard simp_unknown presets, whose absent list removes the deployed file on their next apply sync.
  7. Session config 20260812-tag-deploy-rpm-matrix.yaml (now latest) — merges tag_deploy.yml + release_rpms.yml fleet-wide (scoped, Renovate-managed scalars preserved as always).

Verified: 210 rspec + 19 BoltSpec plan examples green; all plans parse and load; YAML validates; local e2e against a real pupmod-simp-aide clone produces exactly the intended diff with all deployed Renovate values (checkout@v7, github-script@v9, ubuntu-24.04) preserved.

Note: the simp-* asset repos (simp-doc, simp-utils, …) carry the same caller templates but aren't in the dynamic inventory or permitted project types — they pick up the fixed templates on their next apply_puppet_role sync, and the session config notes this. Once merged and rolled out, the failed releases in #84's evidence table can be rebuilt by re-dispatching release_rpms.yml — no re-tagging needed.

🤖 Generated with Claude Code

silug added a commit that referenced this pull request Jul 24, 2026
Mirrors #44 so the two branches merge cleanly in
either order.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCnDsYaJDLiP8z8tafz9Tp
@silug

silug commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Added a second robustness improvement prompted by the gpasswd post-mortem: the built module archive is now uploaded as a workflow artifact before the Forge POST, so every tag run — pass or fail — leaves the exact tarball downloadable from the run page (previously a failed upload left nothing: no artifact, and the GitHub release carries no assets). Mirrored to #42 as before.

@silug

silug commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Third improvement: the module archive is now also attached to the GitHub release (gh release upload --clobber, default GITHUB_TOKEN — same token the release-creation job already uses). Assets are permanent and public, unlike workflow artifacts (authenticated, 90-day expiry), and the upload happens before the Forge POST so a failed publish still leaves the exact archive on the release page. Note: prerelease tags skip this whole job (existing if:), so prereleases get neither Forge nor assets — unchanged behavior. Mirrored to #42.

@hcaballero2 hcaballero2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skeptical review — I went looking for the usual failure modes in "attach assets + surface API errors" changes and verified the PR's claims against the actual branch contents rather than the description. What checks out:

  • Ordering is sound. deploy-to-puppet-forge has needs: [create-github-release], so the release exists before gh release upload runs — no race. And attaching before the Forge POST is the right order, not just for evidence-preservation: the inverse order plus a transient attach failure would force a job re-run whose Forge POST would then 409 on the already-published version.
  • The prerelease claim is accurate: the skip is the job-level if: needs.create-github-release.outputs.prerelease != 'yes', so the new artifact/attach steps can't run for prereleases (where no non-draft release semantics would apply).
  • The token claim is accurate: create-github-release already does gh release create with the default GITHUB_TOKEN, so gh release upload needs nothing the workflow doesn't already rely on.
  • actions/upload-artifact@v7 is the current major (v7.0.1), and if-no-files-found: error means a missing tarball now fails fast at the artifact step instead of producing a cryptic curl --form file=@ error two steps later.
  • The "mirrored to #42" claim is trueopenvox9-ruby4-template-refresh carries the identical three-step change (verified lines 188/196/202-215 of its tag_deploy.yml).
  • Error handling holds up at the transport level too: GitHub run: steps default to bash -e, so a non-HTTP curl failure (DNS, TLS) fails the step at the http_code= assignment with --show-error output; the case only needs to cover HTTP-level failures, which is exactly what the old --fail was eating. Failing on 3xx (which --fail did not) is a behavior change, but a correct one for a POST that should never redirect.

Two small suggestions inline; neither blocks.

silug and others added 7 commits August 12, 2026 19:40
curl --fail discards the response body, so a failed publish reports
only an HTTP status (the simp-gpasswd 2.0.0 release died with a bare
403). Capture the body and status, print both, and fail on any
non-2xx result so the Forge's own error message lands in the job log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCnDsYaJDLiP8z8tafz9Tp
A failed Forge upload previously left nothing to download - the
tarball existed only on the runner and the GitHub release carries no
assets. Upload it before attempting the Forge POST so every tag run,
pass or fail, leaves the exact archive available from the run page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCnDsYaJDLiP8z8tafz9Tp
Release assets are permanent and publicly downloadable, unlike
workflow artifacts (authenticated, expiring). Uploaded before the
Forge POST so a failed publish still leaves the exact archive on the
release. --clobber keeps job re-runs idempotent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCnDsYaJDLiP8z8tafz9Tp
The deployed workflows have moved on (PUPPET_VERSION '~> 8', Ruby 3.4.9,
checkout@v7, github-script@v9, rake pupmod:build instead of pdk build)
while the template still described the Puppet-7 era. Reconciling before
the sync keeps the rollout diff down to the intended changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every tag push has been dispatching two release_rpms.yml runs hardcoded
to the retired centos7/centos8 containers, overriding #80's el8 default
— all tag-triggered RPM builds fail. The caller templates now dispatch
once with no OS override, and release_rpms.yml owns the build-OS list
via a build_container_oses input (default '["el8","el9","el10"]',
narrowable on manual runs).

Per-release work (release lookup/creation, the clean-input asset wipe)
is split into a resolve-release job so the parallel per-OS legs cannot
race on release autocreation or wipe each other's uploads, and both
build inputs are required: false so omitting them in dispatch calls is
well-defined.

Also fixes validate-inputs writing '{name}={value}' to GITHUB_OUTPUT —
invalid syntax, so prebuild_suffix/build_semver never populated and
prerelease tags were treated as full releases.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
EL7 is gone fleet-wide and the per-OS choice now lives in
release_rpms.yml, so tag_deploy_github-rpms-el7-el8.yml had no remaining
purpose. pkg-r10k and simp-adapter fall back to the standard
simp_unknown presets, whose absent list already removes the file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@silug silug changed the title Surface the Forge API response in the tag_deploy Forge step Rework tag_deploy/release_rpms: surface Forge errors, fix tag-triggered RPM builds (el8/el9/el10) Aug 12, 2026
@silug
silug force-pushed the robust-forge-deploy branch from f713fb1 to 346cdc3 Compare August 12, 2026 19:50
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.

tag_deploy workflows hardcode centos7/centos8 RPM builds; move the OS matrix into release_rpms.yml (el8/el9/el10)

3 participants