Files
deepseek-harness/docs/user/guide/github-review.md
T

4.3 KiB

Create review Sessions from GitHub webhooks

English | 中文

This opt-in overlay adds a signed GitHub endpoint to dsh web. When a pull request in the configured repository changes from draft to ready for review, the rule creates a titled root Session under the repository's Web Workspace and starts a read-only review prompt.

Prerequisites

  • A local checkout that DSH may register as a Web Workspace.
  • A high-entropy GitHub webhook secret available through the DSH_GITHUB_WEBHOOK_SECRET credential reference.
  • A TLS reverse proxy or tunnel that can forward one public URL to the loopback listener.
  • GitHub webhook subscription to the Pull requests event with content type application/json.

The overlay defaults the Workspace to the launch directory and the listener to 127.0.0.1:3081. Override them with DSH_GITHUB_REVIEW_WORKSPACE and DSH_GITHUB_WEBHOOK_PORT.

Start DSH

Generate a secret and retain the same value across restarts:

export DSH_GITHUB_WEBHOOK_SECRET="$(openssl rand -hex 32)"
printf '%s\n' "$DSH_GITHUB_WEBHOOK_SECRET"

From a development checkout:

export DSH_GITHUB_REVIEW_WORKSPACE=/path/to/deepseek-harness
pnpm dsh web --patch apps/cli/config/examples/github-review/cordis.yml

An installed DSH uses the same overlay through an absolute path:

dsh web --patch /absolute/path/to/github-review/cordis.yml

For a permanent profile, place github-ready-review-rule.mjs beside $DSH_HOME/profiles/web/cordis.patch.yml, append the rows from cordis.yml to that patch, and start with dsh web. The shipped CLI already contains both webhook packages; the overlay alone activates them.

Expose the dedicated endpoint

The main Web UI and /api remain on port 3080. The overlay mounts a second WebServer in an isolated realm; only POST /github is registered there, and every other path returns 404.

A Caddy configuration can expose only that listener:

hooks.example.com {
  route {
    @github path /github
    reverse_proxy @github 127.0.0.1:3081
    respond 404
  }
}

Configure GitHub with:

Payload URL:  https://hooks.example.com/github
Content type: application/json
Secret:       DSH_GITHUB_WEBHOOK_SECRET value
Events:       Pull requests
Active:       yes

Rule behavior

The rule accepts only source primary-github, repository deepseek-harness/deepseek-harness, event pull_request, and action ready_for_review. It passes the exact head SHA plus selected PR fields to the review prompt, labeling the JSON as untrusted metadata and forbidding file, branch, PR, or GitHub mutation.

The Session request selects the standard agent preset and read-only permission preset. workspacePath is canonicalized through WorkspaceRegistry.create(), so the first matching delivery creates the Web Workspace when absent and later deliveries reuse it.

The HTTP response is intentionally weaker than the Agent outcome: 202 means the signature and JSON were accepted and rule calls were scheduled in memory. It does not mean this rule matched or that a Session was created.

Programmatic extensions

run() is ordinary trusted JavaScript. A deployment can query an internal policy service before returning a Session request:

const response = await fetch('https://policy.internal/pr-review', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ repository: payload.repository.full_name }),
  signal,
})
if (!response.ok || (await response.json()).automaticReview !== true) return null

It can also map repositories to different local paths:

const workspacePath = {
  'deepseek-harness/deepseek-harness': '/path/to/deepseek-harness',
  'deepseek-harness/dsh-sdk': '/path/to/dsh-sdk',
}[payload.repository.full_name]
if (workspacePath === undefined) return null

Delivery semantics

The webhook runtime stores no delivery or execution state. Repeated delivery runs the rule and may create another Session. A crash loses rule calls that have not admitted their prompt. After prompt admission, the ordinary Session log, persistence, Workspace, and Agent lifecycle own the work.

The webhook secret authenticates inbound GitHub data only. It grants neither rule code nor the created Agent outbound GitHub access; configure that authority separately when a rule or Agent needs it.