Profile
dsh-profile-web
dsh-profile-web
- Source
- Yiklek
- stars
- 1 stars
- License
- MIT
- Updated
- Updated yesterday
Readme
# dsh-web-profile 用 Git 管理 dsh `web` profile 的配置:profile 只版本化 4 个配置文件,并提供一键安装脚本、CI 校验和自动化依赖更新。 [](https://github.com/Yiklek/dsh-web-profile/actions/workflows/ci.yml) [](https://github.com/Yiklek/dsh-web-profile/actions/workflows/update-deps.yml) ## 为什么用这个仓库 dsh 的 profile 位于 `$DSH_HOME/profiles/<name>`(`DSH_HOME` 默认 `~/.dsh`),目录里既有需要版本管理的配置,也有不该提交的内容:`node_modules/`、本机生成的 `cordis.patch.yml`、运行期数据 `.dsh-market/`、本地凭据 `.env` 等。 profile 需要管理的配置只有这 4 个: ```text package.json # profile 依赖 + dsh.profile.bundles 声明 pnpm-lock.yaml # 依赖版本锁定 pnpm-workspace.yaml # pnpm 安装策略(hoisted、允许构建的原生模块) cordis.yml # profile 根(空列表,实际由 bundles 与 patch 组合) ``` 通过 `install.sh` 安装到 profile 目录,支持 **clone** 与 **git worktree** 两种方式。 ## 特性 | 能力 | 说明 | |---|---| | 配置版本化 | profile 配置只跟踪 4 个文件;`node_modules/` 与运行期数据被忽略 | | 一键安装 | 本地一条命令;远程 `curl \| bash` 无需先 clone | | worktree 工作流 | profile 目录即本仓库的 worktree,改动可直接提交并快进回 `main` | | 覆盖保护 | 覆盖已有 profile 前自动备份为 `<name>.bak.<YYYYMMDD-HHMMSS>` | | CI 校验 | shellcheck / prettier、profile 可组合可启动、Playwright 冒烟测试 | | 自动化依赖 | 每 6 小时 `pnpm update --latest` 自动提 PR;Dependabot 每日更新 npm、每周更新 Actions | ## 目录结构 ```text dsh-web-profile/ ├── .github/ │ ├── dependabot.yml # 每日 npm / 每周 GitHub Actions 更新 │ └── workflows/ │ ├── ci.yml # lint + profile 启动校验 + Playwright 冒烟 │ └── update-deps.yml # 定时 pnpm update --latest 并提 PR ├── tests/e2e/ # Playwright 冒烟测试 ├── install.sh # 安装脚本(clone / worktree) ├── package.json # profile 依赖与 bundles ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── cordis.yml ├── .gitignore ├── LICENSE └── README.md ``` ## 快速开始 环境要求:`git`、`bash`。依赖安装优先用 `dsh`,没有 `dsh` 时用 `pnpm dlx`,没有 `pnpm` 时用 `npx --yes`。CI 参考环境为 Node 22 + pnpm 11.22(见 `.github/workflows/ci.yml`)。 ### 1. 安装 本地安装(在仓库目录执行,只支持 worktree 模式): ```bash git clone https://github.com/Yiklek/dsh-web-profile.git cd dsh-web-profile ./install.sh # 安装为默认 profile:web ./install.sh web2 # 安装为自定义 profile ./install.sh web2 --force # 覆盖已存在的 profile(覆盖前仍会备份) ``` 远程一键安装(默认 clone 到 `~/.dsh/profiles/web`): ```bash curl -fsSL https://raw.githubusercontent.com/Yiklek/dsh-web-profile/main/install.sh | bash -s -- web ``` ### 2. 启动 ```bash dsh --profile web # 或 npx @deepseek-ai/dsh --profile web ``` 安装脚本完成后会直接打印对应的启动命令。 > dsh CLI 的版本通道会影响插件兼容性:CI 用 `@deepseek-ai/dsh@alpha` 验证,安装脚本回退时使用 `@next`。遇到插件加载异常时,先对齐 dsh 版本。 ## 安装详解 ### 参数 | 参数 | 作用 | 默认值 | 适用模式 | |---|---|---|---| | `[profile-name]` | 目标 profile 名称 | `web` | 全部 | | `--force` / `-f` | 跳过覆盖确认(仍会备份) | 关闭 | 全部 | | `--branch <branch>` / `-b` | worktree 分支名 | `profile-<name>` | 仅 worktree | | `--mode <clone\|worktree>` | 安装方式 | 本地 worktree;远程 clone | 仅远程 | | `--dir <path>` | source 仓库目录路径或名称 | `<cwd>/<仓库名>` | 仅远程 worktree | | `--help` / `-h` | 显示用法 | — | 全部 | > `--branch` 在 worktree 模式生效(本地或远程);`--dir` 只对**远程** worktree 安装生效,本地执行时会被忽略。`--mode clone` 下指定两者会直接报错。 ### clone vs worktree | 方式 | 行为 | 适合场景 | |---|---|---| | **clone** | 把仓库 `git clone` 到 profile 目录 | 远程一键安装,不打算在 profile 里改配置提交 | | **worktree** | 在 profile 目录创建本仓库的 git worktree | 本地开发,需要把 profile 改动合并回 `main` | ### 脚本执行流程 1. **判定模式** - 在本地 git 检出中执行:强制 `worktree`;显式指定 `--mode clone` 会报错。 - 不在 git 检出中执行(如 `curl | bash`):未指定 `--mode` 时默认 `clone`。 2. **确认覆盖(仅当 profile 已存在)** - 交互终端会询问;非交互执行必须加 `--force`。 3. **准备 source 仓库(worktree 模式)** - 远程 worktree:clone 到 `<cwd>/<仓库名>`,或用 `--dir` 指定目录;已存在则 `fetch --all --prune`。 4. **创建分支与 worktree** - 分支不存在时创建 `profile-<name>`:本地从 `main`(无则 `master`,分离 HEAD 则当前提交),远程从 `origin/main`(无则 `origin/master`,都没有则报错)。 - 分支已被其他 worktree 占用时报错退出。 - 需要覆盖时先把原目录备份为 `~/.dsh/profiles/<name>.bak.<YYYYMMDD-HHMMSS>`,再创建 worktree。 5. **安装依赖**,按可用性依次尝试: ```bash dsh plugin --profile <name> install pnpm dlx @deepseek-ai/dsh@next plugin --profile <name> install npx --yes @deepseek-ai/dsh@next plugin --profile <name> install ``` ## 更新与同步 > 以下流程仅适用于 **worktree 安装**。clone 安装直接在 profile 目录 `git pull` 即可。 > > - `<name>`:profile 名,默认 `web` > - `<source-repo>`:source 仓库目录。本地安装即本仓库;远程 worktree 安装是 `--dir` 指定的目录,或默认的 `<cwd>/dsh-web-profile` ### 拉取上游更新 ```bash cd <source-repo> && git pull --ff-only origin main cd ~/.dsh/profiles/<name> && git rebase main dsh plugin --profile <name> install # package.json / pnpm-lock.yaml 有变化时 ``` profile 分支没有本地提交时,也可以直接快进: ```bash git -C ~/.dsh/profiles/<name> merge --ff-only main ``` ### 本地改动回流 main ```bash cd ~/.dsh/profiles/<name> git add -A && git commit -m "update profile config" # 提示:git add -A 会连带暂存未忽略的本地文件(如自定义 Caddyfile); # 只想提交配置改动时改用 git add <file>... cd <source-repo> git merge --ff-only profile-<name> git push origin main # 需要发布时 ``` `--ff-only` 失败说明 `main` 与 `profile-<name>` 已分叉(例如 `main` 上有新提交)。先让 profile 分支基于最新 `main`,再快进: ```bash cd ~/.dsh/profiles/<name> git fetch origin main git rebase origin/main # 冲突时:git add -A && git rebase --continue cd <source-repo> git merge --ff-only profile-<name> ``` ### 把依赖升到最新(可选) 与自动化工作流做的事一致,在 profile 目录执行后按上面的流程提交: ```bash cd ~/.dsh/profiles/<name> pnpm update --latest dsh plugin --profile <name> install ``` ### 冲突处理 ```bash git status # 查看冲突文件 git add -A git rebase --continue # 放弃本次更新:git rebase --abort ``` ## 自动化 ### CI(`.github/workflows/ci.yml`) | Job | 内容 | |---|---| | `lint` | `shellcheck install.sh`、`bash -n install.sh`、prettier 检查 `package.json` 与 `*.yml` | | `test-dsh` | 以 `DSH_HOME=/tmp/dsh-home` 用 `install.sh` 做 worktree 安装(分支 `ci-web`)、`--dump-config` 校验组合结果、启动 web 并等待 boot token URL 出现、检查启动日志无错误 | | `e2e` | worktree 安装(分支 `ci-e2e`)+ Playwright/Chromium 跑 `tests/e2e/smoke.spec.js`:断言页面标题、可打开「设置」、本 profile 插件的设置分区已挂载,且无插件致命错误 | ### 本地复现 e2e CI 的 `e2e` job 等价于下面两步(profile 已安装且依赖已装好)。本地跑用**本机已安装的浏览器**,不下载 Playwright 自带 Chromium: ```bash # 1. 启动 dsh web,boot 日志会被测试用来解析 token URL dsh --profile web --host 127.0.0.1 --port 3099 --no-open > /tmp/dsh-e2e.log 2>&1 & # 2. 安装 Playwright 依赖并运行冒烟测试(用本机 Edge) cd tests/e2e pnpm install DSH_BOOT_LOG=/tmp/dsh-e2e.log pnpm test:edge ``` - `pnpm test:edge` 用本机 Microsoft Edge;本机是 Google Chrome 时改用 `PLAYWRIGHT_CHANNEL=chrome pnpm exec playwright test`。 - 本机确实没有 Chrome / Edge 时,才需要 `pnpm exec playwright install chromium` 使用 Playwright 自带内核。 - 测试从 `DSH_BOOT_LOG`(默认 `/tmp/dsh-e2e.log`)解析带 token 的连接 URL,也可直接用 `DSH_TOKEN_URL` 传入;端口不是 3099 时加 `DSH_PORT=<port>`。 ### 依赖更新(`.github/workflows/update-deps.yml`) - **触发**:`main` 有推送、每 6 小时定时、手动 `workflow_dispatch`。自动提交合并进 `main` 时会跳过,避免自我循环。 - **动作**:在仓库根目录与 `tests/e2e` 各执行 `pnpm update --latest`;有变化则提交到 `bot/dependency-updates-<时间戳>` 分支并开 PR。 - **收敛**:同一时间只保留一个自动化 PR,旧的自动关闭并删除分支;提交信息在只有一条升级时为 `chore(deps): bump <pkg> from <old> to <new>`,多条时为 `chore(deps): update dependencies`。 ### Dependabot(`.github/dependabot.yml`) 每日 03:00(Asia/Shanghai)更新根目录与 `tests/e2e` 的 npm 依赖,每周更新 GitHub Actions。 ## 排障与恢复 | 现象 | 处理 | |---|---| | `--dir` / `--branch` 不生效或报错 | `--branch` 仅 worktree 模式;`--dir` 仅远程 worktree 生效(本地忽略);`--mode clone` 下指定会报错 | | 分支已被其他 worktree 占用 | `git worktree list` 定位后 `git worktree remove <path>` | | `dsh` 不在 PATH | 脚本自动回退到 `pnpm dlx` 或 `npx --yes @deepseek-ai/dsh@next` | | 安装后想回滚 | 删除 profile 目录,把备份目录改回原名 | 恢复备份: ```bash rm -rf ~/.dsh/profiles/<name> mv ~/.dsh/profiles/<name>.bak.<YYYYMMDD-HHMMSS> ~/.dsh/profiles/<name> ``` ## 设计说明:为什么用 git worktree 此前尝试过两种方案,都无法正常工作: - **整个目录软链接**:Node 按真实路径解析依赖,软链接后找不到 profile 里的 `@deepseek-ai/*`。 - **配置文件软链接**:pnpm 拒绝写入符号链接形式的 `pnpm-lock.yaml`。 改用 git worktree 后:profile 目录是真实 git 检出,`pnpm-lock.yaml` 是可写真实文件,`node_modules/` 由 `.gitignore` 忽略,配置改动既能在 profile 里提交,也能回到主仓库统一管理。 ## Git 管理建议 `.gitignore` 已忽略: ```gitignore node_modules/ cordis.patch.yml .dsh-market/ .env .env.* *.local .DS_Store thinking-effort-loaded.json tests/e2e/test-results/ tests/e2e/playwright-report/ .npmrc ``` 以上内容都不要提交:依赖目录、本机生成的 `cordis.patch.yml`、运行期数据、任何包含凭据的本地文件。 ## License [MIT](LICENSE) © 2026 Yiklek
Install
dsh plugin --profile web add @deepseek-ai/dsh-base
dsh plugin --profile web add @deepseek-ai/dsh-web-app
dsh plugin --profile web add dshmarket
dsh plugin --profile web add dsh-settings-manager
dsh plugin --profile web add dsh-llm-retry-settings
dsh plugin --profile web add dsh-anchored-standard
dsh plugin --profile web add dsh-context
dsh plugin --profile web add @opendsh/dsh-plugin-setting-mcp
dsh plugin --profile web add dsh-complete-notify
dsh plugin --profile web add dsh-coding-subscription-oauth
dsh plugin --profile web add dsh-better-sidebar
dsh plugin --profile web add @tt-a1i/archify-dsh
dsh plugin --profile web add @xmanrui/dsh-im
dsh plugin --profile web add @quill507/dsh-auto-approval-llm
dsh plugin --profile web add dsh-free-search
dsh plugin --profile web add @goodandready/dsh-subscriptions
dsh plugin --profile web add dsh-plugin-subscriptions
dsh plugin --profile web add dsh-mermaid
dsh plugin --profile web add dsh-univer-office
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-profile-web from the hub
- Bundles apply in listed order and later layers win per row. Install them in the order shown.