5 Commits
v2 ... v4
Author SHA1 Message Date
dsh-mulm 973ed6cb99 Merge pull request 'fix(cleanup): per-run 缓存清理改容器 root 执行(PLAT-014,升 v4 前置)' (#2) from task/PLAT-014-per-run-cleanup-root into main 2026-08-31 13:05:17 +00:00
zcode-mulm e2b81e7ee6 fix(cleanup): per-run 缓存清理改容器 root 执行(PLAT-014,坑 #18 同族)
宿主 08-30 治理后为非 root gitea-runner,rm 容器 root 属主缓存文件必 EACCES
(Seabed run 917 两 attempt 测试全绿、清理步必死)。复用 job 已拉的 node-image
find -mindepth 1 -delete + 宿主 rmdir 自建目录。v3 不动;合并后打 v4,
per-run 调用方(Seabed)升 @v4,fixed 调用方(Reef)可留 @v3。
2026-08-31 20:52:23 +08:00
钱木 0e132f63af runner contract: TN-only tn-build-runner v3.3.1 (non-root, capacity=1); templates note non-root user 2026-08-30 22:00:15 +08:00
zcode-mulm 12b01c6cc5 Merge pull request 'templates v3: checkout back on actions-checkout@v4 + drop orphan reusable/checkout.yml' (#1) from task/v3-checkout-actions-checkout into main 2026-08-29 13:38:20 +00:00
zcode-mulm ff3dd6ce12 templates v3: checkout back on mu-ref/actions-checkout@v4 + drop orphan reusable/checkout.yml
P1-10 completed the JS-action checkout migration on 2026-08-27 09:39
(est/Est-Infra@57cc9f7) after tn gained a host node runtime (v22).
The 12:07 consolidation founded this repo on the P1-7 host-clone
fallback lineage instead, deleting the migrated copies at 12:25 —
live pipelines have run host git clone with stale 'tn does not
install node' headers ever since.

v3 restores the JS path in both templates, keeps the fallback's
HEAD==SHA assertion as an explicit postcondition step (guard is not
downgraded), and deletes reusable/checkout.yml which had zero
callers (reusable workflows cannot nest; its guard now lives inline).

Verified by a Seabed task-branch probe run before tagging v3
(coordination task M1-423, issue #32).
2026-08-29 21:31:41 +08:00
4 changed files with 58 additions and 71 deletions
-38
View File
@@ -1,38 +0,0 @@
# Unified checkout for host-mode jobs (build-docker): mu-ref/actions-checkout
# (local JS-action mirror) with the Caddy CA and a HEAD==SHA guard.
#
# Requirements (verified 2026-08-27 on Gitea 1.27.2): the runner host must
# have a node runtime for JS actions (tn does), and the action repos must be
# anonymously readable (public). NOT usable from container jobs whose image
# lacks node — those callers keep a host `git clone` step instead.
name: reusable-checkout
on:
workflow_call:
inputs:
fetch-depth:
required: false
type: number
default: 1
verify-sha:
required: false
type: string
default: "yes"
description: "Empty disables; otherwise fail unless HEAD equals the triggering commit (boolean inputs are NOT reliable through workflow_call with:)"
jobs:
checkout:
runs-on: build-docker
steps:
- name: checkout (mu-ref/actions-checkout)
uses: https://git.moneywood.site/mu-ref/actions-checkout@v4
env:
GIT_SSL_CAINFO: /usr/local/share/ca-certificates/caddy-root-ca.crt
with:
fetch-depth: ${{ inputs.fetch-depth }}
- name: verify HEAD equals triggering commit
if: inputs.verify-sha != ''
run: |
set -eu
test "$(git rev-parse HEAD)" = "${GITHUB_SHA}"
+29 -18
View File
@@ -3,15 +3,17 @@
# P1-7 verification status (2026-08-27, Gitea 1.27.2):
# - reusable workflow calls verified working (1.27.2 probe + this workflow's
# selftest caller: .gitea/workflows/selftest.yml)
# - checkout uses host git clone (NOT mu-ref/actions-checkout): act_runner
# runs JS actions with a host node runtime, which tn does not install
# the JS-action path is unavailable for host jobs until node is installed
# on the runner host (coordination review fallback decision)
# - no actions/cache layer for the same reason; the persistent /data/cache/ci
# directory is the primary (and only) cache layer
# - checkout via mu-ref/actions-checkout@v4 (JS action) + explicit
# HEAD==SHA postcondition: tn has a host node runtime (v22, installed
# 2026-08-27). v3 restores the P1-10 JS path — the 2026-08-27 12:07
# consolidation had based this repo on the P1-7 host-clone fallback
# lineage and dropped the completed migration (est/Est-Infra@57cc9f7);
# the action repo must stay PUBLIC (act clones it anonymously)
# - no actions/cache layer; the persistent /data/cache/ci directory is
# the primary (and only) cache layer
#
# Conventions proven on the business-repo pipelines:
# - runs-on: build-docker (host job, root) + docker run for the toolchain
# - runs-on: build-docker (host job, NON-ROOT user gitea-runner) + docker run for the toolchain
# - CA: GIT_SSL_CAINFO (host git) + SSL_CERT_FILE/NODE_EXTRA_CA_CERTS (container;
# helper images have their apt/apk sources baked in, so replacing the public
# trust store is safe here — see playbook pitfall 13)
@@ -73,18 +75,14 @@ jobs:
quality:
runs-on: build-docker
steps:
- name: checkout (host git; JS actions need a host node runtime)
- name: checkout (mu-ref/actions-checkout; tn host node runs JS actions)
uses: https://git.moneywood.site/mu-ref/actions-checkout@v4
env:
CI_ACTOR: ${{ github.actor }}
CI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_SSL_CAINFO: /usr/local/share/ca-certificates/caddy-root-ca.crt
- name: verify HEAD equals triggering commit
run: |
set -eu
export GIT_SSL_CAINFO=/usr/local/share/ca-certificates/caddy-root-ca.crt
git config --global credential.helper \
'!f() { echo "username=${CI_ACTOR}"; echo "password=${CI_TOKEN}"; }; f'
git config --global --add safe.directory '*'
timeout 120 git clone --depth 1 --branch "${GITHUB_REF_NAME}" \
"https://git.moneywood.site/${GITHUB_REPOSITORY}.git" .
test "$(git rev-parse HEAD)" = "${GITHUB_SHA}"
- name: authenticate to gitea registry (private helper image pulls)
@@ -145,6 +143,19 @@ jobs:
$env_args \
"${{ inputs.node-image }}" sh -euxc '${{ inputs.install-command }} && ${{ inputs.quality-command }}'
- name: cleanup per-run cache dir
# PLAT-014: the helper container writes root-owned files (tsx workers,
# playwright, compile caches) into the per-run cache mount; the host job
# runs as non-root gitea-runner since the 2026-08-30 runner governance,
# so a host-side rm -rf fails with EACCES and reds the job (playbook #18
# family). Clean as container root using the image this job already
# pulled, then rmdir the host-created directory itself.
- name: cleanup per-run cache dir (container root)
if: always() && inputs.cache-mode == 'per-run'
run: rm -rf -- "${TOOL_CACHE_DIR:-}"
run: |
set -eu
[ -n "${TOOL_CACHE_DIR:-}" ] || exit 0
docker run --rm \
-v "${TOOL_CACHE_DIR}":/cleanup-root \
"${{ inputs.node-image }}" \
find /cleanup-root -mindepth 1 -delete
rmdir "${TOOL_CACHE_DIR}"
@@ -3,8 +3,9 @@
# P1-7 verification status (2026-08-27, Gitea 1.27.2):
# - reusable workflow calls verified working (selftest caller:
# .gitea/workflows/selftest.yml)
# - checkout uses host git clone (JS actions need a host node runtime that
# tn does not install — see reusable/node-quality.yml header)
# - checkout via mu-ref/actions-checkout@v4 + HEAD==SHA postcondition
# (tn host node v22; v3 restoration history in reusable/node-quality.yml
# header; the action repo must stay PUBLIC — act clones it anonymously)
# - registry identity is the triggering actor (github.actor), credentials
# flow exclusively through the REGISTRY_PASSWORD secret (no hardcoded
# usernames — coordination review pitfall 21)
@@ -106,18 +107,14 @@ jobs:
build:
runs-on: build-docker
steps:
- name: checkout (host git; JS actions need a host node runtime)
- name: checkout (mu-ref/actions-checkout; tn host node runs JS actions)
uses: https://git.moneywood.site/mu-ref/actions-checkout@v4
env:
CI_ACTOR: ${{ github.actor }}
CI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_SSL_CAINFO: /usr/local/share/ca-certificates/caddy-root-ca.crt
- name: verify HEAD equals triggering commit
run: |
set -eu
export GIT_SSL_CAINFO=/usr/local/share/ca-certificates/caddy-root-ca.crt
git config --global credential.helper \
'!f() { echo "username=${CI_ACTOR}"; echo "password=${CI_TOKEN}"; }; f'
git config --global --add safe.directory '*'
timeout 120 git clone --depth 1 --branch "${GITHUB_REF_NAME}" \
"https://git.moneywood.site/${GITHUB_REPOSITORY}.git" .
test "$(git rev-parse HEAD)" = "${GITHUB_SHA}"
- name: authenticate to gitea registry
@@ -308,6 +305,15 @@ jobs:
} >>"${GITHUB_STEP_SUMMARY:-/dev/stdout}"
cat "$digest_file"
- name: cleanup per-run cache dir
# PLAT-014: same ownership fix as node-quality — see the comment there
# (host non-root runner cannot rm container-root-owned cache files).
- name: cleanup per-run cache dir (container root)
if: always() && inputs.build-command != '' && inputs.cache-mode == 'per-run'
run: rm -rf -- "${TOOL_CACHE_DIR:-}"
run: |
set -eu
[ -n "${TOOL_CACHE_DIR:-}" ] || exit 0
docker run --rm \
-v "${TOOL_CACHE_DIR}":/cleanup-root \
"${{ inputs.node-image }}" \
find /cleanup-root -mindepth 1 -delete
rmdir "${TOOL_CACHE_DIR}"
+10 -2
View File
@@ -7,8 +7,7 @@
| 路径 | 用途 |
|---|---|
| `.gitea/workflows/reusable/checkout.yml` | 统一 checkoutmu-ref/actions-checkout + CA + HEAD==SHA 守卫;host job 专用 |
| `.gitea/workflows/reusable/node-quality.yml` | node 质量门(digest helper、持久缓存、rank 源序) |
| `.gitea/workflows/reusable/node-quality.yml` | node 质量门(digest helper、持久缓存、rank 源序、actions-checkout checkout |
| `.gitea/workflows/reusable/oci-build-push-verify.yml` | 镜像构建+推送+verify-command 校验链 |
| `tools/ci/source-policy.sh` | 唯一选源实现(公司级 canonical) |
| `tools/ci/helper/REGISTER.md` | ci-node-* helper 镜像 digest 注册 |
@@ -34,4 +33,13 @@ jobs:
## 迁移与同步
- 2026-08-27 定稿:曾按初版决策试建 est/ci-workflows,因 est org 私有闸门不可跨仓调用而删除(用户改批 mu-ref 宿主);同日自 est/Est-Infra 上移 tools/ci。
- 2026-08-31 v4PLAT-014Issue #75):per-run 缓存清理步改容器 root 执行(node-image `find /cleanup-root -mindepth 1 -delete` + 宿主 `rmdir`)——08-30 非 root runner 治理后宿主 rm 撞容器 root 属主文件必 EACCES(坑 #18 同族,Seabed run 917 两次复现);v3 保持不动,per-run 调用方(est/Seabed)应升 @v4fixed 模式调用方(est/Reef)无清理步可留 @v3
- 2026-08-29 v3:模板 checkout 恢复 mu-ref/actions-checkout@v4JS action+ HEAD==SHA postcondition——P1-10 的 JS 迁移(est/Est-Infra@57cc9f708-27 09:39)在 08-27 12:07 上移建仓时被回退为 P1-7 host-clone fallback 血统,v3 恢复并经 Seabed 私仓探针验证;无调用方的孤儿模板 `reusable/checkout.yml` 删除(reusable 不可嵌套调用,其守卫已内联进两个模板)。
- helper Dockerfile 的可复现 bake 与 ops 巡检脚本仍属项目级(Est-Infra / gitea-host-setup)。
## Runner contract2026-08-30 定死)
- **唯一 runnerTN `tn-build-runner`gitea-runner v3.3.1,注册号 est org 范围)**TS 只承载 Gitea/Registry,无任何 runner0.6.1/act_runner 已全部清除,禁止回潮。
- 服务:TN `gitea-runner.service`**非 root 用户 `gitea-runner`**docker 组,host docker socket 经组权限),capacity=1,工作区 `/data/ci-workspace`,缓存 `/data/actcache``/data/cache/ci`
- Labels(均 host 模式):`build-docker`(存量 workflow 兼容)与 `est-tn-v3`(新 workflow 请用这个带版本的)。
- 注册令牌:注册完成后即重置;凭据 `/opt/act-runner/.runner` 0600,目录 0700。