Update DeepSeek Harness in CI: DSH plugin versions
Updating DeepSeek Harness in CI is a different problem from updating it by hand: there is no terminal (so a single prompt hangs the job), you need reproducibility (versions must not drift), and time is multiplied by build count. Copying interactive commands into YAML therefore fails in predictable ways. Pick a version-source strategy first — pinned versions, latest-with-snapshot, or a version-carrying image — then add non-interactive and fail-fast patterns, then caching. DSH plugin packages add one more layer: pin their versions too, or you lock the CLI and still cannot reproduce failures because plugins drift.
Why updating DeepSeek Harness in CI differs from manual updates
Bottom line: three differences — no terminal, no tolerance for random versions, and amplified time cost. All three point to making the version an explicit input.
| Dimension | Manual update | CI update |
|---|---|---|
| Interaction | You can answer prompts | Any prompt hangs the job |
| Version | Latest is acceptable | Must be pinned or snapshotted |
| Time | Paid once | Paid on every build |
| Visibility | You watch the terminal | Only logs and exit codes |
Option A: pinned versions (reproducible, recommended)
Bottom line: write the CLI and DSH plugin versions into configuration, and treat upgrading as editing that version and committing. This is the only approach that answers "which version ran."
- Install the pinned CLI:
npm i -g @deepseek-ai/dsh@0.2.0-rc.2
dsh --version # expected: matches the pinned version
- Pin the plugin list in an executable manifest:
# plugins.txt — one package@version per line
dsh plugin add <plugin-package>@<version>
- Make upgrading an explicit commit: change the version, commit, re-run. Never write "always install latest" in CI.
- Record validated combinations: one line per CLI plus plugin version set. Rollback means copying the previous line (the same practice applies in aligning DeepSeek Harness across machines).
Option B: latest plus snapshot (tracking upstream)
Bottom line: if you genuinely need "always latest," print and archive the version you actually got — trade reproducibility for traceability.
- Install latest but capture the result immediately:
npm i -g @deepseek-ai/dsh
dsh --version | tee version.txt # archive as a build artifact
- Treat the snapshot as a build output: version file and installed DSH plugin list both archived, so you can compare against the last green run.
- Alert on version changes instead of adopting them silently, making upstream releases visible.
- Stated cost: you give up reproducibility in exchange for early warning of compatibility problems.
Option C: images carry the DeepSeek Harness version (fastest jobs)
Bottom line: bake the CLI and common DSH plugin packages into an internal image and have the pipeline pull it. Versions are pinned by construction and install time drops to nearly zero.
- Pin inside the image and preset plugins (see Path C in installing DeepSeek Harness in Docker).
- Run tests directly from the image — no download, no compile, stable build times.
- Upgrading means building and publishing a new tag; keep the old tag as the rollback point. This is easier to roll back than editing version numbers in scripts.
- Watch volumes: point the data directory at a temporary path in CI so previous session state never leaks into the current test.
Non-interactive and fail-fast patterns for DeepSeek Harness
Bottom line: non-interactive needs an explicit environment variable, input-free flags and a timeout; fail-fast needs set -e plus explicit exit-code checks.
- Pattern one: declare the non-interactive environment (example):
export CI=true
set -euo pipefail # stop on the first failure instead of continuing broken
- Pattern two: avoid interactive flags at the command level. Prefer deterministic equivalents over anything that prompts or opens an editor.
- Pattern three: wrap with a timeout so a hang cannot stall the job:
timeout 900 npm i -g @deepseek-ai/dsh@0.2.0-rc.2
# expected: exits non-zero on timeout, failing the pipeline immediately
- Never ignore exit codes: separate install and verify steps, and fail the pipeline when verification fails. Installing without verifying is not a test.
Caching options for DeepSeek Harness CI jobs
Bottom line: by payoff, images beat package caching, which beats skipping by hash. Use an image when you can.
- Image presets (largest win): the CLI and frequent DSH plugin packages live in the image; the job installs nothing.
- Cache the npm cache directory, keyed by a lockfile or manifest hash:
# illustrative: key derived from manifest hashes
key: dsh-${{ hashFiles('plugins.txt', 'package-lock.json') }}
- Skip installation when nothing changed, but occasionally purge the cache to avoid stale bad artifacts.
- Point the registry at your private source on intranet runners, or every job hits the public internet (see running npx @deepseek-ai/dsh web offline).
Post-run verification for DeepSeek Harness and DSH plugin
Bottom line: a zero exit code is not success. Verify the version, the plugin set, and that the service starts.
- Version check: print dsh --version and the resolved executable path, then compare.
- Plugin list check: list installed plugins and compare counts and versions; missing entries mean a plugin did not install.
- Smoke check: start the service once and confirm the port responds — dsh web starting is the minimum usable proof.
- Archive all three outputs as build artifacts for later comparison.
- Check DSH_HOME: a temporary directory per run keeps state from leaking between builds.

DSH plugin CI troubleshooting
Bottom line: split failures into "hangs" and "errors." Hangs are almost always prompts; errors are versions and sources.
- Hang — check for prompts, a missing CI variable, or a missing timeout.
- Will not install — check the source and whether the package version exists (and whether the private source synced it).
- Version unchanged — check whether the install hit a different entry point, the same root cause as npx versus global drift.
- Plugin missing — check the manifest item by item instead of retrying.
- Intermittent failure — suspect a stale cached artifact; clear the cache and re-run to confirm.
- Repair status, stated honestly: these options follow npm's reproducible install mechanics and the official CLI's upgrade and plugin subcommands. Confirm flag names via dsh --help inside the pipeline, and record both versions and flags in your repository documentation.
Sources: apps/cli/README.md, npm Docs · npm ci, npm @deepseek-ai/dsh.
FAQ
In DeepSeek Harness, an interactive prompt in a pipeline has nobody to answer it, so the process waits forever. Three fixes: set an explicit continuous-integration environment variable, avoid flags that request input, and wrap commands in a timeout so a hang fails fast instead of stalling the job. Confirm flag names with dsh --help for your version.
In DeepSeek Harness, pipelines exist to be reproducible. Without pinning, a build that passes today can fail tomorrow because upstream published a new release, and diagnosis becomes expensive. Pinning lets you state exactly which version ran and gives rollback a definite target; upgrades should be explicit actions, not silent adoption of latest.
Three levers: cache the npm cache directory across pipeline runs, bake DeepSeek Harness and common DSH plugin packages into an internal image so the job only starts, and skip installation when the dependency manifest hash is unchanged. They stack, and the image approach saves the most time.
Three checks: print dsh --version and the resolved executable path and compare with expectations; list installed DSH plugin packages and compare counts and versions; run a smoke test such as starting dsh web and confirming the port responds. An install exit code of zero is not proof — a zero exit with an unchanged version is common.
In DeepSeek Harness, because versions are pinned, rollback means changing the version back to the last known-good one and re-running; no uninstall step is needed. Keep a record of validated version combinations — CLI version plus plugin versions — so rollback is a one-line change rather than trial and error.
Related Terms
- non-interactive mode
- Non-interactive mode is how a command runs where no human can respond, such as a CI pipeline. DeepSeek Harness installs and upgrades must take a non-interactive path in CI or they block waiting for input.— https://docs.npmjs.com/cli/v10/commands/npm-ci
- reproducible build
- A reproducible build produces the same result from the same inputs — code plus pinned dependency versions. Pinning DeepSeek Harness and its DSH plugin packages is what separates build failures from upstream changes.— https://docs.npmjs.com/cli/v10/commands/npm-ci
- cache key
- A cache key decides whether a pipeline cache hits, typically derived from a manifest hash. Keying on a lockfile or manifest hash means unchanged dependencies reuse the cache and changed ones reinstall.— https://docs.npmjs.com/cli/v10/commands/npm-ci
- smoke check
- A smoke check is a minimal post-upgrade validation that the critical path still works. For DeepSeek Harness the minimum set is the version number, the installed DSH plugin list, and whether dsh web starts.— https://github.com/deepseek-ai/deepseek-harness/blob/master/apps/cli/README.md