diff --git a/data/sync/configs/20261025-release-rpms-gpg-key-race.yaml b/data/sync/configs/20261025-release-rpms-gpg-key-race.yaml new file mode 100644 index 0000000..67d0e37 --- /dev/null +++ b/data/sync/configs/20261025-release-rpms-gpg-key-race.yaml @@ -0,0 +1,82 @@ +--- +# Roll out the release_rpms.yml GPG key upload fix to every repo that +# carries it. +# +# Every OS leg of the build matrix signs with the same key and produces the +# same RPM-GPG-KEY-SIMP-UNSTABLE-2.pub.asc, and every leg clobbered and +# re-uploaded it. Run in parallel, those uploads race, so a leg fails with +# 'already_exists' or 'Not Found' and cancels the others. During the +# 2026-10-14 module releases many runs reported failure this way, even +# though every release ended up with all of its assets. Only the first OS +# in build_container_oses attaches the key now. +# +# release_rpms.yml (merge_github_workflows, scoped to that one file): the +# template is shared by every project type, so the merge is widened from the +# pupmod default to rubygem (rubygem-simp-cli) and simp_unknown (the +# packaging repos). The template's header now says "standardized asset +# baseline", like the other shared templates, instead of "puppet module +# baseline". In the module repos that header line changes too; in +# simp-adapter, simp-doc and simp-utils it already matches. +# +# Expected result (checked against every repo's current release_rpms.yml): +# one PR in each of the 80 selected repos, changing only the key-upload +# lines and, in the module repos, the header comment. merge_github_workflows +# creates a workflow that a repo lacks, so the repolist selects only repos +# that already have release_rpms.yml, and it excludes compliance_markup +# (see the comment there). +# +# No version bump: .github/ changes don't affect release artifacts. +# +# Run with `repolist=20261025-release-rpms-gpg-key-race`. +puppetsync::plan_config: + puppetsync: + permitted_project_types: + - pupmod + - pupmod_skeleton + - rubygem + - simp_unknown + plans: + sync: + github_api_delay_seconds: 1 + merge_github_workflows: + files: + - release_rpms.yml + project_types: + - pupmod + - pupmod_skeleton + - rubygem + - simp_unknown + stages: + - install_gems + - checkout_git_feature_branch_in_each_repo + - merge_github_workflows + - git_commit_changes + - ensure_github_fork + - ensure_git_remote + - git_push_to_remote + - ensure_github_pr + + approve_github_prs: + stages: + - approve_github_pr_for_each_repo + + merge_github_prs: + stages: + - merge_github_pr_for_each_repo + + git: + feature_branch: puppetsync/20261025-release-rpms-gpg-key-race + commit_message: | + [puppetsync] release_rpms: attach the GPG public key from one OS leg + + Every OS leg of the build matrix signs with the same key and produces + the same RPM-GPG-KEY-SIMP-UNSTABLE-2.pub.asc, and every leg clobbered + and re-uploaded it. Run in parallel, those uploads raced, failing a + leg with 'already_exists' or 'Not Found' and cancelling the others, + even though the release usually ended up with all of its assets. + + Only the first OS in build_container_oses attaches the key now. + + github: + pr_user: silug # This should be the account that *submitted* the PRs + approval_message: ':+1: :ghost:' diff --git a/data/sync/repolists/20261025-release-rpms-gpg-key-race.yaml b/data/sync/repolists/20261025-release-rpms-gpg-key-race.yaml new file mode 100644 index 0000000..6135af5 --- /dev/null +++ b/data/sync/repolists/20261025-release-rpms-gpg-key-race.yaml @@ -0,0 +1,40 @@ +--- +# Repolist for the 20261025-release-rpms-gpg-key-race session: every repo +# that carries release_rpms.yml. +# +# The github-org dynamic inventory (see github-org.yaml for the selection +# rule) covers the module repos. Of the rubygems only rubygem-simp-cli +# carries release_rpms.yml, and the packaging repos below aren't matched by +# github-org's include globs at all. +# +# merge_github_workflows CREATES a workflow that a repo lacks, so every repo +# selected here must already have release_rpms.yml. Hence no `rubygem-*` +# glob, and pupmod-simp-ufw (not yet released) is excluded. +puppetsync::repos_source: + org: simp + include: + - 'pupmod-*' + - 'puppet-*' + - rubygem-simp-cli + # Packaging repos that carry release_rpms.yml + - pkg-r10k + - simp-adapter + - simp-doc + - simp-environment-skeleton + - simp-gpgkeys + - simp-rsync-skeleton + - simp-selinux-policy + - simp-utils + exclude: + # Held out of every session; see github-org.yaml + - pupmod-voxpupuli-selinux + - pupmod-simp-haveged + # Its release_rpms.yml and tag_deploy.yml predate the run-once/matrix + # split: tag_deploy dispatches release_rpms once per OS with a + # build_container_os input (for centos7/centos8). Merging only + # release_rpms.yml would leave tag_deploy sending an input that no + # longer exists. It has missed every sync since 2026-09-03, so it needs + # its own catch-up session. + - pupmod-simp-compliance_markup + # No release_rpms.yml yet (initial release still in review) + - pupmod-simp-ufw diff --git a/modules/profile/files/_github/workflows/release_rpms.yml b/modules/profile/files/_github/workflows/release_rpms.yml index 6fc8dda..529f52e 100644 --- a/modules/profile/files/_github/workflows/release_rpms.yml +++ b/modules/profile/files/_github/workflows/release_rpms.yml @@ -3,7 +3,7 @@ # # NOTICE: **This file is maintained with puppetsync** # -# This file is updated automatically as part of a puppet module baseline. +# This file is updated automatically as part of a standardized asset baseline. # # The next baseline sync will overwrite any local changes to this file! # @@ -304,6 +304,11 @@ jobs: env: rpm_file_paths: ${{ steps.build-and-sign-rpm.outputs.rpm_file_paths }} rpm_gpg_file: ${{ steps.build-and-sign-rpm.outputs.rpm_gpg_file }} + # Every OS leg signs with the same key and produces an identically + # named .pub.asc; attach it from one leg only, or the legs' parallel + # clobber+upload of that one asset race each other + # ("already_exists" / "Not Found" from the releases API). + upload_gpg_file: ${{ matrix.os == fromJSON(github.event.inputs.build_container_oses)[0] }} release_id: ${{ needs.resolve-release.outputs.release_id }} clobber: ${{ github.event.inputs.clobber }} clean: ${{ github.event.inputs.clean }} @@ -352,8 +357,9 @@ jobs: const clobber = process.env.clobber == 'yes'; const rpm_files = process.env.rpm_file_paths.split(/[\r\n]+/); const rpm_gpg_file = process.env.rpm_gpg_file; + const upload_files = process.env.upload_gpg_file == 'true' ? rpm_files.concat(rpm_gpg_file) : rpm_files; - let uploaded_files = rpm_files.concat(rpm_gpg_file).map(function(file){ + let uploaded_files = upload_files.map(function(file){ const name = path.basename(file) var content_type = 'application/pgp-keys' if( name.match(/\.rpm$/) ){