♻️ refactor(ci): use fixed workflow slots

This commit is contained in:
csh
2026-07-16 09:17:05 +08:00
parent 778297543a
commit 610c2b3e74
7 changed files with 210 additions and 570 deletions
+70 -6
View File
@@ -36,6 +36,65 @@ test_stats_workflow_uses_workflow_secret_consistently() {
! rg -q 'GITHUB_TOKEN' "${file}" || fail "stats workflow should not mention GITHUB_TOKEN in token guidance"
}
test_release_workflow_uses_inline_release_slot() {
local file
file="${REPO_ROOT}/.gitea/workflows/changelog_and_release.yml"
grep -Fq 'group: release-${{ github.repository }}' "${file}" || fail "release workflow should serialize its slot per repository"
grep -q '^[[:space:]]*cancel-in-progress: false$' "${file}" || fail "release slot should queue instead of canceling"
grep -Fq 'WORKSPACE_DIR: "/data/workspace"' "${file}" || fail "release workflow should use /data/workspace"
grep -Fq 'WORKSPACE_SLOT: "release"' "${file}" || fail "release workflow should own the release slot"
grep -Fq 'MAIN_BRANCH: "main"' "${file}" || fail "release workflow should keep an explicit MAIN_BRANCH"
grep -Fq '# 必须明确配置主分支(例如 main 或 master' "${file}" || fail "release workflow should document MAIN_BRANCH as required"
! rg -q 'CHANGELOG\.md (已作为附件上传|已上传为附件)' "${file}" || fail "release workflow should not claim CHANGELOG.md was uploaded as a Release asset"
grep -q 'ADDITIONAL_RELEASE_FILES' "${file}" || fail "release workflow should retain optional Release asset configuration"
grep -Fq 'attachment=@${file}' "${file}" || fail "release workflow should retain optional Release asset uploads"
grep -q 'GIT_CONFIG_COUNT: "3"' "${file}" || fail "release workflow should configure transient Git authentication"
grep -Fq 'case "$REMOTE_URL" in' "${file}" || fail "release workflow should reject token use on non-HTTPS remotes"
grep -Fq 'REPO_DIR="${WORKSPACE_DIR}/${REPO_NAME}/${WORKSPACE_SLOT}"' "${file}" || fail "release workflow should build its clone-root slot inline"
grep -Fq 'git clone --no-checkout "$REMOTE_URL" "$REPO_DIR"' "${file}" || fail "release workflow should clone directly into its slot"
grep -Fq 'git -C "$REPO_DIR" checkout --force -B "$MAIN_BRANCH" "$REMOTE_REF"' "${file}" || fail "release workflow should reset its branch from origin"
grep -Fq 'git -C "$REPO_DIR" clean -ffdx' "${file}" || fail "release workflow should clean ignored output before reuse"
grep -Fq 'git -C "${{ env.REPO_DIR }}" push origin "${{ env.MAIN_BRANCH }}"' "${file}" || fail "release workflow should push directly through transient authentication"
! rg -q 'BOOTSTRAP_SCRIPT|prepare-slot-workspace|git-auth|bootstrap_workspace\.sh' "${file}" || fail "release workflow should not use a shared bootstrap helper"
! rg -q 'MIRROR_ROOT|JOB_WORKSPACE_ROOT|MIRROR_PATH|JOB_WORKSPACE|https://oauth2:' "${file}" || fail "release workflow should not use retired paths or credential URLs"
}
test_stats_workflow_uses_inline_stats_slot() {
local file
file="${REPO_ROOT}/.gitea/workflows/update_stats_badge.yaml"
grep -Fq 'group: stats-${{ github.repository }}' "${file}" || fail "stats workflow should serialize the stats slot per repository"
grep -q '^[[:space:]]*cancel-in-progress: false$' "${file}" || fail "stats slot should queue instead of canceling"
grep -Fq 'WORKSPACE_DIR: "/data/workspace"' "${file}" || fail "stats workflow should use /data/workspace"
grep -Fq 'WORKSPACE_SLOT: "stats"' "${file}" || fail "stats workflow should own the stats slot"
grep -q 'GIT_CONFIG_COUNT: "3"' "${file}" || fail "stats workflow should configure transient Git authentication"
grep -Fq 'case "$REMOTE_URL" in' "${file}" || fail "stats workflow should reject token use on non-HTTPS remotes"
grep -Fq 'REPO_DIR="${WORKSPACE_DIR}/${REPO_NAME}/${WORKSPACE_SLOT}"' "${file}" || fail "stats workflow should build its clone-root slot inline"
grep -Fq 'git clone --no-checkout "$REMOTE_URL" "$REPO_DIR"' "${file}" || fail "stats workflow should clone directly into its slot"
grep -Fq 'git -C "$REPO_DIR" checkout --force -B "$TARGET_BRANCH" "$REMOTE_REF"' "${file}" || fail "stats workflow should reset its source branch from origin"
grep -Fq 'git -C "$REPO_DIR" clean -ffdx' "${file}" || fail "stats workflow should clean ignored output before reuse"
grep -Fq 'git checkout --force -B "${{ env.BADGE_BRANCH }}" "refs/remotes/origin/${{ env.BADGE_BRANCH }}"' "${file}" || fail "stats workflow should reset a reused local stats branch to origin"
grep -Fq 'git branch -D "${{ env.BADGE_BRANCH }}"' "${file}" || fail "stats workflow should remove a stale local stats branch when origin is absent"
grep -Fq 'git -C "${{ env.REPO_DIR }}" push origin "${{ env.BADGE_BRANCH }}"' "${file}" || fail "stats workflow should push directly through transient authentication"
! rg -q 'BOOTSTRAP_SCRIPT|prepare-slot-workspace|git-auth|bootstrap_workspace\.sh' "${file}" || fail "stats workflow should not use a shared bootstrap helper"
! rg -q 'MIRROR_ROOT|JOB_WORKSPACE_ROOT|MIRROR_PATH|JOB_WORKSPACE|https://oauth2:' "${file}" || fail "stats workflow should not use retired paths or credential URLs"
}
test_shared_workspace_helper_is_removed() {
test ! -e "${REPO_ROOT}/.gitea/ci/bootstrap_workspace.sh" || fail "shared workspace helper should be removed"
}
test_register_default_capacity_is_four() {
grep -q "config\['runner'\]\['capacity'\] = 4" "${REPO_ROOT}/docker-runner/common/register.sh" || fail "register.sh should default new runner capacity to 4"
}
test_presets_do_not_mount_workspace_helper() {
! rg -q 'workspace\.sh:/data/workspace\.sh' "${REPO_ROOT}/docker-runner/presets" || fail "presets should not mount a shared workspace helper"
}
test_workflow_docs_and_links_use_actual_paths() {
local workflow_doc stats_workflow release_workflow
@@ -61,13 +120,13 @@ test_workflow_doc_describes_workspace_architecture() {
file="${REPO_ROOT}/WORKFLOW.md"
grep -Eq '^## .*运行模型' "${file}" || fail "WORKFLOW.md should include a run model section"
grep -q 'bare' "${file}" || fail "WORKFLOW.md should describe the bare mirror model"
grep -q '工作副本' "${file}" || fail "WORKFLOW.md should describe isolated work copies"
grep -Eq '共享.*缓存|缓存.*共享' "${file}" || fail "WORKFLOW.md should describe the shared cache model"
grep -Eq '并发|隔离' "${file}" || fail "WORKFLOW.md should mention concurrency or isolation tradeoffs"
grep -Eq '结束后.*清理|清理.*工作副本' "${file}" || fail "WORKFLOW.md should mention cleanup after workflow completion"
grep -Eq '固定.*slot|slot.*固定' "${file}" || fail "WORKFLOW.md should describe fixed workflow slots"
grep -Eq '职责|责任' "${file}" || fail "WORKFLOW.md should describe responsibility ownership"
grep -Eq '并发|串行' "${file}" || fail "WORKFLOW.md should describe slot serialization"
grep -Eq 'reset|重置' "${file}" || fail "WORKFLOW.md should describe reset before reuse"
grep -Eq '保留|复用' "${file}" || fail "WORKFLOW.md should describe persistent reuse"
! rg -q 'bare|MIRROR_ROOT|JOB_WORKSPACE_ROOT|/data/git-mirrors|/home/workspace/jobs' "${file}" || fail "WORKFLOW.md should not describe the retired mirror model"
! rg -q 'bootstrap_workspace\.sh' "${file}" || fail "WORKFLOW.md should describe architecture rather than helper implementation"
! rg -q '/data/git-mirrors|/home/workspace/jobs' "${file}" || fail "WORKFLOW.md should avoid implementation-specific workspace paths"
}
test_presets_do_not_mount_check_crlf_helper() {
@@ -243,6 +302,11 @@ test_entrypoint_uses_platform_aware_multiarch_verification() {
test_preset_compose_uses_env_for_instance
test_workflows_do_not_hardcode_company_server
test_stats_workflow_uses_workflow_secret_consistently
test_release_workflow_uses_inline_release_slot
test_stats_workflow_uses_inline_stats_slot
test_shared_workspace_helper_is_removed
test_register_default_capacity_is_four
test_presets_do_not_mount_workspace_helper
test_workflow_docs_and_links_use_actual_paths
test_workflow_doc_describes_workspace_architecture
test_presets_do_not_mount_check_crlf_helper
-169
View File
@@ -1,169 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
REPO_ROOT=$(cd "${SCRIPT_DIR}/.." && pwd)
# shellcheck source=/dev/null
source "${REPO_ROOT}/.gitea/ci/bootstrap_workspace.sh"
assert_eq() {
local expected=$1
local actual=$2
local message=$3
if [ "${expected}" != "${actual}" ]; then
echo "FAIL: ${message}" >&2
echo " expected: ${expected}" >&2
echo " actual: ${actual}" >&2
exit 1
fi
}
test_repo_path_layout() {
local owner repo_name mirror_dir workspace_root mirror_path workspace_root_path repo_dir
owner="csh"
repo_name="actions-template"
mirror_dir="/data/git-mirrors"
workspace_root="/home/workspace/jobs"
mirror_path=$(build_mirror_path "${mirror_dir}" "${owner}" "${repo_name}")
workspace_root_path=$(build_job_workspace_root "${workspace_root}" "${owner}" "${repo_name}" "123456-1-release")
repo_dir=$(build_job_repo_dir "${workspace_root}" "${owner}" "${repo_name}" "123456-1-release")
assert_eq "/data/git-mirrors/csh/actions-template.git" "${mirror_path}" "mirror path should include owner and bare repo suffix"
assert_eq "/home/workspace/jobs/csh/actions-template/123456-1-release" "${workspace_root_path}" "workspace root should include owner repo and job identity"
assert_eq "/home/workspace/jobs/csh/actions-template/123456-1-release/repo" "${repo_dir}" "repo dir should live under isolated workspace root"
}
test_job_identity_prefers_run_metadata() {
local actual
actual=$(build_job_identity "123456" "2" "release-job")
assert_eq "123456-2-release-job" "${actual}" "job identity should include run id attempt and job name"
}
test_sanitize_job_name() {
local actual
actual=$(sanitize_job_name "release notes/job")
assert_eq "release-notes-job" "${actual}" "job names should be filesystem-safe"
}
test_repo_owner_and_name_parsing() {
local actual
actual=$(split_repository_slug "csh/actions-template")
assert_eq $'csh\nactions-template' "${actual}" "repository slug should split into owner and repo lines"
}
test_prepare_and_cleanup_workspace() {
local temp_root remote_repo seed_repo mirror_root workspace_root env_file
local repo_dir mirror_path job_workspace origin_url alternates_file alternates_target
temp_root=$(mktemp -d)
remote_repo="${temp_root}/remote.git"
seed_repo="${temp_root}/seed"
mirror_root="${temp_root}/mirrors"
workspace_root="${temp_root}/jobs"
env_file="${temp_root}/prepared.env"
git init -b main "${seed_repo}" >/dev/null
git -C "${seed_repo}" config user.name "Test User"
git -C "${seed_repo}" config user.email "test@example.com"
printf 'hello\n' > "${seed_repo}/README.md"
git -C "${seed_repo}" add README.md
git -C "${seed_repo}" commit -m "Initial commit" >/dev/null
git clone --bare "${seed_repo}" "${remote_repo}" >/dev/null
prepare_job_workspace \
"csh/actions-template" \
"${remote_repo}" \
"${mirror_root}" \
"${workspace_root}" \
"123456" \
"2" \
"release job" > "${env_file}"
# shellcheck source=/dev/null
source "${env_file}"
repo_dir="${REPO_DIR}"
mirror_path="${MIRROR_PATH}"
job_workspace="${JOB_WORKSPACE}"
if [ ! -d "${mirror_path}" ]; then
echo "FAIL: mirror path should exist after preparation" >&2
exit 1
fi
if [ ! -d "${repo_dir}/.git" ]; then
echo "FAIL: prepared repo dir should contain a git checkout" >&2
exit 1
fi
origin_url=$(git -C "${repo_dir}" remote get-url origin)
assert_eq "${remote_repo}" "${origin_url}" "prepared repo should point origin to the requested remote"
alternates_file="${repo_dir}/.git/objects/info/alternates"
if [ ! -f "${alternates_file}" ]; then
echo "FAIL: prepared repo should use shared mirror objects via alternates" >&2
exit 1
fi
alternates_target=$(cat "${alternates_file}")
assert_eq "${mirror_path}/objects" "${alternates_target}" "prepared repo should borrow objects from the bare mirror"
cleanup_job_workspace "${job_workspace}"
if [ -e "${job_workspace}" ]; then
echo "FAIL: cleanup should remove the job workspace" >&2
exit 1
fi
rm -rf "${temp_root}"
}
test_register_default_capacity_is_four() {
if ! grep -q "config\['runner'\]\['capacity'\] = 4" "${REPO_ROOT}/docker-runner/common/register.sh"; then
echo "FAIL: register.sh should default new runner capacity to 4" >&2
exit 1
fi
}
test_changelog_workflow_uses_workspace_helper() {
if ! grep -q ".gitea/ci/bootstrap_workspace.sh" "${REPO_ROOT}/.gitea/workflows/changelog_and_release.yml"; then
echo "FAIL: changelog workflow should fetch repo-owned bootstrap helper" >&2
exit 1
fi
}
test_stats_workflow_uses_workspace_helper() {
if ! grep -q ".gitea/ci/bootstrap_workspace.sh" "${REPO_ROOT}/.gitea/workflows/update_stats_badge.yaml"; then
echo "FAIL: stats workflow should fetch repo-owned bootstrap helper" >&2
exit 1
fi
}
test_presets_do_not_mount_workspace_helper() {
if rg -q "workspace\.sh:/data/workspace\.sh" "${REPO_ROOT}/docker-runner/presets"; then
echo "FAIL: preset compose files should not mount workspace helper from runner common" >&2
exit 1
fi
}
test_repo_path_layout
test_job_identity_prefers_run_metadata
test_sanitize_job_name
test_repo_owner_and_name_parsing
test_prepare_and_cleanup_workspace
test_register_default_capacity_is_four
test_changelog_workflow_uses_workspace_helper
test_stats_workflow_uses_workspace_helper
test_presets_do_not_mount_workspace_helper
echo "workspace_helper_test.sh: PASS"