Skip to content

ci: add PyPI release workflow for v0.1.0 [OMN-7647] - #8

Merged
jonahgabriel merged 3 commits into
mainfrom
jonah/omn-7647-pypi-publish
Apr 7, 2026
Merged

jonahgabriel merged 3 commits into
mainfrom
jonah/omn-7647-pypi-publish

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Apr 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add release.yml workflow: triggers on v* tag push or manual dispatch, builds with uv build, publishes to PyPI via token, creates GitHub Release with checksums
  • Add release-dry-run.yml workflow: manual dispatch to verify build without publishing
  • Matches org-wide release pattern from omnibase_core and omnimemory
  • pyproject.toml already has correct metadata, version 0.1.0, classifiers, and URLs

Pre-release checklist

  • Configure PYPI_TOKEN repository secret on GitHub
  • Release omnibase_core v0.39.0 to PyPI first (omnimarket depends on >=0.39.0, PyPI currently has 0.38.0)
  • Tag and push: git tag v0.1.0 && git push origin v0.1.0

Test plan

  • Run release-dry-run workflow manually to verify build succeeds
  • Verify wheel contains expected package contents
  • After PYPI_TOKEN is set, tag v0.1.0 to trigger real publish

Summary by CodeRabbit

  • Chores
    • Added automated release workflow that validates version tags, builds distribution packages, and publishes to PyPI with checksums
    • Added dry-run release workflow for testing the build and verification process without publishing

Add release.yml (tag-triggered build + publish via uv) and
release-dry-run.yml matching org-wide pattern from omnibase_core
and omnimemory. Requires PYPI_TOKEN secret to be configured.
@linear

linear Bot commented Apr 6, 2026

Copy link
Copy Markdown

OMN-7647

@coderabbitai

coderabbitai Bot commented Apr 6, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@jonahgabriel has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 31 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 31 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 62bb16a5-ea5a-4cf5-b862-be0dd7e4db76

📥 Commits

Reviewing files that changed from the base of the PR and between 88e047e and f541fa4.

📒 Files selected for processing (2)
  • .github/workflows/release-dry-run.yml
  • .github/workflows/release.yml
📝 Walkthrough

Walkthrough

The PR adds two GitHub Actions workflows for managing Python package releases. A dry-run workflow tests building distribution artifacts without publishing, while a production workflow builds, publishes artifacts to PyPI, generates checksums, and creates GitHub releases with automated release notes.

Changes

Cohort / File(s) Summary
Release Dry-Run Workflow
.github/workflows/release-dry-run.yml
New manual-trigger workflow that checks out the repository with full history, builds distribution artifacts using Python 3.12 and uv build, then verifies and lists generated wheel and tarball files with SHA-256 checksums.
Production Release Workflow
.github/workflows/release.yml
New workflow triggered by version tags (vMAJOR.MINOR.PATCH) or manual dispatch that validates tag matches pyproject.toml version, builds and publishes artifacts to PyPI, generates checksum file, creates GitHub Release with artifacts, and marks as prerelease when tag contains rc.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 With uv and tags so fine,
Workflows build and publish mine,
Dry runs test before the flight,
Then to PyPI—shining bright!
Checksums tallied, releases bloom,
Artifacts dance—no more room! 📦

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-7647-pypi-publish

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release-dry-run.yml:
- Around line 8-11: The workflow marks the inputs.tag as required but never uses
it; either make it optional or actually consume it. Update the checkout step to
use inputs.tag as the ref (e.g., ref: ${{ inputs.tag }}) and add an early
validation step (run: ...) that reads pyproject.toml, extracts the version, and
compares it to inputs.tag (fail the job if they differ) so the dry-run truly
validates the specified tag before the build step.

In @.github/workflows/release.yml:
- Around line 85-92: The release step "Set release tag" (id: tag) currently
writes the resolved tag to the output variable "tag" but downstream logic
derives "prerelease" from github.ref_name; change that to derive prerelease from
the resolved output "tag" instead. Modify the "Set release tag" step to also
compute and export a "prerelease" output by inspecting the resolved tag value
(the same value echoed to $GITHUB_OUTPUT as "tag") and checking for the
prerelease identifier (e.g., contains "rc" or other prerelease suffix), so that
when github.event_name is "workflow_dispatch" the user-provided inputs.tag is
used to determine prerelease status rather than github.ref_name.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Lite

Run ID: d7052f8c-aec1-4172-886d-869b13d5a924

📥 Commits

Reviewing files that changed from the base of the PR and between 5f88d0d and 88e047e.

📒 Files selected for processing (2)
  • .github/workflows/release-dry-run.yml
  • .github/workflows/release.yml

Comment thread .github/workflows/release-dry-run.yml
Comment thread .github/workflows/release.yml
- release-dry-run.yml: add tag validation step so the required tag
  input is actually consumed and verified against pyproject.toml
- release.yml: derive prerelease from steps.tag.outputs.tag instead
  of github.ref_name so manual dispatch with rc tags works correctly
@jonahgabriel
jonahgabriel enabled auto-merge April 6, 2026 23:13
@jonahgabriel
jonahgabriel added this pull request to the merge queue Apr 7, 2026
Merged via the queue into main with commit 9340fd7 Apr 7, 2026
13 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-7647-pypi-publish branch April 7, 2026 16:29
jonahgabriel added a commit that referenced this pull request Apr 21, 2026
… Pick #8]

- Wraps /onex:agent_healthcheck skill as proper ONEX node
- Polls TaskList, detects stalls, redispatches v2 agents
- Writes friction events on escalation to Blocked
- Entry point: omnimarket.nodes.node_worker_stall_recovery
- Unit tests + documentation included
jonahgabriel added a commit that referenced this pull request Apr 22, 2026
… Pick #8]

- Wraps /onex:agent_healthcheck skill as proper ONEX node
- Polls TaskList, detects stalls, redispatches v2 agents
- Writes friction events on escalation to Blocked
- Entry point: omnimarket.nodes.node_worker_stall_recovery
- Unit tests + documentation included
jonahgabriel added a commit that referenced this pull request Apr 22, 2026
… Pick #8]

- Wraps /onex:agent_healthcheck skill as proper ONEX node
- Polls TaskList, detects stalls, redispatches v2 agents
- Writes friction events on escalation to Blocked
- Entry point: omnimarket.nodes.node_worker_stall_recovery
- Unit tests + documentation included
github-actions Bot pushed a commit to andywu42/omnimarket that referenced this pull request Apr 23, 2026
…OMN-9404 Pick OmniNode-ai#4] (OmniNode-ai#371)

* feat(node_kafka_topic_emit_probe): hourly Kafka topic health probes [OMN-9404 Pick OmniNode-ai#4]

- Emits synthetic events for declared Kafka topics to verify producers/consumers
- Catches silent EMIT_FAILED failures proactively (1hr vs 6 days reactive)
- Entry point: omnimarket.nodes.node_kafka_topic_emit_probe
- Uses omnibase_core event bus protocols
- Unit tests + documentation included

* feat(node_merge_effect): simple git merge resolver for DIRTY PRs [OMN-9404 Pick OmniNode-ai#5]

- Attempts git merge origin/main for conflict-free PRs
- Escalates to LLM when merge is ambiguous
- Mechanical automation based on OmniNode-ai#1354/OmniNode-ai#1356 pattern
- Entry point: omnimarket.nodes.node_merge_effect
- Unit tests + documentation included

* feat(node_worker_stall_recovery): agent stall auto-recovery [OMN-9404 Pick OmniNode-ai#8]

- Wraps /onex:agent_healthcheck skill as proper ONEX node
- Polls TaskList, detects stalls, redispatches v2 agents
- Writes friction events on escalation to Blocked
- Entry point: omnimarket.nodes.node_worker_stall_recovery
- Unit tests + documentation included

* fix(node_kafka_topic_emit_probe): add missing Python models, fix mypy errors + CodeRabbit issues

- Create ModelKafkaProbeRequest, ModelMergeCommand, ModelStallRecoveryCommand as Pydantic models
  (were YAML-only; handlers imported Python modules that didn't exist)
- Remove non-existent omnimarket.adapters.event_bus imports from handler_kafka_probe
- Remove ProtocolStateStore() instantiation (Protocol class, cannot be instantiated)
- Fix publish() call signature: protocol takes ProtocolEventMessage, not (topic, dict)
- Remove per-topic asyncio.sleep(interval) that caused 3600s stall in tests and exceeded
  120s node timeout; probe_interval_seconds is a scheduling hint, not an intra-loop delay
- Fix hardcoded /Users/jonah path in handler_stall_recovery (rule 6)
- Fix test mock in test_handle_healthy_agent to use side_effect so git --version succeeds
  while grep returns non-zero (simulating no dispatch log match)
- Fix docs: correct test path in kafka-probe tracking doc, add blank lines around MD table
- Replace asyncio.get_event_loop().time() with time.time() for wall-clock timestamps

* ci: retrigger PR checks after rebase

* style: normalize docstring whitespace in handler_kafka_probe

* chore: trigger CI re-run [no-op]

* fix(cr-threads): address 18 CodeRabbit issues — stall recovery correctness + probe metadata

- Fix side_effect_class: read_only → write (node emits Kafka events)
- Fix _check_stall: grep -l multi-file handling, timezone-aware comparison,
  context_threshold_pct now wired to stall trigger logic
- Fix lookup failures returned as healthy → now return status: unknown
- Fix dry_run stored on self → request-scoped local variable
- Fix checkpoint path .yaml extension → .json (matches JSON payload)
- Fix _redispatch_agent: attempt-indexed suffix prevents -v2 collision
- Fix hardcoded /Users/jonah paths → _resolve_onex_state() via OMNI_HOME env
- Add field bounds to model_stall_recovery_command (ge/le constraints)
- Fix docs: idempotency claim (not idempotent) + MD058 blank lines around tables
- Fix test: remove no-op `or True` assertion; add real healthy/unknown tests

* fix(cr-threads): resolve all 9 unresolved CodeRabbit threads + Runtime Sweep

Critical:
- handler_kafka_probe: replace stubbed _emit_probe/_verify_consumer with real
  aiokafka producer/admin-client implementation; apply probe_interval_seconds as
  inter-topic delay
- handler_merge: make dry_run request-scoped (was shared mutable instance state,
  race-prone); add TimeoutExpired handling and timeout= to all subprocess.run calls;
  abort merge state after dry-run and before no-conflict early-return

Major:
- handler_stall_recovery: verify grep (not git) in initialize() via shutil.which;
  defer mkdir out of _get_checkpoint_path into _save_checkpoint writer path;
  map 'unknown' status -> 'healthy' to stay within declared contract outputs
- test_node_merge_effect: mock subprocess.run in test_handle_nonexistent_repo
- test_node_worker_stall_recovery: update test to expect 'healthy' for lookup
  failures (contract-aligned)

Runtime Sweep:
- pyproject.toml: remove stale node_merge_sweep entry point (module was renamed
  to node_merge_sweep_compute in OmniNode-ai#373; leftover caused 1/129 broken entry points)

* fix(ci): resolve 3 CI failures — stub __init__, aiokafka typing, kafka probe test mock

- Remove empty __init__ from HandlerMergeEffect (lint stub-only check)
- Add aiokafka to mypy overrides to silence import-untyped errors
- Mock _emit_probe in unit tests so they don't require a live Kafka broker

* fix(typecheck): remove stale type: ignore[import-untyped] for aiokafka — now covered by mypy override

* fix(cr-threads): load default topics from contract.yaml, clarify probe_interval semantics

Resolves 2 unresolved CodeRabbit threads on handler_kafka_probe.py:
- Major: hardcoded topics in _all_declared_topics() — replaced with _load_default_topics()
  that reads default_topics from contract.yaml inputs section
- Minor: probe_interval_seconds timeout concern — clarified in docstring and contract
  description that this is scheduling metadata, not execution time

* style: ruff format handler_kafka_probe.py
andywu42 pushed a commit to andywu42/omnimarket that referenced this pull request Jul 6, 2026
…infra venv (OmniNode-ai#1625)

_resolve_skill_roots derived the default skill roots from _REPO_ROOT
(Path(__file__).parents[5]). Installed into the canonical infra venv,
_REPO_ROOT is the site-packages install dir, so the default pointed at
<venv>/.../plugins/onex/skills — which never exists — and the audit
hard-failed with SkillFunctionalAuditNoSkillsDiscoveredError. The 108
real skills live in the sibling omniclaude/plugins/onex/skills clone.

Mirror _resolve_nodes_roots: resolve the skill libraries via the
$OMNI_HOME sibling-repo layout, so resolution works even when _REPO_ROOT
is a site-packages dir. Keep canonical-clone-relative fallbacks.

Fail-fast preserved (CLAUDE.md rule OmniNode-ai#8): no silent wrong default. When
$OMNI_HOME is unset AND no repo-relative path resolves, only nonexistent
candidates remain, so _audit_skills raises the zero-skills hard fail
rather than reporting a vacuous pass. _resolve_omni_home returns None
(not a guessed path) when neither the env var nor a validated
canonical-clone anchor is available.

Tests: site-packages _REPO_ROOT + $OMNI_HOME resolves integration_sweep
and dod_sweep; unset $OMNI_HOME + no path still raises; canonical-clone
fallback resolves without the env var.

Closes OMN-13993
andywu42 pushed a commit to andywu42/omnimarket that referenced this pull request Jul 6, 2026
…ion_sweep/dod_sweep (OmniNode-ai#1624)

Both sweep orchestrators resolve their contracts/artifact root from
ONEX_CC_REPO_PATH via _resolve_root. A stale/container value (the
in-container mount /onex_change_control) leaks into local infra-venv
runs where it has no contracts/ dir, so _resolve_root raised and the
sweep never ran.

Fall back to the canonical registry clone at $OMNI_HOME/onex_change_control
when the env path lacks contracts/, before raising. Fail-fast
(CLAUDE.md rule OmniNode-ai#8) is preserved: os.environ["OMNI_HOME"] raises
KeyError when unset (never a silent default), and a fallback that
itself lacks contracts/ still raises RuntimeError. The 'ONEX_CC_REPO_PATH
not set at all' branch is unchanged.

Parametrized tests cover both handlers: OMNI_HOME registry fallback
(behavioral) + unset-OMNI_HOME fail-fast.
jonahgabriel added a commit that referenced this pull request Jul 18, 2026
…1805)

* feat(OMN-14462): add scripts/merge-proof local-proof env wrapper (F-20)

Local proof gates (topic-naming lint) resolve their validator from a sibling
omnibase_infra checkout. Under the mandated worktree layout the naive
../omnibase_infra sibling path does not exist, so a correct change fails
locally until the hidden environment is reconstructed by hand — the natural
workaround pressure being --no-verify, which rule #10 bans.

scripts/merge-proof resolves OMNI_HOME + OMNIBASE_INFRA_PATH deterministically
from its own on-disk location (rule #8) and, when it cannot, prints the exact
export lines to run rather than proceeding on a silent wrong path. Modes:
--check, --print-env, -- CMD, default (run topic-lint proof).

Test: tests/scripts/test_merge_proof.py drives the real script via subprocess
in an isolated tmp location (git env stripped per OMN-14746/14744).

* test(OMN-14462): avoid literal path prefixes in merge-proof test

* fix(OMN-14462): harden merge-proof exported environment

* test(OMN-14462): make merge-proof topology hermetic

---------

Co-authored-by: test <test@example.com>
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