Skip to content

Commit db91759

Browse files
committed
fix: isolate release CI environment
1 parent e866ba2 commit db91759

7 files changed

Lines changed: 84 additions & 14 deletions

File tree

.github/workflows/codex-bootstrap-release.yml

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,16 @@ jobs:
139139
--home "${app_home}" \
140140
--codex-home "${app_home}/.codex"
141141
142+
- name: Create a private release-artifact parent
143+
id: release-output
144+
run: |
145+
set -Eeuo pipefail
146+
release_parent=$(mktemp -d -- "${RUNNER_TEMP}/drclaw-release-artifacts.XXXXXXXX")
147+
chmod 700 -- "${release_parent}"
148+
test -d "${release_parent}"
149+
test ! -L "${release_parent}"
150+
printf 'parent=%s\n' "${release_parent}" >> "${GITHUB_OUTPUT}"
151+
142152
- name: Build the validated online and offline release kit
143153
env:
144154
RELEASE_TAG: ${{ github.ref_name }}
@@ -149,13 +159,13 @@ jobs:
149159
--repo-root "${GITHUB_WORKSPACE}" \
150160
--tag "${RELEASE_TAG}" \
151161
--expected-commit "${release_commit}" \
152-
--output "${RUNNER_TEMP}/release-artifacts"
162+
--output "${{ steps.release-output.outputs.parent }}/release-artifacts"
153163
154164
- name: Transfer validated release artifacts
155165
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
156166
with:
157167
name: validated-codex-bootstrap-release
158-
path: ${{ runner.temp }}/release-artifacts/
168+
path: ${{ steps.release-output.outputs.parent }}/release-artifacts/
159169
if-no-files-found: error
160170
retention-days: 7
161171

@@ -280,7 +290,30 @@ jobs:
280290
remote_home="${RUNNER_TEMP}/drclaw-arm64-remote-preview"
281291
mkdir -m 700 "${remote_home}"
282292
release_commit=$(git rev-parse "${RELEASE_TAG}^{commit}")
283-
bash bootstrap/codex/remote-install.sh \
293+
env \
294+
-u DRCLAW_CA_BUNDLE \
295+
-u SSL_CERT_FILE \
296+
-u SSL_CERT_DIR \
297+
-u REQUESTS_CA_BUNDLE \
298+
-u CURL_CA_BUNDLE \
299+
-u AWS_CA_BUNDLE \
300+
-u GIT_SSL_CAINFO \
301+
-u PIP_CERT \
302+
-u NODE_EXTRA_CA_CERTS \
303+
-u npm_config_cafile \
304+
-u NPM_CONFIG_CAFILE \
305+
-u ALL_PROXY \
306+
-u all_proxy \
307+
-u PIP_INDEX_URL \
308+
-u PIP_EXTRA_INDEX_URL \
309+
-u PIP_TRUSTED_HOST \
310+
-u NPM_CONFIG_REGISTRY \
311+
-u npm_config_registry \
312+
-u NPM_CONFIG_PROXY \
313+
-u npm_config_proxy \
314+
-u NPM_CONFIG_HTTPS_PROXY \
315+
-u npm_config_https_proxy \
316+
bash bootstrap/codex/remote-install.sh \
284317
--repo-url "${GITHUB_WORKSPACE}" \
285318
--ref "${release_commit}" \
286319
--home "${remote_home}" \

bootstrap/codex/README.zh-CN.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969

7070
必须以最终实际运行 Codex 的非 root Unix 用户执行本方案;管理员应先 `sudo -iu <USER>`,再 clone 和安装。`--home` 只用于同一用户的隔离测试,不是跨用户 provision 开关;安装器会拒绝 root、owner 不匹配、受保护系统目录后代和隐式符号链接写穿。`$CODEX_HOME` 必须是 `$HOME` 内的专用目录;新建权限为 `0700`,已有目录及其自 HOME 起的现存祖先不得由其他主体替换或写入。唯一例外是上一表所述、经过 POSIX ACL 完整验证的 root-owned Delta HOME;例外不会向 HOME 以下受管目录传播。
7171

72-
生产部署必须由维护者批准一个 immutable Git tag 或完整 commit SHA。当前 manifest 固定到 `codex-bootstrap-v0.2.5``audited_base_commit` 只是编写本方案时检查的起始树,不是可部署 revision。实际安装还必须把该 annotated tag 与 release provenance 中的完整 commit SHA 绑定;不要部署 moving branch,也不要移动既有 tag。
72+
生产部署必须由维护者批准一个 immutable Git tag 或完整 commit SHA。当前 manifest 固定到 `codex-bootstrap-v0.2.6``audited_base_commit` 只是编写本方案时检查的起始树,不是可部署 revision。实际安装还必须把该 annotated tag 与 release provenance 中的完整 commit SHA 绑定;不要部署 moving branch,也不要移动既有 tag。
7373

7474
## 四、NCSA Delta:先建立交互连接
7575

@@ -150,7 +150,7 @@ bash bootstrap/codex/remote-install.sh --help
150150
在 release tag 所在的 clean checkout 上生成一个新的、不可覆盖的目录:
151151

152152
```bash
153-
release_tag=codex-bootstrap-v0.2.5
153+
release_tag=codex-bootstrap-v0.2.6
154154
release_commit=$(git rev-parse "${release_tag}^{commit}")
155155
kit_parent="$PWD/../drclaw-release-output-private"
156156
(umask 077; mkdir "$kit_parent")
@@ -172,7 +172,7 @@ builder 只接受与 manifest、HEAD 和完整 SHA 一致的 annotated tag;拒
172172
完整搬运该目录到新服务器后,只需一条离线命令,不必先从 bundle 手动提取脚本:
173173

174174
```bash
175-
bash /path/to/drclaw-codex-bootstrap-v0.2.5-offline/install.sh --full
175+
bash /path/to/drclaw-codex-bootstrap-v0.2.6-offline/install.sh --full
176176
```
177177

178178
wrapper 会先拒绝目录中的任何额外 entry、symlink、缺失文件、owner/mode 异常或 checksum inventory 漂移,并验证每个 payload,再把同目录 bundle 交给现有远程安装器;tag object 与 peeled commit 两个身份也同时固定。Git bundle 为了保留发布身份与 commit 原始 SHA 必须携带其可达 Git 历史,因此 builder 会扫描**全部可达历史路径,以及所有可达 blob、commit 和 tag payload**,而不只检查当前 tree;允许的 community gitlink 只记录路径与 object ID,bundle/archive 都不携带其仓库内容。内部 checksum 可证明搬运完整性;抵抗“payload 与 checksum 同时被替换”仍需通过独立可信渠道保存并核对 provenance sidecar 的 SHA256。

bootstrap/codex/STATUS-2026-08-19.zh-CN.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
初始记录:2026-08-19(America/Chicago)
44
最近续作:2026-08-25(America/New_York)
5-
状态:**v0.2.2 的本地验收和 tag 保持不变。`codex-bootstrap-v0.2.3``codex-bootstrap-v0.2.4` 均已不可变推送,但都没有发布 Release;当前候选是新的、不可变的 `codex-bootstrap-v0.2.5`,尚未创建或推送。**
5+
状态:**v0.2.2 的本地验收和 tag 保持不变。`codex-bootstrap-v0.2.3``codex-bootstrap-v0.2.4``codex-bootstrap-v0.2.5` 均已不可变推送,但都没有发布 Release;当前候选是新的 `codex-bootstrap-v0.2.6`,尚未创建或推送。**
66

77
这份文件记录本轮工作的真实边界:已经做了什么、验证到了哪里、哪些方案被拒绝、现在还有哪些问题、恢复时应从哪里继续。第八节以前保留 2026-08-19 的历史暂停证据;本节以下的 2026-08-20 与 2026-08-25 更新优先于其中已经解决的旧问题。它不替代正式使用文档 [`README.zh-CN.md`](README.zh-CN.md) 和应用安装文档 [`APP_INSTALL.zh-CN.md`](APP_INSTALL.zh-CN.md)
88

@@ -16,7 +16,7 @@
1616

1717
在将 tag 交给 GitHub Actions 前,发现并修复了一项**测试环境**闭环:`verify_live_delta_identity()` 正确拒绝一个不存在的 `/usr/bin/scontrol`,但其单测曾在没有 Slurm 的 generic CI host 上模拟该不存在路径,因而会被正确的 executable trust gate 拒绝。测试现在以真实 root-owned executable 模拟已验证的 command path;生产端的 Delta 身份检查没有放宽。release workflow 同时在三个 Linux validation job 中显式安装 `acl`,确保 ACL 安全合同的测试不依赖 runner 的偶然预装状态。Python 由 `actions/setup-python` 提供,避免使用系统 Python 缺少 `ensurepip` 的情况。
1818

19-
`codex-bootstrap-v0.2.3` 的 GitHub workflow `#32888891747` 已保留为失败证据:所有 validation job 都在 `actions/checkout` 中发现 `community-tools/autoresearch` 的 gitlink 没有 `.gitmodules` URL 而失败,因此没有执行代码测试,publish job 被安全跳过。已从历史提交 `de72da9991bbbf239546152a9ac6e15c56338228` 恢复两个原始、默认不初始化的社区 gitlink 映射,并让 release-kit 在本地要求 `.gitmodules` 路径与 manifest allowlist 精确一致。`codex-bootstrap-v0.2.4` 的 GitHub workflow `#32891263604` 已证明 checkout 与 Python 3.9–3.13 matrix 恢复正常,但 x86_64 与 native ARM64 的 Web smoke 均未完成,publish 安全跳过。为让隔离 Web smoke 不依赖 Actions checkout 是否 materialize tag ref,v0.2.5 仅使用已验证的 peeled full commit SHA 建立临时 checkout;在 app doctor 前还先安装完整的受管 Codex/router baseline。修复不能移动 v0.2.3 或 v0.2.4;因此 manifest/app bundle version 与 immutable release ref 前移到 `0.2.5`。在创建 annotated `codex-bootstrap-v0.2.5` 前,仍必须完成:干净源码测试、最终 release kit、隔离 fresh/latest-Codex 合同和 source 的 GitHub push;tag 推送后还必须等待 x86_64、Python matrix 与 native ARM64 workflow 绿灯,才允许 workflow publish job 创建 GitHub Release。若任一项失败,保留对应 tag 不动,修复后创建更高的新 tag。
19+
`codex-bootstrap-v0.2.3` 的 GitHub workflow `#32888891747` 已保留为失败证据:所有 validation job 都在 `actions/checkout` 中发现 `community-tools/autoresearch` 的 gitlink 没有 `.gitmodules` URL 而失败,因此没有执行代码测试,publish job 被安全跳过。已从历史提交 `de72da9991bbbf239546152a9ac6e15c56338228` 恢复两个原始、默认不初始化的社区 gitlink 映射,并让 release-kit 在本地要求 `.gitmodules` 路径与 manifest allowlist 精确一致。`codex-bootstrap-v0.2.4` 的 GitHub workflow `#32891263604` 已证明 checkout 与 Python 3.9–3.13 matrix 恢复正常,但 x86_64 与 native ARM64 的 Web smoke 均未完成,publish 安全跳过。`codex-bootstrap-v0.2.5` 的 workflow `#32893368825` 已证明 x86_64 的核心与完整 Web doctor,以及 Python 3.9–3.13 matrix 都通过;但 release-kit 正确拒绝 GitHub Actions 组可写的 `RUNNER_TEMP` 作为输出父目录,而 ARM64 预览正确拒绝 Actions 注入的 `PIP_INDEX_URL` 包镜像环境。两项都是 CI 调用边界问题,不放宽生产安全合同:v0.2.6 改为在 `RUNNER_TEMP` 下原子创建 `0700` 私有输出父目录,并仅为 ARM64 的隔离 dry-run 清除 Actions 注入的包镜像/额外 CA 变量。修复不能移动 v0.2.3、v0.2.4 或 v0.2.5;因此 manifest/app bundle version 与 immutable release ref 前移到 `0.2.6`。在创建 annotated `codex-bootstrap-v0.2.6` 前,仍必须完成:干净源码测试、最终 release kit、隔离 fresh/latest-Codex 合同和 source 的 GitHub push;tag 推送后还必须等待 x86_64、Python matrix 与 native ARM64 workflow 绿灯,才允许 workflow publish job 创建 GitHub Release。若任一项失败,保留对应 tag 不动,修复后创建更高的新 tag。
2020

2121
### 0.1 2026-08-25 最新官方 Codex 无人值守合同
2222

@@ -78,7 +78,7 @@
7878
- skill runtime inventory:24 个 skill 仍含 Claude-specific 提示、33 个提到 MCP,source installed/discoverable 不等于外部 provider/credential 已激活;
7979
- isolated app service 使用 `service=none`,因此 doctor 正确提示需要在真实 login HOME 下由批准的 supervisor 启动。
8080

81-
`v0.2.2` 是完整的历史验收基线;`v0.2.3` 是保留的 checkout-failure 证据,`v0.2.4` 是保留的 Web smoke failure 证据。为使 CI 的隔离 checkout 与完整 app doctor 合同确定化,本次会从干净源码创建新的 `v0.2.5` release。绝不移动、删除或复用 `v0.1.0``v0.2.0``v0.2.1``v0.2.2``v0.2.3``v0.2.4` tags;未来只可继续创建更高的新 tag。
81+
`v0.2.2` 是完整的历史验收基线;`v0.2.3` 是保留的 checkout-failure 证据,`v0.2.4` 是保留的 Web smoke failure 证据`v0.2.5`CI 边界 failure 证据。为使 release-kit 输出父目录和 ARM64 远程预览与这些 fail-closed 合同兼容,本次会从干净源码创建新的 `v0.2.6` release。绝不移动、删除或复用 `v0.1.0``v0.2.0``v0.2.1``v0.2.2``v0.2.3``v0.2.4``v0.2.5` tags;未来只可继续创建更高的新 tag。
8282

8383
## 一、暂停时的准确结论
8484

bootstrap/codex/app-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"schema_version": 1,
3-
"bundle_version": "0.2.5",
3+
"bundle_version": "0.2.6",
44
"application": {
55
"name": "Dr. Claw Web",
66
"package_name": "dr-claw",

bootstrap/codex/manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"schema_version": 1,
3-
"bundle_version": "0.2.5",
3+
"bundle_version": "0.2.6",
44
"audited_at": "2026-08-19",
55
"baseline": {
66
"repository": "https://github.com/OpenLAIR/dr-claw.git",
77
"audited_base_commit": "4b3575641b63f8e09a9539b23c2be4f45f5d0317",
8-
"bundle_release_ref": "codex-bootstrap-v0.2.5",
9-
"production_revision_policy": "Deploy the exact codex-bootstrap-v0.2.5 tag together with its full commit SHA from the signed-off release provenance. The audited_base_commit records the starting tree inspected while this bundle was authored; it is not the deployable bundle revision. Never deploy a moving branch as a reproducible baseline."
8+
"bundle_release_ref": "codex-bootstrap-v0.2.6",
9+
"production_revision_policy": "Deploy the exact codex-bootstrap-v0.2.6 tag together with its full commit SHA from the signed-off release provenance. The audited_base_commit records the starting tree inspected while this bundle was authored; it is not the deployable bundle revision. Never deploy a moving branch as a reproducible baseline."
1010
},
1111
"requirements": {
1212
"python": ">=3.9",

bootstrap/codex/tests/test_install_app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def _complete_install(self, **overrides):
361361

362362
def test_manifest_pins_official_node_artifacts(self):
363363
node = self.manifest["node"]
364-
self.assertEqual(self.manifest["bundle_version"], "0.2.5")
364+
self.assertEqual(self.manifest["bundle_version"], "0.2.6")
365365
self.assertEqual(
366366
self.manifest["runtime_receipt"],
367367
{"schema_version": 1, "filename": ".drclaw-node-runtime.json"},

bootstrap/codex/tests/test_remote_install.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,20 @@ def test_release_workflow_run_blocks_have_valid_shell_and_heredocs(self) -> None
992992
)
993993

994994
workflow_text = workflow.read_text(encoding="utf-8")
995+
self.assertIn('id: release-output', workflow_text)
996+
self.assertIn(
997+
'release_parent=$(mktemp -d -- "${RUNNER_TEMP}/drclaw-release-artifacts.XXXXXXXX")',
998+
workflow_text,
999+
)
1000+
self.assertIn('chmod 700 -- "${release_parent}"', workflow_text)
1001+
self.assertIn(
1002+
'--output "${{ steps.release-output.outputs.parent }}/release-artifacts"',
1003+
workflow_text,
1004+
)
1005+
self.assertIn(
1006+
'path: ${{ steps.release-output.outputs.parent }}/release-artifacts/',
1007+
workflow_text,
1008+
)
9951009
self.assertNotIn(
9961010
'git -C "${app_home}/release" checkout --quiet --detach "${RELEASE_TAG}"',
9971011
workflow_text,
@@ -1009,6 +1023,29 @@ def test_release_workflow_run_blocks_have_valid_shell_and_heredocs(self) -> None
10091023
self.assertLess(script.index('bootstrap/codex/bootstrap.py"'), script.index('install_app.py"'))
10101024
self.assertGreaterEqual(script.count('install_app.py"'), 2)
10111025

1026+
arm_blocks = [
1027+
script
1028+
for _, script in scripts
1029+
if 'remote_home="${RUNNER_TEMP}/drclaw-arm64-remote-preview"' in script
1030+
]
1031+
self.assertEqual(len(arm_blocks), 1)
1032+
arm_block = arm_blocks[0]
1033+
for variable in (
1034+
"DRCLAW_CA_BUNDLE",
1035+
"SSL_CERT_FILE",
1036+
"PIP_INDEX_URL",
1037+
"PIP_EXTRA_INDEX_URL",
1038+
"PIP_TRUSTED_HOST",
1039+
"NPM_CONFIG_REGISTRY",
1040+
"npm_config_registry",
1041+
):
1042+
with self.subTest(environment_variable=variable):
1043+
self.assertIn(f"-u {variable}", arm_block)
1044+
self.assertLess(
1045+
arm_block.index("-u PIP_INDEX_URL"),
1046+
arm_block.index("bash bootstrap/codex/remote-install.sh"),
1047+
)
1048+
10121049
def test_manifest_pinned_optional_gitlink_remains_uninitialized(self) -> None:
10131050
tag = "drclaw-codex-gitlink-v1"
10141051
repository, commit = self.build_release(

0 commit comments

Comments
 (0)