Compare commits

..

1 Commits

Author SHA1 Message Date
ogt
6dd6d6b221 perf(cd): coalesce stale deployment carriers 2026-07-18 19:56:59 +08:00

View File

@@ -60,13 +60,66 @@ on:
type: boolean
default: false
# 新 push 立即取消舊 job只部署最新版本
# Gitea 1.25 不可靠執行 workflow concurrencyroot selector 會在 deploy
# 前以 main tip 做 coalescing。不要中途取消 rsync / migration。
concurrency:
group: cd-deploy-${{ gitea.ref }}
cancel-in-progress: true
cancel-in-progress: false
jobs:
select-latest-carrier:
runs-on: ewoooc-host
timeout-minutes: 3
outputs:
selected: ${{ steps.carrier.outputs.selected }}
source_sha: ${{ steps.carrier.outputs.source_sha }}
latest_sha: ${{ steps.carrier.outputs.latest_sha }}
steps:
- name: Select latest main carrier
id: carrier
env:
GITEA_TOKEN: ${{ gitea.token }}
GITEA_SERVER_URL: ${{ gitea.server_url }}
GITEA_REPOSITORY: ${{ gitea.repository }}
GITEA_SHA: ${{ gitea.sha }}
run: |
set -euo pipefail
: "${GITEA_TOKEN:?missing Gitea token}"
: "${GITEA_SERVER_URL:?missing Gitea server URL}"
: "${GITEA_REPOSITORY:?missing Gitea repository}"
[[ "${GITEA_SHA}" =~ ^[0-9a-f]{40}$ ]] || {
echo "BLOCKER ewoooc_cd_source_sha_invalid"
exit 1
}
sleep "${EWOOOC_CD_CARRIER_DEBOUNCE_SECONDS:-15}"
source_url="${GITEA_SERVER_URL%/}/${GITEA_REPOSITORY}.git"
auth_header="Basic $(printf 'x-access-token:%s' "${GITEA_TOKEN}" | base64 | tr -d '\n')"
latest_sha="$(
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0=http.extraHeader \
GIT_CONFIG_VALUE_0="Authorization: ${auth_header}" \
git \
ls-remote --heads "${source_url}" refs/heads/main | awk 'NR == 1 {print $1}'
)"
unset auth_header GITEA_TOKEN
[[ "${latest_sha}" =~ ^[0-9a-f]{40}$ ]] || {
echo "BLOCKER ewoooc_cd_main_tip_unresolved"
exit 1
}
selected=false
status=superseded_by_latest_main_carrier
if [ "${GITEA_SHA}" = "${latest_sha}" ]; then
selected=true
status=selected_latest_main_carrier
fi
echo "selected=${selected}" >> "${GITHUB_OUTPUT}"
echo "source_sha=${GITEA_SHA}" >> "${GITHUB_OUTPUT}"
echo "latest_sha=${latest_sha}" >> "${GITHUB_OUTPUT}"
echo "EWOOOC_CD_CARRIER status=${status} source=${GITEA_SHA} latest=${latest_sha}"
deploy:
needs: [select-latest-carrier]
if: ${{ needs.select-latest-carrier.outputs.selected == 'true' }}
timeout-minutes: 20
runs-on: ewoooc-host
@@ -186,7 +239,16 @@ jobs:
# rsync --inplace 避免 app.py/config.py 單檔 bind mount 因 inode replacement 卡住舊版本
- name: 安裝 rsync / ssh
run: |
apt-get update -qq && apt-get install -y -qq rsync openssh-client
missing=()
command -v rsync >/dev/null 2>&1 || missing+=(rsync)
command -v ssh >/dev/null 2>&1 || missing+=(openssh-client)
if [ "${#missing[@]}" -eq 0 ]; then
echo "ewoooc_deploy_tools_ready=1 install_performed=0"
else
apt-get update -qq
apt-get install -y -qq "${missing[@]}"
echo "ewoooc_deploy_tools_ready=1 install_performed=1"
fi
- name: AI 觀測台 Pre-deploy 靜態 QA
if: steps.observability_qa.outputs.needed == 'true'