Skip to content

feat(OMN-20710): post-merge bot bumps the onex plugin version; PRs stop racing - #2609

Merged
jonahgabriel merged 3 commits into
devfrom
jonah/omn-20710-plugin-version-bump-bot
Oct 8, 2026
Merged

jonahgabriel merged 3 commits into
devfrom
jonah/omn-20710-plugin-version-bump-bot

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

OMN-20710: post-merge bot bumps the onex plugin version; PRs stop racing

Base: dev

Summary

Every open plugin PR had to claim the same next onex version, so each merge turned the others red on the Plugin Version Bump Gate (2026-10-07: #2591, #2596 and #2598 together). Lane cause-claude-bump-2245 measured 47 of dev's 161 merges since 2026-09-30 setting the plugin version. Operator RULING 2026-10-08T03:53:09Z lane=orchestrator-716d adopts omniclaude-internal's OMN-20497 approach: one bot bump PR after each dev merge; the per-PR check refuses only a lowered or broken version.

This PR replaces the per-PR requirement to bump the plugin version with a post-merge bot bump. It updates the validator to allow unchanged versions, adds a --bump-to-base mode, introduces a new workflow for automated bumps, and updates documentation and hooks.

What changed

  • Per-PR check: scripts/validation/validate_plugin_version_bump.py (OMN-16913) now passes if the version is unchanged. A changed version must be dotted integers (BROKEN_VERSION) and above the merge-base value (LOWERED_VERSION). plugin.json and the onex entry in plugins/onex-dev-marketplace/.claude-plugin/marketplace.json must agree (MARKETPLACE_SKEW). NO_BUMP is removed. The check and job name "Plugin Version Bump Gate" are unchanged.
  • Validator mode: --bump-to-base added to the same validator. When shipped files changed since --base, it raises both files to the next patch above the base, editing only the version value bytes. A second run changes nothing.
  • Workflow: New .github/workflows/plugin-version-bump.yml triggers on push to dev, a */30 schedule backstop, and workflow_dispatch. It runs --bump-to-base against the last dev commit that set the version. It keeps one bot PR open on automation/omn-20710-plugin-version-bump with title "chore(OMN-20710): post-merge plugin version bump", using ONEXBOT_OCC_APP_ID. It pushes only when version files would change or the branch conflicts with dev. It closes the PR when dev already carries a version for every merged plugin change. There is no batching hold (omniclaude-internal has one), because the ruling is one bump PR after each dev merge; dev does not require branches up to date, so the branch is not rebuilt on every merge.
  • Hooks and Docs: Pre-commit hook plugin-version-bump-gate renamed to "Plugin version not lowered or broken (OMN-20710)". Gate workflow comments updated. One CLAUDE.md bullet under Git/CI Standards: PRs do not bump the onex version.

Proof against the acceptance criteria

Tests

  • tests/ci/test_plugin_version_bump_gate.py: 36 passed (was 11), including the workflow's bump step shell run from the YAML and a workflow shape test.
  • ruff, ruff format, mypy clean on both files.
  • pre-commit passed on commit f9330d1.

Not in this PR

  • The landing controller and its workers in omniclaude-internal still treat only omniclaude-internal as version-keyed (VERSION_KEYED_REPOS, PLUGIN_VERSION_REPO), so they may still hand-bump omniclaude PRs (now allowed but unnecessary) and will not auto-resolve a version-line conflict on an old PR that bumped by hand. A companion change belongs in omniclaude-internal.

Evidence-Ticket: OMN-20710
Evidence-Source: OCC#13246

…op racing

Adopts the OMN-20497 approach per operator ruling 2026-10-08T03:53:09Z.
A single bot bump PR now opens after each dev merge, replacing the
per-PR bump requirement: every open plugin PR claimed the same next
version, and 47 of dev's 161 merges since 2026-09-30 set it.

The per-PR check in scripts/validation/validate_plugin_version_bump.py
now passes if the version is unchanged. If changed, it must be dotted
integers (BROKEN_VERSION) and above the merge base (LOWERED_VERSION).
plugin.json and the marketplace.json entry must agree (MARKETPLACE_SKEW).

Added --bump-to-base flag to the existing validator. It raises both
version files to the next patch above the base when shipped files
changed, editing only version bytes. A second run changes nothing.

New .github/workflows/plugin-version-bump.yml triggers on dev push,
30-minute schedule, and manual dispatch. It maintains one bot PR on
automation/omn-20710-plugin-version-bump, pushing only when version
files change or conflicts exist, and closes the PR when dev is current.

Updated CLAUDE.md, pre-commit hook, and workflow comments. Rewrote
tests/ci/test_plugin_version_bump_gate.py with 36 tests covering the
bump step.
onexbot-occ-writer Bot pushed a commit to OmniNode-ai/onex_change_control that referenced this pull request Oct 8, 2026
…0184): author OCC companion for OmniNode-ai/omniclaude#2609

OCC companion by node_pr_lifecycle_fix_effect (OMN-13317 F1 / OMN-13990 / OMN-14285). Product PR head f9330d14be45a4761a77a94ef3de878dbf018d03.
@jonahgabriel

Copy link
Copy Markdown
Contributor Author

Lab: host=h202 lane=plugin-race-0355 head=f9330d14be45a4761a77a94ef3de878dbf018d03; uv run pytest tests/ci/test_plugin_version_bump_gate.py -q -> 36 passed.
ac1_sim.py (runs the workflow's bump and publish shell from the committed plugin-version-bump.yml against a local bare origin and a gh stub over 7 dev events) -> one bump PR open whenever dev had an unbumped plugin change, none after the bump merged, never two.
ac2_compare.sh (old vs new validator) -> unbumped plugin PRs: old exit 1 NO_BUMP, new exit 0; lowered 2.4.51 new exit 1 LOWERED_VERSION; 2.4.x new exit 1 BROKEN_VERSION; files disagree new exit 1 MARKETPLACE_SKEW.
validate_plugin_version_bump.py --bump-to-base on a clone at 3b16286 plus one plugin change -> plugin.json and the dev marketplace entry 2.4.52 -> 2.4.53, only those two lines; second run prints nothing.

@jonahgabriel
jonahgabriel enabled auto-merge (squash) October 8, 2026 04:37
@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

✅ Hostile Reviewer — PASSED

Blocking findings (critical/error): 0
Total findings: 12
Models succeeded: qwen3-review,gpt-oss-review

Findings

Severity Location Finding
error .github/workflows/plugin-version-bump.yml:1 ai-reviewer:qwen3-review:security Workflow grants write access to .github/workflows, enabling supply chain compromise | The new plugin-version-bump.yml workflow requests permission-workflows: write for the GitHub App token. This allows the bot to modify workflow files on the bump branch. Because the workflow performs a force-push to automation/omn-20710-plugin-version-bump and opens a PR against dev, a compromised runner or malicious dependency could modify the workflow definition itself, potentially exfiltrating secrets or executing
warning .github/workflows/plugin-version-bump.yml:1 ai-reviewer:qwen3-review:correctness Race condition between dev tip check and force-push | The workflow checks if dev moved during the run by comparing git rev-parse HEAD (the checked-out dev tip) with git ls-remote origin refs/heads/dev. If dev moves between this check and the git push --force, the force-push will overwrite the bump branch with a commit based on an older dev state. The subsequent PR will be based on stale code, and the next push event will trigger another run, but the intermediate state may have been lost or the PR ma
warning scripts/validation/validate_plugin_version_bump.py:1 ai-reviewer:qwen3-review:correctness bump_to_base does not handle untracked files in the diff | The bump_to_base function includes untracked files in the changed list via git ls-files --others --exclude-standard, but the check function does not. This inconsistency means that a PR with untracked shipped files will pass the gate but the post-merge bump will include them, potentially causing a version bump for files that were not part of the PR. This could lead to unnecessary version bumps or confusion about which changes triggered the bu
info scripts/validation/validate_plugin_version_bump.py:1 ai-reviewer:qwen3-review:performance Inefficient version comparison in _set_version | The _set_version function iterates over all matches of VERSION_VALUE_RE in the text and attempts to parse the entire JSON for each match to verify that only the intended version was changed. For large JSON files with many version fields, this could be slow. The regex VERSION_VALUE_RE is not specific enough to target only the intended version field, leading to unnecessary JSON parsing. | Evidence: for match in VERSION_VALUE_RE.finditer(text): can
info tests/ci/test_plugin_version_bump_gate.py:1 ai-reviewer:qwen3-review:testing Missing test for concurrent bump runs | The tests do not cover the scenario where two bump runs are triggered concurrently (e.g., two dev merges in quick succession). The race condition identified in the workflow is not tested, and the current implementation may not handle this correctly. A test should simulate two concurrent runs and verify that the final state is consistent. | Evidence: No test in tests/ci/test_plugin_version_bump_gate.py covers concurrent bump runs. | Fix: Add a test that simulates two c
info scripts/validation/validate_plugin_version_bump.py:1 ai-reviewer:qwen3-review:completeness No handling for partial failures in bump_to_base | If bump_to_base fails after writing some files but before writing others, the repository will be in an inconsistent state. The function should be atomic: either all files are updated or none are. Currently, if an exception occurs after writing one file, the other files will not be updated, leading to a partial bump. | Evidence: for path, text in edits.items(): try: path.write_bytes(text.encode("utf-8")) except OSError as exc:
warning .github/workflows/plugin-version-bump.yml:1 ai-reviewer:gpt-oss-review:architecture Concurrent runs may conflict on bump branch | The workflow defines a concurrency group with cancel-in-progress set to false, allowing multiple overlapping executions. Each run may push to the same automation branch with a forced push, leading to race conditions and possible loss of work. | Evidence: concurrency: group: plugin-version-bump cancel-in-progress: false | Fix: Set cancel-in-progress to true or implement a lock file/branch protection that serializes access to the bump branch before pushing.
info .github/workflows/plugin-version-bump.yml:1 ai-reviewer:gpt-oss-review:performance Cron schedule runs every 30 seconds | The workflow is scheduled with a cron expression '*/30 * * * ', causing it to trigger twice per minute. This can generate unnecessary load and may exceed GitHub Actions rate limits. | Evidence: schedule: - cron: '/30 * * * *' | Fix: Adjust the schedule to a more reasonable interval, such as every 5 or 15 minutes, based on the required backstop frequency.
warning .github/workflows/plugin-version-bump.yml:1 ai-reviewer:gpt-oss-review:security Force‑push without branch‑protection checks | The job pushes to the automation branch using 'git push --force' without verifying that branch protection rules (e.g., required reviews or status checks) are satisfied. An attacker who can trigger the workflow could overwrite protected branches. | Evidence: git push --force origin "HEAD:refs/heads/${BUMP_BRANCH}" | Fix: Remove the '--force' flag and rely on normal fast‑forward pushes, or enforce branch protection that still allows the bot to push via a dedicated
warning scripts/validation/validate_plugin_version_bump.py:1 ai-reviewer:gpt-oss-review:correctness bump_to_base ignores staged (cached) changes | The bump_to_base function gathers changed files with 'git diff --name-only' (working tree) and untracked files, but omits staged changes (git diff --cached). Consequently, a PR that stages modifications without committing may not trigger the required version bump, violating the gate's intent. | Evidence: changed = _git(repo, "diff", "--name-only", merge_base).splitlines() + changed += _git(repo, "ls-files", "--others", "--exclude-standard").splitlines()
info scripts/validation/validate_plugin_version_bump.py:1 ai-reviewer:gpt-oss-review:correctness Unescaped version strings may cause false GateError | The _set_version helper uses a regex that matches only double‑quoted "version" keys. JSON strings containing escaped characters (e.g., Unicode escapes) will not match, leading to a GateError even though the version is syntactically valid. | Evidence: VERSION_VALUE_RE = re.compile(r'"version"\s*:\s*"([^"\\]*)"') | Fix: Broaden the regex to allow escaped characters or parse the JSON and replace the version programmatically while preserving formatting via a
info .github/workflows/plugin-version-bump.yml:1 ai-reviewer:gpt-oss-review:correctness Missing error handling for git ls-remote failure | The workflow obtains the remote dev tip with 'git ls-remote origin refs/heads/dev' and assumes a non‑empty result. Network failures or permission issues could yield an empty string, causing the subsequent comparison to treat the remote as unchanged and silently skip the bump. | Evidence: live="$(git ls-remote origin refs/heads/dev | cut -f1)" | Fix: Check that the command succeeded and that $live is non‑empty; abort with a clear error if the remote tip cann

Gate semantics (pilot phase)

Verdict Meaning Blocks merge?
passed No critical/error findings No
blocked CRITICAL or ERROR findings found Yes
degraded Reviewer ran but every model failed mid-run No (pilot)
infra_error cli_review failed to run at all (install/crash) after 2 attempts Yes
unavailable_fork_isolation Fork PR — the LAN-only model is unreachable and the fleet is off limits Yes

Powered by omniintelligence.review_pairing.cli_review — node-based adversarial review via HandlerLlmCliSubprocess (OMN-8524)

jonahgabriel and others added 2 commits October 8, 2026 03:22
Fixed test failure in tests/workflows/test_automated_pusher_identity_omn18273.py::test_every_git_push_workflow_is_classified by adding plugin-version-bump to BRANCH_PUSHERS.
The job mints the App token fail-closed, sets the bot identity, and stamps Onex trailers; 10 tests in that file pass.
@jonahgabriel
jonahgabriel merged commit 4ca1647 into dev Oct 8, 2026
315 of 321 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-20710-plugin-version-bump-bot branch October 8, 2026 20:21
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.

1 participant