chore(release): 版本号改 v3.5.1 + promote 时同步打版本号 tag
版本号机制(老师 2026-10-03 定):
· latest 永远 = master 最新正式版(原有行为不变);
· 每个正式版额外留一个**不可变**的版本号 tag(vX.Y.Z),日后可靠它拉回旧正式版;
· **无论如何都不能靠版本号拉到 test 分支的镜像** —— 结构性保证:promote 步骤的 if 写死
github.ref == 'refs/heads/master',分支构建根本执行不到打 tag 那几行。
版本号来源 = src/config/app.php 的 version(单一事实来源,与 PIN 从 Dockerfile 解析同一原则),
本次 v3.5 → v3.5.1。
三道守卫:
① 格式必须 vX.Y.Z;
② 用 Compare API 确认本 commit 确实在 master 上(挡住 workflow_dispatch 在别的 ref 上手动跑);
③ 版本号 tag 已存在则保留原样、绝不覆盖(这正是「靠版本号拉旧版」能成立的前提)。
This commit is contained in:
1 parent
0c24398130
commit
cdd4eb7d2e
2 files changed
+47
-6
No files matched your search
@@ -993,10 +993,51 @@ jobs:
|
||||
set -euo pipefail
|
||||
# pin 从 Dockerfile 解析(不要再写死:曾经漂移过一次,把新镜像贴上了旧 pin 的 tag)
|
||||
PIN="${{ steps.pin.outputs.pin }}"
|
||||
docker buildx imagetools create \
|
||||
-t "${IMAGE}:latest" \
|
||||
-t "${IMAGE}:${PIN}" \
|
||||
"${IMAGE}:sha-${GITHUB_SHA}"
|
||||
echo "已把 sha-${GITHUB_SHA} 提升为 :latest 与 :${PIN}"
|
||||
|
||||
# ================= 版本号 tag(vX.Y.Z)=================
|
||||
# 目的(老师 2026-10-03 定):
|
||||
# · `latest` 永远 = master 最新正式版;
|
||||
# · 同时每个正式版都留一个**不可变**的版本号 tag,日后能靠它拉回旧正式版;
|
||||
# · **无论如何都不能靠版本号拉到 test 分支的镜像** —— 这不是靠约定,而是结构保证:
|
||||
# 本步骤的 if 里写死了 github.ref == 'refs/heads/master',分支构建根本执行不到这里。
|
||||
# 下面再加两道守卫,挡住「手动 workflow_dispatch 在别的 ref 上跑」这类旁路。
|
||||
#
|
||||
# 版本号来源 = 应用自己的 config/app.php(单一事实来源,避免 workflow 与代码漂移;
|
||||
# 与上面 PIN 从 Dockerfile 解析同一个原则)。
|
||||
VER=$(grep -oE "'version'[[:space:]]*=>[[:space:]]*'[^']+'" src/config/app.php \
|
||||
| head -1 | sed -E "s/.*'([^']+)'.*/\1/")
|
||||
[ -n "$VER" ] || { echo "::error::读不到 src/config/app.php 里的 version"; exit 1; }
|
||||
echo "本次版本号:$VER"
|
||||
# 守卫①:格式必须是 v<数字>.<数字>.<数字>,免得手滑写出怪 tag
|
||||
[[ "$VER" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|
||||
|| { echo "::error::版本号格式不对(期望 vX.Y.Z,实际 '$VER')"; exit 1; }
|
||||
|
||||
# 守卫②:这个 commit 必须真的在 master 上。
|
||||
# 只信 github.ref 不够 —— workflow_dispatch 可以在任意 ref 上手动触发。
|
||||
# 用 Compare API 判断(checkout 是浅克隆,本地 git 历史不足以做 merge-base)。
|
||||
# 以本 commit 为 base、master 为 head:identical(就是 master 顶端)或 ahead(master 更新)
|
||||
# 都说明本 commit 在 master 的历史里。
|
||||
CMP=$(curl -fsS \
|
||||
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"https://api.github.com/repos/${GITHUB_REPOSITORY}/compare/${GITHUB_SHA}...master" \
|
||||
| python3 -c 'import sys,json;print(json.load(sys.stdin).get("status",""))')
|
||||
case "$CMP" in
|
||||
identical|ahead) echo "守卫②通过:${GITHUB_SHA:0:12} 在 master 上(compare=$CMP)" ;;
|
||||
*) echo "::error::${GITHUB_SHA:0:12} 不在 master 上(compare=$CMP)—— 拒绝打版本号 tag"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# 守卫③:版本号 tag **不可变** —— 已存在就保留原样、绝不覆盖。
|
||||
# 这正是「靠版本号拉旧正式版」能成立的前提:老 tag 永远指向老镜像。
|
||||
TAGS=(-t "${IMAGE}:latest" -t "${IMAGE}:${PIN}")
|
||||
if docker buildx imagetools inspect "${IMAGE}:${VER}" >/dev/null 2>&1; then
|
||||
echo "::notice::${IMAGE}:${VER} 已存在 —— 保留原样,不覆盖(版本号 tag 不可变)"
|
||||
else
|
||||
TAGS+=(-t "${IMAGE}:${VER}")
|
||||
echo "将新建版本号 tag:${VER}"
|
||||
fi
|
||||
|
||||
docker buildx imagetools create "${TAGS[@]}" "${IMAGE}:sha-${GITHUB_SHA}"
|
||||
echo "已把 sha-${GITHUB_SHA} 提升为 latest + ${PIN} + 版本号 ${VER}"
|
||||
docker buildx imagetools inspect "${IMAGE}:latest" > /tmp/promoted.txt
|
||||
head -20 /tmp/promoted.txt
|
||||
+1
-1
@@ -213,6 +213,6 @@
|
||||
|
|
||||
*/
|
||||
|
||||
'version' => 'v3.5',
|
||||
'version' => 'v3.5.1',
|
||||
'author' => 'Mole404 & DeepSeek & Claude',
|
||||
];
|
||||
Reference in new issue
Block a user