Skip to content

ci: run the metadata pipeline on main, and push with a PAT - #489

Open
Loup-Garou911XD wants to merge 2 commits into
bombsquad-community:mainfrom
Loup-Garou911XD:ci/guard-on-committer-identity
Open

ci: run the metadata pipeline on main, and push with a PAT#489
Loup-Garou911XD wants to merge 2 commits into
bombsquad-community:mainfrom
Loup-Garou911XD:ci/guard-on-committer-identity

Conversation

@Loup-Garou911XD

Copy link
Copy Markdown
Member

Two commits. The first makes ci.yml able to do its job at all; the second fixes problems the first one introduces.

fix require pr issue for ci (f4eea3d)

ci.yml never ran auto_apply_plugin_metadata.py. A push that bumps a plugin's plugman version therefore landed the new bytes with no matching manifest entry, leaving the manifest advertising the OLD version's md5sum. The in-game manager verifies MD5 before installing, so every download of that plugin fails, and test_latest_version fails on that run and every later one. That is what 8628c97 (finder 1.0 to 4.1) did to main; it stayed broken until #485 reverted the change, restoring the old bytes rather than recording the new ones.

The commit adds the missing step, plus a Resolve push base step so the diff and PLUGMAN_BASE_REF are computed from github.event.before before any auto-commit rewrites HEAD.

It also switches the pushes from GITHUB_TOKEN to secrets.PAT. ci.yml currently cannot push to main at all:

remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: - Changes must be made through a pull request.

That is a protection-rule rejection rather than a permissions one, so no permissions: value fixes it, and GITHUB_TOKEN cannot be given a ruleset bypass (bypass actors are repository roles, teams, installed Apps or Dependabot). The PAT account sits on the bypass list instead. GITHUB_TOKEN is dropped to contents: read.

key the self-trigger guard on committer identity (f3575ca)

Unlike GITHUB_TOKEN, a PAT's pushes start new workflow runs, so the job must skip its own commits. The first commit did that by matching the [ci] message prefix. That is unsafe: ci-apply.yml commits [ci] apply-version-metadata and [ci] apply-plugin-metadata-and-formatting onto the PR branch, so those routinely sit at a PR branch's tip (7d8b18e, 2b1763a). Rebase merge is enabled here, so rebase-merging an ordinary PR makes one of them main's head commit and skips the entire job, including the authoritative strict test_versions run. That is the worst possible push to skip, because a rebase rewrites the very shas ci-apply.yml stamped into the manifests.

The three auto-commit steps now commit as plugman-ci and the guard keys on that. Nothing else uses that identity, so it skips this workflow's own pushes and nothing more; ci-apply.yml's commits reaching main now get a full run. Squash merge was never affected, since COMMIT_OR_PR_TITLE resolves to the PR title on a multi-commit branch.

Also in ci.yml:

  • Skip the job on forks. They have no PAT and only ever fail at the preflight.
  • Record why the missing-PAT preflight fails the whole job instead of letting the tests run. Without a PAT the metadata steps and the suite both still pass against the runner's tree, so the run goes green over a main whose committed manifests were never stamped. That is the trap ci-apply.yml's MERGE GATE comment describes.
  • Reset the remote URL after the last push so the test suite cannot reach a ruleset-bypassing credential. Partial mitigation only, and the comment says so: autopep8 and GitPython are unpinned and already ran with it live.

release.yml gets a concurrency group for the same root cause. It filters on paths: [index.json], exactly what [ci] apply-version-metadata rewrites, so under a PAT that push now starts a release run of its own. Two runs for one release read the same previous tag and both try to create it. Serialised, the second sees the published tag and no-ops through versioning_tools.py. Never cancel-in-progress: a cancelled run can leave a tag with no release attached.

Before merging

  • secrets.PAT predates this work (created 2022-08-31, never rotated, referenced nowhere else). Confirm it is still valid and that its owner can bypass ruleset 22381346. That ruleset's existing bypass is RepositoryRole:5 (repository admin), so an admin's token needs no new entry; a non-admin's does.
  • Worth replacing it with a fine-grained token scoped to this repo. A 2022-era classic PAT carries repo scope across every repo its owner can reach.

Testing

No test covers workflow files. The plugin-metadata step was validated by replaying five synthetic cases (version bump stamps the manifest and 21 tests pass; no bump fails loudly; non-plugin push no-ops; deletions are filtered out by --diff-filter=d; a new plugin gets an entry) and eight real historical merges, seven of which were clean no-ops. Both files parse as YAML and the step order is unchanged apart from the additions described above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QDSzHqhTmdMMD8f3UF6eNo

Loup-Garou911XD and others added 2 commits September 6, 2026 21:01
Since ci.yml pushes with a PAT, its own commits start new workflow runs,
so the job needs to skip them. It did that by matching the "[ci] " message
prefix, which is unsafe: ci-apply.yml commits "[ci] apply-version-metadata"
and "[ci] apply-plugin-metadata-and-formatting" onto the PR BRANCH, so those
routinely sit at a PR branch's tip (7d8b18e, 2b1763a). Rebase merge is
enabled on this repo, so rebase-merging an ordinary PR makes one of them
main's head commit and skips this entire job, the authoritative test_versions
run included. That is the worst push to skip: a rebase rewrites the very
shas ci-apply.yml stamped into the manifests.

The three auto-commit steps now commit as `plugman-ci` and the guard keys on
that. Nothing else commits under that identity, so it skips this workflow's
own pushes and nothing more; ci-apply.yml's commits (github-actions[bot]) now
get a full run when they reach main.

Also in ci.yml:

- Skip the job on forks. They have no PAT, so they only ever fail at the
  preflight, and their main is not authoritative for anything.
- Record why the missing-PAT preflight fails the whole job rather than
  letting the tests run. Without a PAT the metadata steps and the suite both
  still pass against the runner's tree, so the run would go green over a main
  whose committed manifests were never stamped. No signal beats a false one.
- Reset the remote URL once the pushes are done, so the test suite cannot
  reach a credential that bypasses main's ruleset. Partial only: autopep8 and
  GitPython are unpinned and already ran with it live.

release.yml gets a concurrency group for the same root cause. It filters on
paths: [index.json], which is exactly what "[ci] apply-version-metadata"
rewrites, so under a PAT that push now starts a release run of its own. Two
runs in flight for one release read the same previous tag and both try to
create the new one. Serialised, the second sees the published tag and no-ops
through versioning_tools.py.

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The CI workflow contains a non-existent actions/setup-python@v7 reference and the PAT “drop credentials” step doesn’t actually clear checkout’s auth header, leaving elevated credentials available to later steps.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the GitHub Actions workflows to ensure plugin/version metadata is generated and committed on main, and to allow the workflow to push those updates despite branch rules requiring PR-only changes by using a PAT plus a self-trigger guard.

Changes:

  • Update ci.yml to push metadata/formatting commits using secrets.PAT, add a preflight for missing PAT, and guard against re-entry by keying off a dedicated committer identity.
  • Ensure the CI pipeline runs the plugin metadata application step so manifests stay consistent with plugin bytes.
  • Add concurrency to release.yml to prevent multiple release runs racing when index.json is rewritten by CI.
File summaries
File Description
.github/workflows/ci.yml Switch CI pushes to PAT, add preflight + self-trigger guard, and add credential drop before tests.
.github/workflows/release.yml Serialize release workflow runs to avoid tag/release races caused by CI-triggered index.json updates.
Review details

Suppressed comments (1)

.github/workflows/ci.yml:113

  • actions/setup-python@v7 is not a valid major version for the official action (latest is v5), so this workflow will fail at runtime when trying to resolve the action ref.
          token: ${{ secrets.PAT }}

      - name: Set up Python
        uses: actions/setup-python@v7
        with:
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/ci.yml
Comment on lines +207 to +208
- name: Drop push credentials
run: git remote set-url origin "https://github.com/${GITHUB_REPOSITORY}.git"
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.

2 participants