Bundle
dsh-ci-cd-bot
DSH Web UI plugin: listens to GitHub issues/PRs across the account's repositories, auto-fixes issues whose repos are checked out locally, and turns PRs / feature requests / other items into a review-and-run queue with one-click agent execution and push.
- Source
- bkMoon1024
- stars
- 4 stars
- License
- MIT
- Updated
- Updated 6 days ago
Readme
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="docs/banner-dark.svg">
<img src="docs/banner.svg" alt="dsh-ci-cd-bot" width="720">
</picture>
</p>
<h1 align="center">dsh-ci-cd-bot</h1>
<p align="center">
<em>DSH Web UI plugin — watches GitHub issues/PRs across your account's repositories, auto-fixes issues whose repos are checked out locally, and turns PRs, feature requests, and other items into a review-and-run queue with one-click agent execution and push.</em>
</p>
<p align="center">
<a href="https://github.com/bkMoon1024/dsh-ci-cd-bot/stargazers"><img src="https://img.shields.io/github/stars/bkMoon1024/dsh-ci-cd-bot?logo=github&label=Stars" alt="GitHub stars"></a>
<a href="https://github.com/bkMoon1024/dsh-ci-cd-bot/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-65a30d?style=flat" alt="MIT license"></a>
<br>
<img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=fff" alt="TypeScript">
<img src="https://img.shields.io/badge/esbuild-FFCF00?style=flat&logo=esbuild&logoColor=000" alt="esbuild">
<img src="https://img.shields.io/badge/shipped__plugin-16a34a?style=flat" alt="shipped plugin">
</p>
<p align="center">
<b>English</b> · <a href="README.zh.md">中文</a>
</p>
---
## What it does
| Item | Handling |
| --- | --- |
| Bug issue, repo checked out locally | **Fully automatic**: an agent fixes the issue in the local checkout and self-tests → the plugin commits and pushes (optionally opens a PR) → replies to the issue |
| Feature request | Enters the board queue → click **Run** → agent implements → push → reply to the issue |
| Other issue (question / maintenance) | Enters the board queue → implements and pushes when a local checkout exists; otherwise the agent drafts a reply and the plugin posts it as a comment |
| Pull request | Enters the board queue → click **Review** → fetch the diff → agent reviews → submits APPROVE / REQUEST_CHANGES / COMMENT according to the verdict, auto-merges on approve (configurable) |
Every run is a **real agent session** (kept in the session list so you can watch the full transcript). All git plumbing — branch, commit, push — is done by the plugin itself, deterministically; the push policy can be set to **auto** or **confirm in the board**.
---
## How it works
The host half polls GitHub every N minutes (configurable): it lists the account's repositories, fetches recently updated issues/PRs per repo with a watermark (first poll backfills only the last few days), classifies them by label rules plus title/body keywords, and matches repositories to local checkouts found under the configured scan roots and DSH workspaces. New local bug issues are auto-enqueued; everything else waits in the board for a user choice.
Agent runs use the official headless pattern — `ctx.agents.create({ meta: { cwd } })` + `followup` + `whenIdle`, with success/failure decided by the `turn/end` reason in the session log. The agent only edits code and self-tests (git is forbidden in the prompt); the plugin then runs `fetch → checkout ghbot/#<n>-<slug> → add → commit → push` and writes back to GitHub (comment, PR, review, merge).
The browser half injects a **CI/CD** sidebar entry and a center-column board (mutual-exclusion handshake with the sibling panels via `dsh-panel-activate`). Config lives in `~/.dsh/dsh-ci-cd-bot.json` (0600) — the token never leaves the host, and the GUI settings page edits it through a loopback-fenced `/api/dsh-ghbot/*` route family.
---
## Quick start
DSH plugins are installed into a **profile** (`dsh web` corresponds to the `web` profile). Requires Node.js ≥ 22 and `dsh` 0.1.0-rc.6.
The package is published on npm, so installing from npm is the recommended path; building from source is only needed for development/debugging.
Full installation guide — prerequisites, npm / source / manual install, verify, update, uninstall: **[INSTALL.md](INSTALL.md)**.
### From npm (recommended)
```bash
dsh plugin --profile web add dsh-ci-cd-bot
dsh web
```
### From source
```bash
git clone https://github.com/bkMoon1024/dsh-ci-cd-bot.git
cd dsh-ci-cd-bot
npm install --ignore-scripts # the esbuild platform binary ships via optionalDependencies — no postinstall needed
npm run build
npm test # 11 headless behavior scenarios
# the package ships its own cordis.patch.yml (declared via dsh.bundle.patch),
# so the plugin row registers automatically
dsh plugin --profile web add link:$(pwd)
dsh web
```
### Manual install (no pnpm / dsh plugin)
```bash
ln -sfn "$(pwd)" ~/.dsh/profiles/node_modules/dsh-ci-cd-bot
# then append to ~/.dsh/profiles/web/cordis.patch.yml:
# - insert:
# - id: ci-cd-bot
# name: 'dsh-ci-cd-bot'
dsh web
```
> Switching from a manual install to `dsh plugin add`? Remove the manually added `insert` entry first — the bundle patch registers the plugin row itself and duplicate rows conflict.
### Verify & uninstall
```bash
dsh --profile web --dump-config | grep ci-cd-bot # confirm the config layer mounted
```
After a restart a **CI/CD** entry appears in the sidebar. First use: open the board → 设置 → paste a GitHub token (repo scope), configure scan roots if needed → save.
```bash
dsh plugin --profile web remove dsh-ci-cd-bot # npm / repo install
# or delete the symlink + insert entry # manual install
dsh web
```
---
## Configuration
Most parameters are editable in the board's settings page; changes apply immediately and persist to `~/.dsh/dsh-ci-cd-bot.json` (`announceToAgent` is JSON / API only). Complete reference — required fields, defaults, examples, security notes: **[CONFIG.md](CONFIG.md)**.
| Field | Default | Description |
| --- | --- | --- |
| GitHub Token | — | GitHub PAT with repo scope; kept on the host, never sent to the browser |
| Poll interval (ms) | `300000` | How often the listener polls GitHub |
| Backfill window (days) | `3` | First-poll window for open items |
| Scan roots | — | Extra local roots scanned for git checkouts (DSH workspaces are added automatically) |
| Bug labels | `bug,故障,defect` | Labels that classify an issue as a bug |
| Feature labels | `enhancement,feature,需求` | Labels that classify an issue as a feature request |
| Auto-fix local bugs | on | Bug issues whose repo is checked out locally run automatically |
| Push policy | `auto` | `auto` pushes immediately; `confirm` parks the run at a board confirmation gate |
| Open a PR after fixes | on | Push the `ghbot/…` branch and open a PR instead of merging directly |
| Reply to the issue | on | Post a summary comment after a run finishes |
| Auto-merge on approve | on | Merge a PR when the review verdict is approve |
| Run concurrency | `2` | Max concurrent agent runs |
| Run timeout (ms) | `1800000` | Hard timeout for one agent run |
| Enable listener | on | Master switch for polling + execution |
| Announce to agent | on | System-prompt section announcing the plugin to chat agents |
| Include / exclude repos | — | `owner/repo` filters (empty = all account repos) |
---
## Tech stack & structure
| Layer | Choice |
| --- | --- |
| Platform | DSH Web GUI plugin — host half + browser half (shipped form, no dsh source changes) |
| Language | TypeScript (host half runs in the ordinary Node process: node builtins, fetch, dsh SDK packages) |
| Build | esbuild platform binary invoked directly + tsc declarations (`node build.mjs`) |
| Runtime deps | Host: `@deepseek-ai/dsh-agent` / `dsh-llm` / `dsh-session` (resolved by the dsh installation); browser: `react` (platform seed word) |
| Storage | `~/.dsh/dsh-ci-cd-bot.json` (config) + `~/.dsh/dsh-ci-cd-bot-state.json` (items / watermarks) |
```
dsh-ci-cd-bot/
├── package.json # plugin manifest (dsh.client / dsh.bundle)
├── cordis.patch.yml # profile patch layer: registers the plugin row
├── INSTALL.md / CONFIG.md # installation guide / configuration manual
├── build.mjs # esbuild build (browser CJS wrap + host ESM)
├── tsconfig.json / tsconfig.build.json
├── src/
│ ├── index.ts # host half: listener/runner/queue/routes/announcement
│ ├── gh.ts # GitHub REST client (fetch, pagination, rate-limit backoff)
│ ├── listener.ts # polling engine (watermarks, auto-enqueue local bugs)
│ ├── agent-run.ts # ctx.agents.create({meta:{cwd}}) → followup → whenIdle
│ ├── runner.ts # fix/implement/handle flows + git plumbing + push policy
│ ├── review.ts # PR review flow (diff → agent → submit review / merge)
│ ├── routes.ts # /api/dsh-ghbot/* (loopback-fenced)
│ └── client/
│ ├── index.ts # browser half entry
│ ├── sidebar-entry.ts# DOM-injected sidebar entry (family-block convention)
│ ├── board-mount.tsx # center-column React root + panel mutual exclusion
│ ├── Board.tsx / settings-view.tsx / controller.ts / api.ts
│ └── locales.ts / board.css / styles.ts
├── tests/run.mjs # 11 headless behavior scenarios
├── lib/ # build output (committed, directly linkable)
└── docs/ # banners + design notes
```
---
## Known limitations
- The sibling sidebar panels (task board, SSH) do not know the `ghbot` panel-activate event value; their controllers stay "open" internally while this board is visible (visual exclusivity holds, one extra click toggles back).
- Classification is rule-based (labels + keywords, both configurable); an LLM fallback is a planned option.
- A timed-out run is marked failed but the agent is not cancelled mid-flight.
- github.com only (no GitHub Enterprise yet); the board refreshes by polling, not SSE.
---
## Development
```bash
npm run typecheck # tsc --noEmit
npm run build # lib/client.js + lib/index.js + lib/types
npm test # node tests/run.mjs — 11 behavior scenarios
```
Source must stay compatible with Node's strip-only TypeScript loader (used by the test runner): no parameter properties (`constructor(readonly x)`), no `enum`, no `namespace`.
---
## Publishing
```bash
npm run build
npm publish # publishes dsh-ci-cd-bot with the bundled cordis.patch.yml
```
A tag-triggered CI pipeline (verify version tag → build + test → publish → GitHub release with artifacts) can be added the same way as sibling DSH plugins.
---
## Links
- **Repository**: [github.com/bkMoon1024/dsh-ci-cd-bot](https://github.com/bkMoon1024/dsh-ci-cd-bot)
- **Installation**: [INSTALL.md](INSTALL.md) · **Configuration**: [CONFIG.md](CONFIG.md)
- **DeepSeek Harness**: [github.com/deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)
---
## License
[](LICENSE)
MIT © bkMoon1024
Install
dsh plugin --profile web add github:bkMoon1024/dsh-ci-cd-bot#c2f8f7b6f16780360978addf4ffea00f5c1676aa
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-ci-cd-bot from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.