From fb71332c0f6d035cfb393cfe509dc5f16dde2438 Mon Sep 17 00:00:00 2001 From: Antony Garand <9059487+AntonyGarand@users.noreply.github.com> Date: Mon, 19 Oct 2026 10:06:21 -0400 Subject: [PATCH] ci: validate the snapshot via a scratch ref before pushing hub/publish The official packager clones the plugin repository from GitHub and checks out the pinned SHA, but the workflow validated the new snapshot commit before pushing it, so the packager always failed with "upload-pack: not our ref". The pipeline had never exercised this path: earlier snapshots were pushed by local script runs, and the automatic runs all found nothing to publish. Push the snapshot to the temporary hub/validate ref first so the packager fetches the exact commit from GitHub exactly as the real Hub build will, and only fast-forward hub/publish after validation passes. The scratch ref is deleted afterwards (also on failure), and the job summary no longer prints pin instructions when validation failed - previously it recommended pinning a commit that was never pushed. --- .github/workflows/publish-hub.yml | 26 ++++++++++++++++++++++++-- README.md | 18 +++++++++++------- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/.github/workflows/publish-hub.yml b/.github/workflows/publish-hub.yml index cae48f46..40516b05 100644 --- a/.github/workflows/publish-hub.yml +++ b/.github/workflows/publish-hub.yml @@ -17,8 +17,9 @@ permissions: concurrency: group: publish-hub # A newer master push supersedes queued runs: intermediate snapshots are - # pointless because reviewers only ever diff pin against pin, and a cancelled - # run never leaves partial state on the remote (push is the last step). + # pointless because reviewers only ever diff pin against pin. A cancelled + # run can leave only the scratch hub/validate ref behind, which the next + # run overwrites; hub/publish itself is only pushed after validation. cancel-in-progress: true jobs: @@ -68,7 +69,17 @@ jobs: COMMIT: ${{ steps.snapshot.outputs.commit }} run: git checkout --detach "${COMMIT}" + # The official packager clones the plugin repository from GitHub and + # checks out the pinned SHA, so the snapshot must be reachable from a + # ref there before it can be validated. hub/validate is a scratch ref + # for exactly that; it is deleted once validation finishes and is never + # pinned. hub/publish itself is only pushed after validation passes. + - name: Expose the snapshot commit to the packager + if: ${{ steps.snapshot.outputs.changed == 'true' }} + run: git push origin refs/heads/hub/publish:refs/heads/hub/validate + - name: Validate with the official Plugin Hub packager + id: validate if: ${{ steps.snapshot.outputs.changed == 'true' }} env: PLUGIN_REPOSITORY: ${{ github.repository }} @@ -76,6 +87,10 @@ jobs: shell: bash run: bash "${RUNNER_TEMP}/hub-check/check-plugin-hub.sh" + - name: Drop the validation ref + if: ${{ always() && steps.snapshot.outputs.changed == 'true' }} + run: git push origin --delete refs/heads/hub/validate || true + - name: Upload Plugin Hub feedback and package if: ${{ always() && steps.snapshot.outputs.changed == 'true' }} uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -95,6 +110,7 @@ jobs: COMMIT: ${{ steps.snapshot.outputs.commit }} PREVIOUS: ${{ steps.snapshot.outputs.previous }} CHANGED: ${{ steps.snapshot.outputs.changed }} + VALIDATED: ${{ steps.validate.outcome }} BASE: ${{ inputs.base || github.sha }} REPOSITORY: ${{ github.repository }} shell: bash @@ -106,6 +122,12 @@ jobs: echo "Nothing to publish: \`hub/publish\` already matches \`${BASE:-master}\` at \`${COMMIT}\`." exit 0 fi + if [[ "${VALIDATED}" != success ]]; then + echo "Validation failed for \`${COMMIT}\`; \`hub/publish\` was not updated." + echo "Do not pin \`${COMMIT}\` — it was not pushed. Check the job log and the" + echo "plugin-hub-check artifact, fix the cause, and push to \`master\` again." + exit 0 + fi echo "- Commit to pin: \`${COMMIT}\`" if [[ -n "${PREVIOUS}" ]]; then echo "- Review diff: [${PREVIOUS:0:10}...${COMMIT:0:10}](https://github.com/${REPOSITORY}/compare/${PREVIOUS}...${COMMIT})" diff --git a/README.md b/README.md index 45c29cc2..b2f1f833 100644 --- a/README.md +++ b/README.md @@ -194,13 +194,17 @@ To cut a new pin: 1. Merge your changes to `master` and set `version=` in `runelite-plugin.properties`. 2. The **Publish Plugin Hub branch** workflow runs automatically on every push - to `master`. It appends one snapshot commit to `hub/publish`, validates that - commit with RuneLite's official packager, pushes it, and reports the commit - SHA to pin in its summary. Pushes that do not change plugin files (tests, - docs, CI) are detected and skipped. You can also run the workflow manually - for another ref, or locally: `bash .github/scripts/publish-hub.sh --push`. - On first use the branch is seeded from the currently pinned commit, so the - transition review only shows the removal of non-plugin files. + to `master`. It appends one snapshot commit, exposes it on the temporary + `hub/validate` ref so RuneLite's official packager can clone and check out + that exact commit from GitHub, validates it, and only then pushes + `hub/publish` (deleting the temporary ref) and reports the commit SHA to + pin in its summary. If validation fails, `hub/publish` is left untouched + and the summary says so — never pin an unreported commit. Pushes that do + not change plugin files (tests, docs, CI) are detected and skipped. You can + also run the workflow manually for another ref, or locally: + `bash .github/scripts/publish-hub.sh --push`. On first use the branch is + seeded from the currently pinned commit, so the transition review only + shows the removal of non-plugin files. 3. Open a pull request against [runelite/plugin-hub](https://github.com/runelite/plugin-hub) updating [`plugin-hub/plugins/flipping-utilities`](https://github.com/runelite/plugin-hub/blob/master/plugins/flipping-utilities) with that commit.