Skip to content

Add production treasury executor service#650

Merged
ramimbo merged 2 commits into
mainfrom
maintainer/treasury-executor-service
May 30, 2026
Merged

Add production treasury executor service#650
ramimbo merged 2 commits into
mainfrom
maintainer/treasury-executor-service

Conversation

@ramimbo
Copy link
Copy Markdown
Owner

@ramimbo ramimbo commented May 30, 2026

Summary

  • add a shared treasury executor path that executes due pending proposals and reuses the existing create-bounty GitHub finalization behavior from Automate post-execution bounty issue updates #630
  • add scripts/treasury_executor.py and a treasury-executor Docker Compose service that uses the production .env and shared data volume
  • keep the executor opt-in with MERGEWORK_TREASURY_EXECUTOR_ENABLED=1, plus interval and batch-limit settings
  • document production enablement, logs, and verification/fallback steps in the admin runbook

Maintainer Note

Maintainer infrastructure PR; not requesting a bounty.

This does not change the 24-hour proposal delay, challenge behavior, reserve cap checks, or the rule that GitHub issues must not get mrwk:bounty/Reserved on MergeWork before successful proposal execution. It only adds a production-side loop that can execute proposals after they become eligible, using the same execution path as the manual admin route.

After merge and deploy, production still needs the real production .env updated with MERGEWORK_TREASURY_EXECUTOR_ENABLED=1, then the treasury-executor service started. First due create-bounty proposal should be treated as a canary: inspect result.github_issue_finalization, then confirm both mrwk:bounty and Reserved on MergeWork are present before relying on the service unattended.

Validation

  • ./.venv/bin/python -m pytest -> 535 passed
  • ./.venv/bin/python -m ruff format --check .
  • ./.venv/bin/python -m ruff check .
  • ./.venv/bin/python -m mypy app
  • ./.venv/bin/python scripts/docs_smoke.py
  • cp .env.example .env; docker compose config --quiet; rm -f .env

Summary by CodeRabbit

  • New Features

    • Added a configurable Treasury Executor service and CLI mode to automatically run and finalize eligible treasury proposals with adjustable enable, interval, and batch-size settings.
  • Chores

    • Added a dedicated executor service to container compose and environment examples for enabling it.
  • Documentation

    • Updated production runbook with deployment, configuration, and verification guidance for the executor.
  • Tests

    • Added and extended tests covering executor behavior, configuration parsing, and integration flows.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 98f4f0b8-c86e-49da-a8f0-b8c75a0a832e

📥 Commits

Reviewing files that changed from the base of the PR and between 394ea36 and ab777af.

📒 Files selected for processing (3)
  • scripts/treasury_executor.py
  • tests/test_treasury_executor.py
  • tests/test_treasury_executor_script.py

📝 Walkthrough

Walkthrough

This PR adds a periodic treasury executor service that automatically discovers and executes due treasury proposals. Execution orchestration is extracted into app/treasury_executor.py, the HTTP route handler delegates to it, and a new scripts/treasury_executor.py script polls periodically via Docker Compose. Environment variables control enablement, polling interval, and batch size.

Changes

Treasury Executor Service

Layer / File(s) Summary
Executor core functions and finalization
app/treasury_executor.py
Implements due_treasury_proposal_ids to query pending proposals, execute_treasury_proposal_with_finalization to execute with optional bounty GitHub issue finalization, and execute_due_treasury_proposals to iterate due proposals while capturing actions, handling LedgerError separately, and returning aggregated execution statistics. Defines Finalizer callback type.
Treasury route delegation to executor
app/treasury_routes.py
Updates /api/v1/treasury/proposals/{proposal_id}/execute endpoint to call execute_treasury_proposal_with_finalization instead of performing execution and in-route bounty finalization inline.
Periodic executor script and config
scripts/treasury_executor.py
Adds ExecutorConfig dataclass and executor_config_from_env for environment variable parsing with validation (enabled flag, interval seconds ≥ 1, batch limit ≥ 1). Implements run_once orchestration and main entry point with --once flag, periodic polling loop, JSON logging, and broad exception handling.
Deployment service and environment configuration
.env.example, docker-compose.yml
Adds three .env.example variables: MERGEWORK_TREASURY_EXECUTOR_ENABLED (default 0), MERGEWORK_TREASURY_EXECUTOR_INTERVAL_SECONDS (default 300), MERGEWORK_TREASURY_EXECUTOR_BATCH_LIMIT (default 25). Adds treasury-executor Docker Compose service depending on app, loading .env, mounting shared data volume, and running python -m scripts.treasury_executor.
Operational documentation and validation
docs/admin-runbook.md, scripts/docs_smoke.py
Adds "Production Treasury Executor" section documenting enablement via .env, deployment/restart, batching/failure behavior, challenge blocking, and GitHub issue finalization verification. Updates "Post a Bounty" and manual payout steps. Updates doc-smoke test to require executor documentation strings.
Executor behavior end-to-end tests
tests/test_treasury_executor.py
Tests execution of due create_bounty proposals with injected finalizer callback, due pay_bounty proposals with balance updates, and continuation after tampered/failed proposals. Includes database initialization and proposal-due-marking helpers.
Executor script configuration tests
tests/test_treasury_executor_script.py
Tests executor_config_from_env defaults (disabled, 300s, 25 batch), explicit environment overrides, and ValueError for invalid zero numeric values.
Deployment and documentation verification
tests/test_docker_compose.py, tests/test_docs_public_urls.py
Verifies treasury-executor service command, mounts, restart policy, and feature flag absence. Verifies runbook includes executor enablement, log command, and finalization verification guidance.
Existing proposal test monkeypatch updates
tests/test_treasury_proposals.py
Updates three tests patching app.treasury_executor.finalize_created_bounty_issue instead of app.treasury_routes, following relocated finalization call site.

Possibly related PRs

  • ramimbo/mergework#630: Introduces GitHub issue finalization recording during treasury execution; this PR relocates that same finalization logic into the new executor module.
  • ramimbo/mergework#458: Modifies the treasury proposal execution flow; both PRs refactor execution orchestration from the HTTP route handler.
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add production treasury executor service' clearly names the changed surface—a new production-side executor service for automated treasury proposal execution.
Description check ✅ Passed The description includes all required sections: Summary with bullet points, Evidence (confusion/bug addressed, intended surfaces, expected size, out of scope), Test Evidence with all checks listed, and maintainer notes clarifying scope and post-deploy guidance.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Mergework Public Artifact Hygiene ✅ Passed No investment, price, cash-out, fabricated payout, or private security claims found. MRWK described only operationally. All banned phrases absent. Documentation properly validated.
Bounty Pr Focus ✅ Passed PR does not reference Bounty #N or Refs #N; it's a maintainer infrastructure PR ("no bounty requested"), so the bounty PR focus check is not applicable.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f5473622-ac1c-4969-bcf1-133d93afd4dc

📥 Commits

Reviewing files that changed from the base of the PR and between a59f9b1 and 394ea36.

📒 Files selected for processing (12)
  • .env.example
  • app/treasury_executor.py
  • app/treasury_routes.py
  • docker-compose.yml
  • docs/admin-runbook.md
  • scripts/docs_smoke.py
  • scripts/treasury_executor.py
  • tests/test_docker_compose.py
  • tests/test_docs_public_urls.py
  • tests/test_treasury_executor.py
  • tests/test_treasury_executor_script.py
  • tests/test_treasury_proposals.py

Comment thread scripts/treasury_executor.py
Comment thread tests/test_treasury_executor_script.py
Comment thread tests/test_treasury_executor.py
Copy link
Copy Markdown
Contributor

@bitdamii bitdamii left a comment

Choose a reason for hiding this comment

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

Reviewed current head ab777afb0fadba4f203d14152decff4784161a32 as a non-author.

Verdict: APPROVE with a mergeability note. I did not find a code blocker in this head. Pre-review GitHub mergeStateStatus reported UNSTABLE, but a local merge-tree against origin/main completed cleanly; I would still recheck branch protection/mergeability after review state refresh before merging.

Evidence:

  • Inspected scripts/treasury_executor.py, app/treasury_executor.py, app/treasury_routes.py, docker-compose.yml, .env.example, docs/admin-runbook.md, tests/test_treasury_executor.py, tests/test_treasury_executor_script.py, tests/test_treasury_proposals.py, tests/test_docker_compose.py, and tests/test_docs_public_urls.py.
  • Verified the one-shot executor failure path now returns non-zero and has a regression test.
  • Verified due proposals are selected oldest-first, future proposals are skipped, LedgerError failures are reported while later due proposals continue, and create-bounty GitHub finalization records status back onto the proposal result.
  • Verified the route refactor still maps LedgerError through the existing HTTP error handling.
  • Verified the Docker service is disabled by default through .env.example, shares the production data volume, and the runbook documents executor enablement, logs, finalization checks, and manual fallback expectations.

Validation run locally:

  • uv run --extra dev python -m pytest tests/test_treasury_executor.py tests/test_treasury_executor_script.py tests/test_treasury_proposals.py tests/test_docker_compose.py tests/test_docs_public_urls.py -q -> 76 passed.
  • uv run --extra dev ruff check app/treasury_executor.py app/treasury_routes.py scripts/treasury_executor.py tests/test_treasury_executor.py tests/test_treasury_executor_script.py tests/test_treasury_proposals.py tests/test_docker_compose.py tests/test_docs_public_urls.py -> passed.
  • uv run --extra dev ruff format --check ... -> 8 files already formatted.
  • uv run --extra dev python -m mypy app/treasury_executor.py app/treasury_routes.py scripts/treasury_executor.py -> success.
  • uv run --extra dev python scripts/docs_smoke.py -> docs smoke ok.
  • git diff --check origin/main...HEAD -> clean.
  • git merge-tree --write-tree origin/main HEAD -> clean.
  • GitHub Quality/readiness/docs/image check -> success.

No private data, credentials, wallet material, production mutation, price/exchange/bridge/off-ramp claims, or fabricated payout claims used.

Copy link
Copy Markdown

@Thanhdn1984 Thanhdn1984 left a comment

Choose a reason for hiding this comment

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

Reviewed current head ab777afb0fadba4f203d14152decff4784161a32 as a non-author.

Verdict: APPROVE. Clean extraction of the treasury-executor concern from the route handler into a reusable app/treasury_executor.py module plus a standalone scripts/treasury_executor.py entry point.

Strengths:

  • Proper separation: route handler now delegates to execute_treasury_proposal_with_finalization, keeping the HTTP layer thin.
  • Executor loop is opt-in (MERGEWORK_TREASURY_EXECUTOR_ENABLED), with sane defaults (300s interval, 25 batch limit) and reasonable bounds validation.
  • _db_utc helper correctly strips timezone for SQLite comparison.
  • Error isolation: one proposal failure does not block remaining due proposals in the same batch.
  • Docker Compose service uses the same .env and shared data volume — straightforward production deployment.
  • Comprehensive test coverage: unit tests for config parsing, executor logic with fake finalizer, finalizer failure handling, Docker Compose structure, and docs smoke tests.
  • Existing test_treasury_proposals.py monkeypatch targets updated to match the new import path.

Minor observation (non-blocking):

  • The disabled-but-running loop (while True: time.sleep(...)) in main() means the container stays alive even when disabled, which is fine for the restart: unless-stopped strategy but could be documented as intentional idle behavior.

No security, correctness, or merge-readiness issues found.

@ramimbo ramimbo merged commit 41c2e64 into main May 30, 2026
2 checks passed
@ramimbo ramimbo deleted the maintainer/treasury-executor-service branch May 30, 2026 13:30
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.

3 participants