Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
973ed6cb99 | ||
|
|
e2b81e7ee6 | ||
|
|
0e132f63af | ||
|
|
12b01c6cc5 | ||
|
|
ff3dd6ce12 | ||
|
|
1be2f0f072 | ||
|
|
7d8d9d8a2a |
@@ -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: boolean
|
|
||||||
default: true
|
|
||||||
description: "Fail unless the checked-out HEAD equals the triggering commit"
|
|
||||||
|
|
||||||
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}"
|
|
||||||
@@ -3,15 +3,17 @@
|
|||||||
# P1-7 verification status (2026-08-27, Gitea 1.27.2):
|
# P1-7 verification status (2026-08-27, Gitea 1.27.2):
|
||||||
# - reusable workflow calls verified working (1.27.2 probe + this workflow's
|
# - reusable workflow calls verified working (1.27.2 probe + this workflow's
|
||||||
# selftest caller: .gitea/workflows/selftest.yml)
|
# selftest caller: .gitea/workflows/selftest.yml)
|
||||||
# - checkout uses host git clone (NOT mu-ref/actions-checkout): act_runner
|
# - checkout via mu-ref/actions-checkout@v4 (JS action) + explicit
|
||||||
# runs JS actions with a host node runtime, which tn does not install —
|
# HEAD==SHA postcondition: tn has a host node runtime (v22, installed
|
||||||
# the JS-action path is unavailable for host jobs until node is installed
|
# 2026-08-27). v3 restores the P1-10 JS path — the 2026-08-27 12:07
|
||||||
# on the runner host (coordination review fallback decision)
|
# consolidation had based this repo on the P1-7 host-clone fallback
|
||||||
# - no actions/cache layer for the same reason; the persistent /data/cache/ci
|
# lineage and dropped the completed migration (est/Est-Infra@57cc9f7);
|
||||||
# directory is the primary (and only) cache layer
|
# 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:
|
# 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;
|
# - 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
|
# helper images have their apt/apk sources baked in, so replacing the public
|
||||||
# trust store is safe here — see playbook pitfall 13)
|
# trust store is safe here — see playbook pitfall 13)
|
||||||
@@ -44,7 +46,27 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: /data/cache/ci/quality
|
default: /data/cache/ci/quality
|
||||||
description: "Persistent host-side cache dir (pnpm store, tools, browsers)"
|
description: "Host-side cache dir (pnpm store, tools, browsers)"
|
||||||
|
cache-mode:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: fixed
|
||||||
|
description: "fixed: one shared persistent dir. per-run: fresh mktemp child per run + always() cleanup (for scripts with from-zero guards on commit-keyed tool caches)"
|
||||||
|
mount-docker-socket:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Non-empty (e.g. 'yes') mounts /var/run/docker.sock into the toolchain containers (boolean inputs are NOT passed reliably through workflow_call with:)"
|
||||||
|
commit-env-name:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Env var name that receives the triggering commit SHA inside the containers (e.g. EST_GIT_COMMIT); empty disables"
|
||||||
|
extra-env:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Multiline KEY=VALUE extra env for the toolchain containers (values must not contain spaces; caller-side expressions are NOT evaluated)"
|
||||||
secrets:
|
secrets:
|
||||||
REGISTRY_PASSWORD:
|
REGISTRY_PASSWORD:
|
||||||
required: false
|
required: false
|
||||||
@@ -53,18 +75,14 @@ jobs:
|
|||||||
quality:
|
quality:
|
||||||
runs-on: build-docker
|
runs-on: build-docker
|
||||||
steps:
|
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:
|
env:
|
||||||
CI_ACTOR: ${{ github.actor }}
|
GIT_SSL_CAINFO: /usr/local/share/ca-certificates/caddy-root-ca.crt
|
||||||
CI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
- name: verify HEAD equals triggering commit
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
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}"
|
test "$(git rev-parse HEAD)" = "${GITHUB_SHA}"
|
||||||
|
|
||||||
- name: authenticate to gitea registry (private helper image pulls)
|
- name: authenticate to gitea registry (private helper image pulls)
|
||||||
@@ -80,21 +98,64 @@ jobs:
|
|||||||
- name: prepare cache dir (dirs 0777, files untouched)
|
- name: prepare cache dir (dirs 0777, files untouched)
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
mkdir -p "${{ inputs.cache-dir }}"
|
cache_root="${{ inputs.cache-dir }}"
|
||||||
chmod 0777 "${{ inputs.cache-dir }}"
|
mkdir -p "$cache_root"
|
||||||
find "${{ inputs.cache-dir }}" -mindepth 1 -maxdepth 1 -type d -exec chmod 0777 {} + 2>/dev/null || true
|
chmod 0777 "$cache_root"
|
||||||
|
if [ "${{ inputs.cache-mode }}" = "per-run" ]; then
|
||||||
|
cache_dir="$(mktemp -d "$cache_root/run-XXXXXXXX")"
|
||||||
|
else
|
||||||
|
cache_dir="$cache_root"
|
||||||
|
fi
|
||||||
|
chmod 0777 "$cache_dir"
|
||||||
|
find "$cache_dir" -mindepth 1 -maxdepth 1 -type d -exec chmod 0777 {} + 2>/dev/null || true
|
||||||
|
printf 'TOOL_CACHE_DIR=%s\n' "$cache_dir" >>"$GITHUB_ENV"
|
||||||
|
|
||||||
# install and quality run in ONE container: toolchains installed by the
|
# install and quality run in ONE container: toolchains installed by the
|
||||||
# install command (global pnpm, local bins) must still be on PATH for the
|
# install command (global pnpm, local bins) must still be on PATH for the
|
||||||
# quality command — two `docker run --rm` invocations would not share
|
# quality command — two `docker run --rm` invocations would not share
|
||||||
# anything but the workspace and /cache mounts.
|
# anything but the workspace and /cache mounts.
|
||||||
- name: install and quality (containerized toolchain)
|
- name: install and quality (containerized toolchain)
|
||||||
|
env:
|
||||||
|
COMMIT_ENV_NAME: ${{ inputs.commit-env-name }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
|
mount_args=""
|
||||||
|
if [ -n "${{ inputs.mount-docker-socket }}" ]; then
|
||||||
|
mount_args="-v /var/run/docker.sock:/var/run/docker.sock"
|
||||||
|
fi
|
||||||
|
env_args=""
|
||||||
|
if [ -n "${COMMIT_ENV_NAME}" ]; then
|
||||||
|
env_args="${env_args} -e ${COMMIT_ENV_NAME}=${GITHUB_SHA}"
|
||||||
|
fi
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -n "$line" ] && env_args="${env_args} -e $line"
|
||||||
|
done <<EOF
|
||||||
|
${{ inputs.extra-env }}
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2086
|
||||||
docker run --rm --add-host npm.cache.est:172.17.0.1 \
|
docker run --rm --add-host npm.cache.est:172.17.0.1 \
|
||||||
|
$mount_args \
|
||||||
-v "$PWD:${{ inputs.workspace }}" -w "${{ inputs.workspace }}" \
|
-v "$PWD:${{ inputs.workspace }}" -w "${{ inputs.workspace }}" \
|
||||||
-v "${{ inputs.cache-dir }}:/cache" -e TMPDIR=/cache \
|
-v "${TOOL_CACHE_DIR}:/cache" -e TMPDIR=/cache \
|
||||||
-v /usr/local/share/ca-certificates/est-bundle.crt:/ca/est-bundle.crt:ro \
|
-v /usr/local/share/ca-certificates/est-bundle.crt:/ca/est-bundle.crt:ro \
|
||||||
-e SSL_CERT_FILE=/ca/est-bundle.crt \
|
-e SSL_CERT_FILE=/ca/est-bundle.crt \
|
||||||
-e NODE_EXTRA_CA_CERTS=/ca/est-bundle.crt \
|
-e NODE_EXTRA_CA_CERTS=/ca/est-bundle.crt \
|
||||||
|
$env_args \
|
||||||
"${{ inputs.node-image }}" sh -euxc '${{ inputs.install-command }} && ${{ inputs.quality-command }}'
|
"${{ inputs.node-image }}" sh -euxc '${{ inputs.install-command }} && ${{ inputs.quality-command }}'
|
||||||
|
|
||||||
|
# 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: |
|
||||||
|
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):
|
# P1-7 verification status (2026-08-27, Gitea 1.27.2):
|
||||||
# - reusable workflow calls verified working (selftest caller:
|
# - reusable workflow calls verified working (selftest caller:
|
||||||
# .gitea/workflows/selftest.yml)
|
# .gitea/workflows/selftest.yml)
|
||||||
# - checkout uses host git clone (JS actions need a host node runtime that
|
# - checkout via mu-ref/actions-checkout@v4 + HEAD==SHA postcondition
|
||||||
# tn does not install — see reusable/node-quality.yml header)
|
# (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
|
# - registry identity is the triggering actor (github.actor), credentials
|
||||||
# flow exclusively through the REGISTRY_PASSWORD secret (no hardcoded
|
# flow exclusively through the REGISTRY_PASSWORD secret (no hardcoded
|
||||||
# usernames — coordination review pitfall 21)
|
# usernames — coordination review pitfall 21)
|
||||||
@@ -31,9 +32,10 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
description: "Digest-pinned helper image with node + docker CLI + verifier tooling"
|
description: "Digest-pinned helper image with node + docker CLI + verifier tooling"
|
||||||
image-matrix:
|
image-matrix:
|
||||||
required: true
|
required: false
|
||||||
type: string
|
type: string
|
||||||
description: "Multiline matrix: service|dockerfile|target per line"
|
default: ""
|
||||||
|
description: "Multiline matrix: service|dockerfile|target per line (required for the built-in loop; script mode uses it only for the digest summary)"
|
||||||
platform:
|
platform:
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -62,6 +64,41 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: git.moneywood.site
|
default: git.moneywood.site
|
||||||
|
build-command:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Script mode: run this command inside the helper container (full mounts: sock/docker-config/buildx/CA/cache + envs) instead of the built-in matrix loop"
|
||||||
|
install-command:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Script mode only: runs in the SAME container before build-command (toolchains installed here must survive to the build phase)"
|
||||||
|
cache-dir:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: /data/cache/ci/build
|
||||||
|
description: "Script mode: host-side cache dir mounted at /cache"
|
||||||
|
cache-mode:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: fixed
|
||||||
|
description: "fixed | per-run (per-run = fresh mktemp child + always() cleanup; for from-zero tool caches)"
|
||||||
|
commit-env-name:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Script mode: env var receiving the commit SHA inside the container (e.g. EST_GIT_COMMIT)"
|
||||||
|
extra-env:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ""
|
||||||
|
description: "Script mode: multiline KEY=VALUE extra env (no spaces in values; expressions NOT evaluated)"
|
||||||
|
workspace:
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: /workspace
|
||||||
|
description: "Script mode: workspace mount point inside the container"
|
||||||
secrets:
|
secrets:
|
||||||
REGISTRY_PASSWORD:
|
REGISTRY_PASSWORD:
|
||||||
required: true
|
required: true
|
||||||
@@ -70,18 +107,14 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: build-docker
|
runs-on: build-docker
|
||||||
steps:
|
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:
|
env:
|
||||||
CI_ACTOR: ${{ github.actor }}
|
GIT_SSL_CAINFO: /usr/local/share/ca-certificates/caddy-root-ca.crt
|
||||||
CI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
- name: verify HEAD equals triggering commit
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
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}"
|
test "$(git rev-parse HEAD)" = "${GITHUB_SHA}"
|
||||||
|
|
||||||
- name: authenticate to gitea registry
|
- name: authenticate to gitea registry
|
||||||
@@ -92,7 +125,60 @@ jobs:
|
|||||||
printf '%s' "${REGISTRY_PASSWORD}" \
|
printf '%s' "${REGISTRY_PASSWORD}" \
|
||||||
| docker login "${{ inputs.registry-host }}" -u "${{ github.actor }}" --password-stdin
|
| docker login "${{ inputs.registry-host }}" -u "${{ github.actor }}" --password-stdin
|
||||||
|
|
||||||
|
- name: prepare script-mode cache dir
|
||||||
|
if: inputs.build-command != ''
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
cache_root="${{ inputs.cache-dir }}"
|
||||||
|
mkdir -p "$cache_root"
|
||||||
|
chmod 0777 "$cache_root"
|
||||||
|
if [ "${{ inputs.cache-mode }}" = "per-run" ]; then
|
||||||
|
cache_dir="$(mktemp -d "$cache_root/run-XXXXXXXX")"
|
||||||
|
else
|
||||||
|
cache_dir="$cache_root"
|
||||||
|
fi
|
||||||
|
chmod 0777 "$cache_dir"
|
||||||
|
find "$cache_dir" -mindepth 1 -maxdepth 1 -type d -exec chmod 0777 {} + 2>/dev/null || true
|
||||||
|
printf 'TOOL_CACHE_DIR=%s\n' "$cache_dir" >>"$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: run build script (script mode)
|
||||||
|
if: inputs.build-command != ''
|
||||||
|
env:
|
||||||
|
REGISTRY_AUTH_USER: ${{ github.actor }}
|
||||||
|
REGISTRY_AUTH_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
COMMIT_ENV_NAME: ${{ inputs.commit-env-name }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
mount_args="-v /var/run/docker.sock:/var/run/docker.sock"
|
||||||
|
if [ -f "$HOME/.docker/config.json" ]; then
|
||||||
|
mount_args="$mount_args -v $HOME/.docker/config.json:/root/.docker/config.json:ro"
|
||||||
|
fi
|
||||||
|
if [ -f /usr/libexec/docker/cli-plugins/docker-buildx ]; then
|
||||||
|
mount_args="$mount_args -v /usr/libexec/docker/cli-plugins/docker-buildx:/root/.docker/cli-plugins/docker-buildx:ro"
|
||||||
|
fi
|
||||||
|
env_args=""
|
||||||
|
if [ -n "${COMMIT_ENV_NAME}" ]; then
|
||||||
|
env_args="${env_args} -e ${COMMIT_ENV_NAME}=${GITHUB_SHA}"
|
||||||
|
fi
|
||||||
|
env_args="${env_args} -e REGISTRY_AUTH_USER -e REGISTRY_AUTH_PASSWORD"
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -n "$line" ] && env_args="${env_args} -e $line"
|
||||||
|
done <<EOF
|
||||||
|
${{ inputs.extra-env }}
|
||||||
|
EOF
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
docker run --rm --add-host npm.cache.est:172.17.0.1 \
|
||||||
|
$mount_args \
|
||||||
|
-v "$PWD:${{ inputs.workspace }}" -w "${{ inputs.workspace }}" \
|
||||||
|
-v "${TOOL_CACHE_DIR}:/cache" -e TMPDIR=/cache \
|
||||||
|
-v /usr/local/share/ca-certificates/est-bundle.crt:/ca/est-bundle.crt:ro \
|
||||||
|
-e SSL_CERT_FILE=/ca/est-bundle.crt \
|
||||||
|
-e NODE_EXTRA_CA_CERTS=/ca/est-bundle.crt \
|
||||||
|
$env_args \
|
||||||
|
"${{ inputs.node-image }}" sh -euxc '${{ inputs.install-command }} && ${{ inputs.build-command }}'
|
||||||
|
|
||||||
- name: build push and verify image matrix
|
- name: build push and verify image matrix
|
||||||
|
if: inputs.build-command == ''
|
||||||
env:
|
env:
|
||||||
REGISTRY_AUTH_USER: ${{ github.actor }}
|
REGISTRY_AUTH_USER: ${{ github.actor }}
|
||||||
REGISTRY_AUTH_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
REGISTRY_AUTH_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
@@ -102,6 +188,7 @@ jobs:
|
|||||||
VERIFY_COMMAND: ${{ inputs.verify-command }}
|
VERIFY_COMMAND: ${{ inputs.verify-command }}
|
||||||
CACHE_REGISTRY_REF: ${{ inputs.cache-registry-ref }}
|
CACHE_REGISTRY_REF: ${{ inputs.cache-registry-ref }}
|
||||||
REVISION_ARG_NAME: ${{ inputs.revision-arg-name }}
|
REVISION_ARG_NAME: ${{ inputs.revision-arg-name }}
|
||||||
|
IMAGE_MATRIX: ${{ inputs.image-matrix }}
|
||||||
run: |
|
run: |
|
||||||
set -eu
|
set -eu
|
||||||
IMAGE_TAG="git-${GITHUB_SHA}"
|
IMAGE_TAG="git-${GITHUB_SHA}"
|
||||||
@@ -137,6 +224,10 @@ jobs:
|
|||||||
done <<EOF
|
done <<EOF
|
||||||
${{ inputs.build-args }}
|
${{ inputs.build-args }}
|
||||||
EOF
|
EOF
|
||||||
|
if [ -z "${IMAGE_MATRIX:-}" ]; then
|
||||||
|
echo "image-matrix is required for the built-in loop (or use build-command script mode)" >&2
|
||||||
|
exit 64
|
||||||
|
fi
|
||||||
if [ -n "${REVISION_ARG_NAME}" ]; then
|
if [ -n "${REVISION_ARG_NAME}" ]; then
|
||||||
build_args="${build_args} --build-arg ${REVISION_ARG_NAME}=${GITHUB_SHA}"
|
build_args="${build_args} --build-arg ${REVISION_ARG_NAME}=${GITHUB_SHA}"
|
||||||
fi
|
fi
|
||||||
@@ -185,3 +276,44 @@ jobs:
|
|||||||
echo '```'
|
echo '```'
|
||||||
} >>"${GITHUB_STEP_SUMMARY:-/dev/stdout}"
|
} >>"${GITHUB_STEP_SUMMARY:-/dev/stdout}"
|
||||||
cat "$digest_file"
|
cat "$digest_file"
|
||||||
|
|
||||||
|
- name: digest summary (script mode)
|
||||||
|
if: inputs.build-command != '' && inputs.image-matrix != ''
|
||||||
|
env:
|
||||||
|
IMAGE_ROOT: ${{ inputs.image-root }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
image_tag="git-${GITHUB_SHA}"
|
||||||
|
digest_file=".tmp-ci/digests-script.txt"
|
||||||
|
mkdir -p .tmp-ci
|
||||||
|
: >"$digest_file"
|
||||||
|
while IFS='|' read -r service dockerfile target; do
|
||||||
|
[ -n "${service:-}" ] || continue
|
||||||
|
index_digest=$(docker buildx imagetools inspect "${IMAGE_ROOT}/${service}:${image_tag}" | awk '/^Digest:/{print $2}')
|
||||||
|
printf '%s|%s|%s\n' "$service" "$image_tag" "$index_digest" >>"$digest_file"
|
||||||
|
done <<'IMAGES'
|
||||||
|
${{ inputs.image-matrix }}
|
||||||
|
IMAGES
|
||||||
|
{
|
||||||
|
echo "## V4 fresh image digests"
|
||||||
|
echo
|
||||||
|
echo "revision: ${GITHUB_SHA}"
|
||||||
|
echo
|
||||||
|
echo '```'
|
||||||
|
cat "$digest_file"
|
||||||
|
echo '```'
|
||||||
|
} >>"${GITHUB_STEP_SUMMARY:-/dev/stdout}"
|
||||||
|
cat "$digest_file"
|
||||||
|
|
||||||
|
# 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: |
|
||||||
|
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}"
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
|
|
||||||
| 路径 | 用途 |
|
| 路径 | 用途 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `.gitea/workflows/reusable/checkout.yml` | 统一 checkout(mu-ref/actions-checkout + CA + HEAD==SHA 守卫;host job 专用) |
|
| `.gitea/workflows/reusable/node-quality.yml` | node 质量门(digest helper、持久缓存、rank 源序、actions-checkout checkout) |
|
||||||
| `.gitea/workflows/reusable/node-quality.yml` | node 质量门(digest helper、持久缓存、rank 源序) |
|
|
||||||
| `.gitea/workflows/reusable/oci-build-push-verify.yml` | 镜像构建+推送+verify-command 校验链 |
|
| `.gitea/workflows/reusable/oci-build-push-verify.yml` | 镜像构建+推送+verify-command 校验链 |
|
||||||
| `tools/ci/source-policy.sh` | 唯一选源实现(公司级 canonical) |
|
| `tools/ci/source-policy.sh` | 唯一选源实现(公司级 canonical) |
|
||||||
| `tools/ci/helper/REGISTER.md` | ci-node-* helper 镜像 digest 注册 |
|
| `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-27 定稿:曾按初版决策试建 est/ci-workflows,因 est org 私有闸门不可跨仓调用而删除(用户改批 mu-ref 宿主);同日自 est/Est-Infra 上移 tools/ci。
|
||||||
|
- 2026-08-31 v4(PLAT-014,Issue #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)应升 @v4,fixed 模式调用方(est/Reef)无清理步可留 @v3。
|
||||||
|
- 2026-08-29 v3:模板 checkout 恢复 mu-ref/actions-checkout@v4(JS action)+ HEAD==SHA postcondition——P1-10 的 JS 迁移(est/Est-Infra@57cc9f7,08-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)。
|
- helper Dockerfile 的可复现 bake 与 ops 巡检脚本仍属项目级(Est-Infra / gitea-host-setup)。
|
||||||
|
|
||||||
|
## Runner contract(2026-08-30 定死)
|
||||||
|
|
||||||
|
- **唯一 runner:TN `tn-build-runner`(gitea-runner v3.3.1,注册号 est org 范围)**;TS 只承载 Gitea/Registry,无任何 runner;0.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。
|
||||||
|
|||||||
Reference in New Issue
Block a user