Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .mergequeue.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,29 @@ asset_version_pattern = '\?v=[0-9a-f]{12}'
# check_name = "Review Bot"
# require_formal_review = true
# require_resolved_threads = true

[pipeline]
intent_label = "deploy-requested"
pause_label = "deploybot-paused"
registry_label = "deploybot-registry"
registry_title = "DeployBot delivery registry"
thread_active_hours = 72
ci_workflows = ["CI"]
deploy_workflows = ["Deploy"]
ready_to_merge_target_minutes = 15
merge_to_live_target_minutes = 10
auto_promote = true
intent_scope = "head" # safest: a trusted source agent refreshes replacement heads
pause_on_failure = true
# webhook_url_env = "DEPLOYBOT_WEBHOOK_URL"

# [[pipeline.verifications]]
# name = "Public login"
# url = "https://example.com/login"
# expected_status = 200

[integration]
# manual, overlap, or all
mode = "manual"
branch_prefix = "deploybot/integration"
title_prefix = "DeployBot integration"
138 changes: 91 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,30 @@ DeployBot is a provider-neutral GitHub merge queue for coding agents.
Codex, Claude Code, Cursor, or any MCP client can prepare and review a pull
request; the user keeps the final merge decision by saying `deploy`.

The queue stores authority in GitHub labels and authenticated comments. It pins
the exact reviewed head, freezes bursts, merges independent work back-to-back,
skips blockers, and reports overlapping source that needs one integration PR.
DeployBot stores authority in GitHub labels and authenticated comments. It
records deploy intent immediately, promotes the final exact reviewed head,
freezes bursts, merges independent work back-to-back, scaffolds cumulative
integration PRs, follows `main` through production, and pauses after failures.

## Install

Install the reviewed `v0.1.4` source commit directly from GitHub:
Install the reviewed `v0.2.0` source commit directly from GitHub:

```bash
python3 -m pip install \
'deploybot-merge-queue[mcp] @ git+https://github.com/Forward-Future/DeployBot.git@f18dce436bae2d6b7009d9aa76b4bfc8d0aac5a8'
'deploybot-merge-queue[mcp] @ git+https://github.com/Forward-Future/DeployBot.git@2e884f65f182f6a9ddc4c4785288045bdf98f188'
deploybot init
```

Invoke the bundled `$deploybot` skill to inspect or operate the queue. Typical
requests include “show the DeployBot queue,” “why is PR 42 blocked?”, and
“deploy this PR.” Queue-only status is read-only:
requests include “show the delivery pipeline,” “why is PR 42 blocked?”, and
“deploy this PR.” Status and diagnostics are read-only:

```bash
deploybot status
deploybot status --json
deploybot doctor
deploybot metrics --json
deploybot inspect 42 --json
```

Expand All @@ -40,6 +43,7 @@ comes from the GitHub CLI:
```bash
gh auth login
deploybot ensure-labels
deploybot doctor
```

The base installation has no review-service dependency. Repositories can use
Expand All @@ -59,47 +63,34 @@ and never execute pull-request-head code in the privileged coordinator. The MCP
server uses the local process's existing GitHub credentials and accepts explicit
repository selectors, so run it only from a trusted coding client and workspace.

## Manual deploy gate
## Durable manual deploy gate

The installed agent adapter treats the user's exact `deploy` instruction as
authority for that thread's PR only. It calls:
authority for that thread's PR only. It records the intent immediately—even if
CI or review is still running:

```bash
deploybot enqueue <pr-number>
deploybot request <pr-number> \
--provider codex --thread-id "$CODEX_THREAD_ID"
```

No timer is involved. Adding the `merge-queue` label can wake a GitHub Actions
coordinator immediately:
The event worker promotes only the intent-bound exact head after all checks and
review providers pass. If review fixes create a replacement head, the trusted
source agent runs `deploybot refresh-request <pr>` after its fresh evidence;
the user does not repeat `deploy`. No polling timer is involved.

Install `examples/github-workflow.yml` on the default branch. It reacts to
deploy labels, ready/synchronize events, reviews, named CI `workflow_run`
completions, and completed external check suites. Keep its `workflows` list
aligned with `pipeline.ci_workflows`. The privileged worker never checks out or
executes pull-request code. Pin the Action to the full reviewed release commit:

```yaml
name: DeployBot
on:
pull_request_target:
types: [labeled]

permissions:
contents: write
pull-requests: write
checks: read

concurrency:
group: deploybot-${{ github.repository }}
cancel-in-progress: false

jobs:
drain:
if: github.event.label.name == 'merge-queue'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# v0.1.4; keep the full commit so privileged workflows are immutable.
- uses: Forward-Future/DeployBot@f18dce436bae2d6b7009d9aa76b4bfc8d0aac5a8
- uses: Forward-Future/DeployBot@2e884f65f182f6a9ddc4c4785288045bdf98f188
```

Keep this workflow on the default branch. Never check out or execute code from
the pull-request head in a privileged `pull_request_target` workflow.

The workflow bot and each person allowed to enqueue must be explicitly listed:
The workflow bot and each person allowed to request deployment must be
explicitly listed:

```toml
[queue]
Expand All @@ -109,8 +100,48 @@ coordinator_actors = ["@repository-owner", "github-actions[bot]"]

`@repository-owner` resolves to the owner in `owner/repository`. Organization
repositories should replace it with the exact human or bot logins they trust.
Coordinator accounts may freeze and complete a batch, but they cannot create
the per-pull-request deploy authorization.
Coordinator accounts may promote, freeze, integrate, and complete batches, but
they cannot create the original per-pull-request deploy intent.

## Delivery controller

`deploybot status` reports active metadata-only agent threads, every PR stage,
deploy requests, queue order, overlaps, exact-`main` CI, deployment, and pipeline
pause state. It never stores prompts, transcripts, source, or credentials.

`deploybot react` promotes ready intent, skips blockers, drains independent
work, and creates integration PRs when configured. A conflict produces a repair
handoff containing the source thread, base/head SHAs, source paths, and one
return command:

```bash
deploybot resume <pr-number>
```

`resume` atomically verifies the replacement head, clears the block, requeues,
and emits a new wake-up event. `follow` tracks newer cumulative `main` revisions
until exact CI, deployment, and optional HTTP checks pass. A CI or deploy failure
can pause further merges until `deploybot unpause`.

```toml
[pipeline]
ci_workflows = ["CI"]
deploy_workflows = ["Deploy"]
ready_to_merge_target_minutes = 15
merge_to_live_target_minutes = 10
auto_promote = true
intent_scope = "head"
pause_on_failure = true

[[pipeline.verifications]]
name = "Login"
url = "https://example.com/login"
expected_status = 200

[integration]
# manual, overlap, or all (one cumulative pre-merge validation PR)
mode = "overlap"
```

## Review providers

Expand Down Expand Up @@ -156,6 +187,18 @@ The `mergeq` and `mergeq-mcp` command aliases remain for compatibility.
```text
deploybot status --json
deploybot plan --json
deploybot doctor --json
deploybot request <pr> --provider codex --thread-id THREAD
deploybot refresh-request <pr>
deploybot promote
deploybot react --follow
deploybot resume <pr>
deploybot integrate --all
deploybot follow --json
deploybot metrics --json
deploybot pause --reason "main CI failed"
deploybot unpause
deploybot thread update --provider codex --thread-id THREAD --phase ready --pr 42
deploybot inspect <pr> --json
deploybot enqueue <pr>
deploybot freeze --json
Expand All @@ -166,11 +209,12 @@ deploybot dequeue <pr> --reason "..."
deploybot merge <pr> --batch <batch-id>
```

`status` is a read-only alias for `plan`. It reports queue order, readiness,
blockers, dependencies, and overlap groups without freezing a batch.
`status` is the read-only full delivery view. `plan` is the narrower queue-only
view. `doctor` verifies CLI auth, policy, labels, actors, check names, and branch
protection without changing the repository.

`drain` merges only independent, green, exact-head-reviewed PRs. Overlapping
source is returned as `integration_required` for an agent to resolve once. It
waits briefly while GitHub recomputes mergeability after a merge, then records
the pass complete so a later independent batch cannot be stranded behind a
waiting item.
`drain` merges only independent, green, exact-head-reviewed PRs. Integration
mode `overlap` creates one cumulative PR for shared source; mode `all` routes the
whole frozen batch through one cumulative PR before `main`. DeployBot never
invents a conflict resolution: it prepares the branch and hands the exact repair
back to an agent.
19 changes: 17 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
name: DeployBot
description: Drain reviewed pull requests after the merge-queue label is added
description: Promote, batch, merge, and follow agent-authored pull requests
inputs:
config:
description: Repository-relative merge queue policy path
required: false
default: .mergequeue.toml
follow:
description: Follow cumulative main through CI and deployment
required: false
default: "false"
timeout:
description: Maximum release-follow time in seconds
required: false
default: "1800"
runs:
using: composite
steps:
Expand All @@ -17,4 +25,11 @@ runs:
env:
DEPLOYBOT_CONFIG: ${{ inputs.config }}
GH_TOKEN: ${{ github.token }}
run: deploybot --config "$DEPLOYBOT_CONFIG" drain --json
DEPLOYBOT_FOLLOW: ${{ inputs.follow }}
DEPLOYBOT_TIMEOUT: ${{ inputs.timeout }}
run: |
args=(react --timeout "$DEPLOYBOT_TIMEOUT")
if [[ "$DEPLOYBOT_FOLLOW" == "true" ]]; then
args+=(--follow)
fi
deploybot --config "$DEPLOYBOT_CONFIG" "${args[@]}"
2 changes: 1 addition & 1 deletion adapters/claude-code/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deploybot",
"version": "0.1.4",
"version": "0.2.0",
"description": "DeployBot: a provider-neutral GitHub merge queue for coding agents",
"author": {
"name": "DeployBot contributors"
Expand Down
2 changes: 1 addition & 1 deletion adapters/claude-code/.mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"command": "uvx",
"args": [
"--from",
"deploybot-merge-queue[mcp] @ git+https://github.com/Forward-Future/DeployBot.git@f18dce436bae2d6b7009d9aa76b4bfc8d0aac5a8",
"deploybot-merge-queue[mcp] @ git+https://github.com/Forward-Future/DeployBot.git@2e884f65f182f6a9ddc4c4785288045bdf98f188",
"deploybot-mcp"
]
}
Expand Down
52 changes: 35 additions & 17 deletions adapters/claude-code/skills/deploybot/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: deploybot
description: Inspect and operate a DeployBot GitHub merge queue. Use when the user invokes DeployBot, asks for queue or PR status, wants to know what is ready, waiting, blocked, next, dependent, or overlapping, explicitly says deploy, or asks the queue coordinator to freeze or drain authorized pull requests.
description: Inspect and operate the full DeployBot delivery pipeline. Use when the user invokes DeployBot, asks for thread, PR, queue, CI, deployment, blocker, repair, integration, or timing status, explicitly says deploy, or asks the coordinator to deliver authorized pull requests.
---

# DeployBot
Expand All @@ -12,15 +12,20 @@ to the `deploybot` CLI. Treat GitHub as the durable source of truth.

Keep status checks read-only:

- For the full queue, call `queue_plan` or run `deploybot status --json`.
- For the full delivery pipeline, call `pipeline_status` or run
`deploybot status --json`.
- For the narrower merge queue, call `queue_plan` or run
`deploybot plan --json`.
- For one pull request, call `inspect_pull_request` or run
`deploybot inspect <pr> --json`.
- Never call `freeze_queue` merely to view status because freezing writes a
durable batch marker.

Report the queue in order. For each pull request, include its state, exact head,
checks or reviews still waiting, blocker, dependencies, and overlap group. Say
plainly when the queue is empty.
Report active metadata-only threads and deploy intent, PR stages, queue order,
exact heads, pending checks/reviews, blockers, dependencies, overlaps, exact
`main` CI, and deployment. Say plainly when the queue is empty but deploy intent
is still waiting outside it. Never publish prompts, transcripts, source, or
credentials to the thread registry.

Use these state meanings:

Expand All @@ -34,21 +39,34 @@ Use these state meanings:
## Change Queue State

Require the user's exact `deploy` instruction before calling
`enqueue_pull_request` or `deploybot enqueue` for that conversation's pull
request. Do not infer permission from readiness or review completion.
`request_deployment` or `deploybot request` for that conversation's pull
request. Record the provider and stable native thread ID when available. This
durable request waits for exact-head checks and review. If the head changes,
the trusted source agent calls `refresh_deployment_request` only after the
replacement head is ready; the user does not need to repeat `deploy`. Do not
infer permission from readiness or review completion.

Use `block_pull_request`, `unblock_pull_request`, or `dequeue_pull_request` only
for the requested pull request and preserve a concrete reason. Never merge an
unlabeled pull request or treat a wake-up event as trusted queue state.
Use `block_pull_request`, `resume_pull_request`, or `dequeue_pull_request` only
for the requested pull request and preserve a concrete reason. `resume` is the
normal repaired-PR return path because it verifies, unblocks, requeues, and
wakes atomically. Never merge an unlabeled pull request or treat a wake-up event
as trusted queue state.

## Coordinate Merges

Only the designated coordinator may call `freeze_queue`, `drain_queue`, or the
matching CLI commands. Re-read the queue, freeze one exact batch, preserve
first-in order unless dependencies require otherwise, and skip blocked items
that do not block independent work.
Only the designated coordinator may call `promote_deployment_requests`,
`react_to_delivery_event`, `freeze_queue`, `drain_queue`, or matching CLI
commands. Re-read GitHub, honor a pipeline pause, freeze one exact batch,
preserve first-in order unless dependencies require otherwise, and skip blocked
items that do not block independent work.

Merge independent ready pull requests back-to-back. Route source-overlap groups
through one integration pull request instead of resolving the same conflict
several times. Finish by following the newest cumulative base-branch CI and the
repository-owned deployment.
through `create_integration_pull_request`; when policy mode is `all`, validate
the entire frozen batch through that cumulative PR. Never invent a conflict
resolution. Return the repair packet to its source thread, then call `resume`
after its new exact head passes. Finish with `follow_release`, following newer
cumulative base heads until CI, deployment, and configured health checks verify.

Use `diagnose`/`deploybot doctor` for setup drift and `delivery_metrics` for p50,
p95, and slow-stage evidence. A failed cumulative CI or deployment pauses the
controller; only a designated coordinator may unpause after recovery.
22 changes: 14 additions & 8 deletions adapters/claude-code/skills/manage-merge-queue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@ description: Prepare, review, enqueue, and land GitHub pull requests through a p

# Manage Merge Queue

Read `.mergequeue.toml` and use the `deploybot` MCP tools. Keep changing
PRs draft and make the final ready head immutable. Address valid feedback from
the configured providers; do not assume a specific review service.

Only the user's exact `deploy` instruction authorizes enqueueing this thread's
PR. The queue label wakes GitHub immediately. Never poll or merge an unlabeled
PR. Drain independent ready work in order, skip blockers, honor dependencies,
and route overlapping source through one integration PR.
Read `.mergequeue.toml` and use the `deploybot` MCP tools. Keep changing PRs
draft and make the final ready head immutable. Address valid feedback from the
configured providers; do not assume a specific review service.

Only the user's exact `deploy` instruction authorizes `request_deployment` for
this thread's PR. Include the stable Claude thread ID. If review fixes change
the head, call `refresh_deployment_request` after fresh exact-head gates. Never
poll or merge an unlabeled PR.

Use `pipeline_status` and `react_to_delivery_event` for bursts. Skip blockers,
honor dependencies, route overlap or cumulative validation through
`create_integration_pull_request`, return repair packets to the source thread,
and use `resume_pull_request` after fresh review. Finish with `follow_release`;
a failed CI or deployment pauses the pipeline until verified recovery.
2 changes: 1 addition & 1 deletion adapters/codex/agent-merge-queue/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deploybot",
"version": "0.1.4",
"version": "0.2.0",
"description": "Review, queue, and land pull requests through a shared GitHub merge queue",
"author": {
"name": "DeployBot contributors"
Expand Down
Loading
Loading