mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
ci(repository-plugin): authenticate private GitHub source
This commit is contained in:
+2
-2
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-30-static-repository-plugin-format.md
|
||||
2026-07-30-static-repository-plugin-format.md: 4823495dabee2101713ac72c8d0cee5bcc6b38d1
|
||||
2026-07-30-static-repository-plugin-format.zh.md: e5817ca982a71a609c86c5835b803b12f1317e1a
|
||||
2026-07-30-static-repository-plugin-format.md: 5b1038f8738868a5838d4b20a6d56399c5f11ab6
|
||||
2026-07-30-static-repository-plugin-format.zh.md: c7cbc588c5ce6982c7c7003815151c9d40956972
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@ Unknown MCP fields reject. This intentionally excludes OAuth, `auth` objects, `C
|
||||
|
||||
## Testing
|
||||
|
||||
Focused tests prepare skills and MCP metadata, prove the emitted wrapper contains no imports, reject Work IQ-style OAuth fields, map Expo-style HTTP and DataJunction-style stdio plus environment values, and exercise missing variables. A real Loader test mounts a generated wrapper through the registered builtin, reads its skill through `ctx.skills`, removes the Loader entry, and observes provider cleanup. The CI built-entry acceptance invokes `dsh run` with a GitHub source pinned to the pull request head, lets bundled pnpm fetch and prepare a private dependency-free fixture, then observes the copied skill in the real model request and the prepared wrapper in the immutable cache.
|
||||
Focused tests prepare skills and MCP metadata, prove the emitted wrapper contains no imports, reject Work IQ-style OAuth fields, map Expo-style HTTP and DataJunction-style stdio plus environment values, and exercise missing variables. A real Loader test mounts a generated wrapper through the registered builtin, reads its skill through `ctx.skills`, removes the Loader entry, and observes provider cleanup. The CI built-entry acceptance invokes `dsh run` with a GitHub source pinned to the pull request head, authenticates to the private pull request repository through job-scoped Git configuration, lets bundled pnpm fetch and prepare its dependency-free fixture, then observes the copied skill in the real model request and the prepared wrapper in the immutable cache.
|
||||
|
||||
+1
-1
@@ -46,4 +46,4 @@
|
||||
|
||||
## 测试
|
||||
|
||||
聚焦测试会准备 skills 与 MCP metadata,证明生成包装模块不含 import,拒绝 Work IQ 风格的 OAuth 字段,映射 Expo 风格 HTTP 与 DataJunction 风格 stdio 及环境变量,并覆盖缺失变量。真实 Loader 测试通过已注册 builtin 挂载生成包装模块,经 `ctx.skills` 读取其 skill,移除 Loader 条目并观察提供方清理。CI 的构建入口验收会用锁定到 PR(Pull Request)head 的 GitHub 源调用 `dsh run`,让随附 pnpm 获取并准备一个私有且不含依赖的 fixture(测试前置数据),然后在真实模型请求中观察已复制的 skill,并在不可变缓存中观察已准备的包装模块。
|
||||
聚焦测试会准备 skills 与 MCP metadata,证明生成包装模块不含 import,拒绝 Work IQ 风格的 OAuth 字段,映射 Expo 风格 HTTP 与 DataJunction 风格 stdio 及环境变量,并覆盖缺失变量。真实 Loader 测试通过已注册 builtin 挂载生成包装模块,经 `ctx.skills` 读取其 skill,移除 Loader 条目并观察提供方清理。CI 的构建入口验收会用锁定到 PR(Pull Request)head 的 GitHub 源调用 `dsh run`,通过作业作用域的 Git 配置认证私有 PR 仓库,让随附 pnpm 获取并准备其中不含依赖的 fixture(测试前置数据),然后在真实模型请求中观察已复制的 skill,并在不可变缓存中观察已准备的包装模块。
|
||||
|
||||
+2
-2
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-08-08-host-owned-git-repository-plugin-preparation.md
|
||||
2026-08-08-host-owned-git-repository-plugin-preparation.md: 45e84f9c8a89bb9d1eb7e4521634d16789dea2f0
|
||||
2026-08-08-host-owned-git-repository-plugin-preparation.zh.md: ba88d5bb351427118d55c357209b496b39c2eb98
|
||||
2026-08-08-host-owned-git-repository-plugin-preparation.md: 47410bf3c55455a971ec347eab4e8b37ea26c6a5
|
||||
2026-08-08-host-owned-git-repository-plugin-preparation.zh.md: 64c37543d34147c41fc7a362040c7ada8fde0652
|
||||
|
||||
+3
-2
@@ -18,7 +18,7 @@ The fixed authoring format now requires exact `scripts.prepack: "dsh-plugin-prep
|
||||
|
||||
`@deepseek-ai/dsh-repository-plugin` materializes short-lived POSIX and Windows command wrappers that invoke its own built `dsh-plugin-prepare` entry. `RepositoryCache` accepts caller-owned executable directories, resolves them absolutely, and prepends them to the credential-scrubbed lifecycle `PATH` passed to bundled pnpm. The command directory exists only for the installation transaction and is removed on success or failure. The repository remains trusted package-manager input: DSH supplies one command, but other lifecycle scripts and dependencies still execute under the existing trust contract.
|
||||
|
||||
The Node 24 consumer lane passes an exact source derived from the pull request head repository and SHA. Its built-entry acceptance launches the real `apps/cli/lib/bin.js run` command with a one-run patch selecting a `private: true`, dependency-free GitHub fixture. It requires the run to reach the mock LLM, finds the repository skill description in the actual model request, and verifies the generated wrapper and copied skill under the immutable DSH cache. The test fails if CI omits the exact source instead of silently skipping.
|
||||
The Node 24 consumer lane passes an exact source derived from the pull request head repository and SHA. Because that repository is private, the workflow writes a job-scoped Git configuration that uses the read-only job token for GitHub HTTPS and rewrites pnpm's SSH fallback to that authenticated transport. Its built-entry acceptance launches the real `apps/cli/lib/bin.js run` command with a one-run patch selecting a `private: true`, dependency-free GitHub fixture. It requires the run to reach the mock LLM, finds the repository skill description in the actual model request, and verifies the generated wrapper and copied skill under the immutable DSH cache. The test fails if CI omits the exact source instead of silently skipping.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
@@ -33,10 +33,11 @@ The Node 24 consumer lane passes an exact source derived from the pull request h
|
||||
## Consequences
|
||||
|
||||
- A repository author can commit the fixed `.dsh-plugin/package.json` and source assets to GitHub without publishing either the Plugin or its preparation helper to npm.
|
||||
- Private GitHub sources use the host's standard Git authentication. CI proves that path with a temporary read-only configuration rather than persistent runner credentials.
|
||||
- `prepack`, not `prepare`, is part of the pre-release authoring format. Invalid lifecycle metadata fails during source preparation or installed-package validation instead of producing an ambiguous partial format.
|
||||
- Exact source strings still identify immutable cache generations; a changed ref or source configuration selects another generation.
|
||||
- This repair does not expand the contribution surface: prepared repository Plugins still contribute only declared skills and common MCP definitions, while arbitrary package lifecycle code remains trusted installation code rather than a model-facing Cordis Plugin API.
|
||||
|
||||
## Testing
|
||||
|
||||
`packages/ui/app-boot/tests/repository-cache.spec.ts` runs a local Git subpath through bundled pnpm with an injected command directory and proves that visible environment survives while credential-shaped variables are scrubbed. `packages/cordis/repository-plugin/tests/repository-plugin.spec.ts` pins the exact `prepack` metadata and temporary command cleanup. `apps/cli/tests/github-repository-plugin.built.e2e.ts` is the product acceptance: fresh DSH home, exact live GitHub source, actual built `dsh run`, real headless composition, mock LLM request observation, and prepared cache inspection.
|
||||
`packages/ui/app-boot/tests/repository-cache.spec.ts` runs a local Git subpath through bundled pnpm with an injected command directory and proves that visible environment survives while credential-shaped variables are scrubbed. `packages/cordis/repository-plugin/tests/repository-plugin.spec.ts` pins the exact `prepack` metadata and temporary command cleanup. `examples/headless-agent/tests/keyless-smoke.e2e.ts` keeps the checked-in prepared fixture on that source contract. `apps/cli/tests/github-repository-plugin.built.e2e.ts` is the product acceptance: fresh DSH home, exact authenticated private GitHub source, actual built `dsh run`, real headless composition, mock LLM request observation, and prepared cache inspection.
|
||||
|
||||
+3
-2
@@ -18,7 +18,7 @@ repository 插件的创作契约依赖 `scripts.prepare: "dsh-plugin-prepare"`
|
||||
|
||||
`@deepseek-ai/dsh-repository-plugin` 会生成临时的 POSIX 和 Windows 命令包装脚本,用于调用其自有的已构建 `dsh-plugin-prepare` 入口。`RepositoryCache` 接受由调用方持有的可执行文件目录,将它们解析为绝对路径,再前置到传给随附 pnpm、已清除凭据的包生命周期 `PATH`。该命令目录仅存在于安装事务期间,无论成功还是失败都会被移除。仓库仍是受信任的包管理器输入:DSH 仅提供这一条命令,其他生命周期脚本和依赖仍会按既有信任契约执行。
|
||||
|
||||
Node 24 消费方 CI 任务会传入从 PR(Pull Request)head 仓库和 SHA 派生的精确源。其构建入口验收会启动真实的 `apps/cli/lib/bin.js run` 命令,并通过一个仅作用于当次运行的 patch 选择 `private: true`、不含依赖的 GitHub fixture。验收要求该次运行到达 mock LLM(大语言模型),在实际模型请求中找到 repository skill 描述,并验证不可变 DSH 缓存中的生成包装层和已复制 skill。如果 CI 遗漏精确源,测试会失败,而不是静默跳过。
|
||||
Node 24 消费方 CI 任务会传入从 PR(Pull Request)head 仓库和 SHA 派生的精确源。由于该仓库为私有仓库,工作流会写入一份作业作用域的 Git 配置,使用该作业的只读 token 对 GitHub HTTPS 连接进行认证,并将 pnpm 的 SSH 回退路径重写为这一已认证的传输方式。其构建入口验收会启动真实的 `apps/cli/lib/bin.js run` 命令,并通过一个仅作用于当次运行的 patch 选择 `private: true`、不含依赖的 GitHub fixture。验收要求该次运行到达 mock LLM(大语言模型),在实际模型请求中找到 repository skill 描述,并验证不可变 DSH 缓存中的生成包装层和已复制 skill。如果 CI 遗漏精确源,测试会失败,而不是静默跳过。
|
||||
|
||||
## 考虑过的替代方案
|
||||
|
||||
@@ -33,10 +33,11 @@ Node 24 消费方 CI 任务会传入从 PR(Pull Request)head 仓库和 SHA
|
||||
## 后果
|
||||
|
||||
- 仓库作者可以把修复后的 `.dsh-plugin/package.json` 和源资源提交到 GitHub,而无需把插件或其准备辅助程序发布到 NPM。
|
||||
- 私有 GitHub 源使用宿主的标准 Git 认证。CI 使用临时的只读配置而非运行器上的持久凭据来验证该路径。
|
||||
- 预发布创作格式使用 `prepack` 而不是 `prepare`。无效的生命周期元数据会在源码准备或已安装包校验阶段导致失败,而不会留下状态不明的半成品格式。
|
||||
- 精确源字符串仍标识不可变缓存 generation;改变 ref 或源配置会选择另一个 generation。
|
||||
- 本次修复不扩大贡献范围:已准备的 repository 插件仍只贡献已声明的 skills 和通用 MCP 定义,而任意包生命周期代码仍是受信任的安装代码,不是面向模型的 Cordis 插件 API。
|
||||
|
||||
## 测试
|
||||
|
||||
`packages/ui/app-boot/tests/repository-cache.spec.ts` 会用注入的命令目录通过随附 pnpm 运行本地 Git 子路径,并证明可见环境变量得以保留,而名称符合凭据模式的变量会被清除。`packages/cordis/repository-plugin/tests/repository-plugin.spec.ts` 锁定精确的 `prepack` 元数据和临时命令清理行为。`apps/cli/tests/github-repository-plugin.built.e2e.ts` 是产品验收测试:全新的 DSH 主目录、精确的真实 GitHub 源、实际构建产物的 `dsh run`、真实 headless 组合、mock LLM 请求观测,以及对已准备缓存的检查。
|
||||
`packages/ui/app-boot/tests/repository-cache.spec.ts` 会用注入的命令目录通过随附 pnpm 运行本地 Git 子路径,并证明可见环境变量得以保留,而名称符合凭据模式的变量会被清除。`packages/cordis/repository-plugin/tests/repository-plugin.spec.ts` 锁定精确的 `prepack` 元数据和临时命令清理行为。`examples/headless-agent/tests/keyless-smoke.e2e.ts` 使签入仓库的已准备 fixture 继续符合该源格式契约。`apps/cli/tests/github-repository-plugin.built.e2e.ts` 是产品验收测试:全新的 DSH 主目录、精确且经过认证的私有 GitHub 源、实际构建产物的 `dsh run`、真实 headless 组合、mock LLM 请求观测,以及对已准备缓存的检查。
|
||||
|
||||
@@ -242,6 +242,17 @@ jobs:
|
||||
if: vars.DSH_CI_FAILOVER == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]'
|
||||
run: pnpm --filter @deepseek-ai/dsh-frontend exec playwright install chromium
|
||||
|
||||
- name: Configure private GitHub repository Plugin access
|
||||
env:
|
||||
DSH_GITHUB_SOURCE_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
source_config="$RUNNER_TEMP/dsh-github-source.gitconfig"
|
||||
basic_auth=$(printf 'x-access-token:%s' "$DSH_GITHUB_SOURCE_TOKEN" | base64 | tr -d '\n')
|
||||
git config --file "$source_config" url.https://github.com/.insteadOf git@github.com:
|
||||
git config --file "$source_config" --add url.https://github.com/.insteadOf ssh://git@github.com/
|
||||
git config --file "$source_config" http.https://github.com/.extraheader "AUTHORIZATION: basic $basic_auth"
|
||||
echo "GIT_CONFIG_GLOBAL=$source_config" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Run compatibility, snapshot, and artifact gates
|
||||
run: pnpm run check:ci:consumers
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/self-modification/repository-plugin/README.md
|
||||
README.md: e0b45dc5fd40b5d1005598ae100d23ca7d0b6ec9
|
||||
README.zh.md: 30f200d2b7188d88e4a5e4e566cf3394f799933a
|
||||
README.md: 23c4cc0dceaf0692b7ef5067f9170b8c6b311cc0
|
||||
README.zh.md: db2f3e5a5c8915836d97177f797411e17e70441c
|
||||
|
||||
@@ -40,6 +40,8 @@ The shipped `dsh-base` bundle every profile starts from contains an empty `repos
|
||||
|
||||
Each source must use `github:owner/repository#<ref>`. Omitting `&path:` selects `/.dsh-plugin`; an explicit path is absolute within the repository and must end in `.dsh-plugin`. A commit ref gives the clearest immutable identity, while tags and branches remain accepted exact config values. `cacheDir` may override the default `$DSH_HOME/cache/repository-plugins` cache root.
|
||||
|
||||
Git transport uses the host's ordinary Git authentication. Public repositories need no credentials; private sources require a read-only credential or SSH agent that can read the selected repository. DSH removes credential-shaped environment variables before package lifecycles, so configure Git itself, such as through a credential helper or job-scoped Git config, instead of expecting an exported token variable to cross that boundary. Repository lifecycle code is trusted and can invoke Git, so use the narrowest repository-scoped credential available.
|
||||
|
||||
Long-lived surfaces watch both `cordis.patch.yml` layers through Cordis HMR. A valid source-list change installs and swaps the complete repository Plugin generation; a failed fetch, prepare, import, or Plugin application keeps the last good tree and broadcasts `hmr/config-update-failed(filename, error)`. One-shot runs read the layers only at startup, and a `--patch` overlay is never watched. An identical source string permanently reuses its prepared cache entry, so selecting changed code requires a ref, path, or other source-config change. App integration rationale: [config-only repository Plugins Agent Note](../../../.agents/notes/implemented/feature/2026-07-30-config-only-repository-plugins.md).
|
||||
|
||||
## Preparation
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
|
||||
每个源都必须采用 `github:owner/repository#<ref>`。省略 `&path:` 时选择 `/.dsh-plugin`;显式路径是仓库内的绝对路径,并且必须以 `.dsh-plugin` 结尾。commit ref 提供最清晰的不可变身份;tag 和 branch 仍可作为精确配置值使用。`cacheDir` 可覆盖默认缓存根 `$DSH_HOME/cache/repository-plugins`。
|
||||
|
||||
Git 传输使用宿主的常规 Git 认证。公共仓库无需凭据;私有源需要可读取所选仓库的只读凭据或 SSH agent。DSH 会在包生命周期运行前移除名称符合凭据模式的环境变量,因此请配置 Git 本身,例如使用 Git 凭据辅助工具或作业作用域的 Git 配置,而不要指望已导出的 token 变量跨越该边界。仓库生命周期代码受信任且可以调用 Git,因此请使用作用域最窄且仅限所选仓库的凭据。
|
||||
|
||||
长期运行的 surface 通过 Cordis HMR(热模块替换)监视两个 `cordis.patch.yml` 层。有效的源列表变更会安装并替换整套 repository Plugin generation;拉取、准备、导入或插件应用失败时,最后一个可用树保持运行,并广播 `hmr/config-update-failed(filename, error)`。一次性运行只在启动时读取这些层,`--patch` overlay 则从不被监视。相同的源字符串会永久复用其已准备缓存条目,因此必须改变 ref、路径或其他源配置,才能选择发生变化的代码。应用集成依据见[仅凭配置接入 repository Plugin 的 Agent Note](../../../.agents/notes/implemented/feature/2026-07-30-config-only-repository-plugins.md)。
|
||||
|
||||
## 准备阶段
|
||||
|
||||
Reference in New Issue
Block a user