比较提交
| 作者 | SHA1 | 提交日期 | |
|---|---|---|---|
|
|
4720149c20 |
@@ -8,6 +8,30 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [未发布]
|
||||||
|
|
||||||
|
### 发布流程修复:脚本从来没打过 git tag
|
||||||
|
|
||||||
|
- **问题**:`tools/push-all.sh` 里只有 `docker tag` + `docker push`,**没有 `git tag`**。
|
||||||
|
结果是远程仓库里**只有软件包、没有版本 tag** —— 「1.5.0 对应哪个提交」只能靠翻本文件猜,
|
||||||
|
想 checkout 某个已发布版本的代码没有可靠入口。镜像 tag 只说明「注册表里有这个包」,
|
||||||
|
它回答不了「这个包是哪份代码构建的」。
|
||||||
|
- **现在脚本会做三件事**:
|
||||||
|
1. **版本预检**(传了版本号时):从 `workbuddy_portal/__init__.py` 读 `__version__`
|
||||||
|
与传入值比对,不一致**立刻退出**。放在最前面,免得代码和镜像都推完了才发现
|
||||||
|
「代码里写着 1.4.0、却当 1.5.0 发」——那种错误只能靠改 tag 补救。
|
||||||
|
2. 代码与镜像都推成功后,打 `git tag -a vX.Y.Z` 并推送该 tag。放在最后是有意的:
|
||||||
|
tag 一旦出现在远端就是「这个版本发过了」的公开声明,不该先于产物出现。
|
||||||
|
3. 已存在的 tag **只提示、不改写** —— 指向哪个提交由历史决定,不该被脚本偷偷换掉。
|
||||||
|
- **补齐历史 tag**:`v1.2.0` / `v1.3.0` / `v1.4.0` 三个注解 tag 已按各自提交的
|
||||||
|
`__version__` 补打并推送(每个都指向引入该版本号的那个提交,可用
|
||||||
|
`git for-each-ref refs/tags` 复核)。1.1.0 在仓库里没有对应提交,故未补。
|
||||||
|
- **文档**:`docs/DEPLOYMENT.md` 第 7.1 节补上「为什么必须有 git tag」与版本预检说明;
|
||||||
|
第 7.4 节补上「镜像与 tag 要分别核验」的命令(`git ls-remote --tags origin`)——
|
||||||
|
此前 7.4 只验镜像,正是这个盲区让「没有 tag」一直没被发现。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## [1.5.0] — 2026-09-18
|
## [1.5.0] — 2026-09-18
|
||||||
|
|
||||||
**主题:按「将会被公网访问」重新审一遍界面与暴露面**
|
**主题:按「将会被公网访问」重新审一遍界面与暴露面**
|
||||||
|
|||||||
+31
-5
@@ -675,17 +675,30 @@ WB_TRUST_PROXY=1
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
export GITEA_TOKEN=<你的令牌>
|
export GITEA_TOKEN=<你的令牌>
|
||||||
tools/push-all.sh # 推 main 分支 + 镜像 latest
|
tools/push-all.sh # 推 main 分支 + 镜像 latest(不打版本 tag)
|
||||||
tools/push-all.sh 1.5.0 # 同时打一个版本 tag 并推送
|
tools/push-all.sh 1.5.0 # 另外打 git tag v1.5.0 与镜像 tag 1.5.0
|
||||||
```
|
```
|
||||||
|
|
||||||
脚本做的事:
|
脚本做的事:
|
||||||
|
|
||||||
1. `git push origin main` —— 用 `http.extraHeader` 传 Basic 认证,Token **只在环境变量里**,
|
1. **版本预检**(只有传了版本号时才做):从 `workbuddy_portal/__init__.py` 读
|
||||||
|
`__version__`,与传入的版本号比对,不一致**立刻退出**。放在最前面,免得代码和镜像
|
||||||
|
都推完了才发现「代码里写着 1.4.0,却当 1.5.0 发」——那种错误只能靠改 tag 补救。
|
||||||
|
2. `git push origin main` —— 用 `http.extraHeader` 传 Basic 认证,Token **只在环境变量里**,
|
||||||
不会写进 `.git/config`、URL 或 reflog;同时用 `-c credential.helper=` 屏蔽凭据助手
|
不会写进 `.git/config`、URL 或 reflog;同时用 `-c credential.helper=` 屏蔽凭据助手
|
||||||
(否则在非交互 / 无桌面会话里 Git Credential Manager 会挂住等弹窗)。
|
(否则在非交互 / 无桌面会话里 Git Credential Manager 会挂住等弹窗)。
|
||||||
2. `docker compose build` —— 镜像名本身就是注册表地址。
|
3. `docker compose build` —— 镜像名本身就是注册表地址。
|
||||||
3. `docker login` + `docker push`(`--password-stdin`,Token 不进命令行历史)。
|
4. `docker login` + `docker push`(`--password-stdin`,Token 不进命令行历史)。
|
||||||
|
5. **`git tag -a vX.Y.Z` + 推送该 tag** —— 放在最后,**只有代码与镜像都推成功才落 tag**。
|
||||||
|
tag 一旦出现在远端就是「这个版本发过了」的公开声明,不该先于产物出现。
|
||||||
|
已存在的 tag 只提示、不改写:指向哪个提交由历史决定,脚本不去偷偷换掉
|
||||||
|
「v1.5.0 到底是哪份代码」这个答案。
|
||||||
|
|
||||||
|
> **为什么必须有 git tag**:镜像 tag 只说明「注册表里有这个包」,不能回答
|
||||||
|
> 「这个包对应哪个提交」。只推镜像的话,远程仓库里永远是**只有软件包、没有版本 tag**,
|
||||||
|
> 事后想 checkout 某个版本的代码只能靠翻 CHANGELOG 猜。
|
||||||
|
> v1.5.0 之前的三个版本(1.2.0 / 1.3.0 / 1.4.0)已按各自提交的 `__version__` 补打了
|
||||||
|
> `v1.2.0` / `v1.3.0` / `v1.4.0` 注解 tag;1.1.0 没有对应的提交,故未补。
|
||||||
|
|
||||||
> 不用脚本、手工推也行:`git push origin main` 弹出凭据窗口时,用户名填 `wangchuanli`,
|
> 不用脚本、手工推也行:`git push origin main` 弹出凭据窗口时,用户名填 `wangchuanli`,
|
||||||
> **密码处填 Access Token**(不是网页登录密码)。
|
> **密码处填 Access Token**(不是网页登录密码)。
|
||||||
@@ -728,6 +741,19 @@ curl -s -u wangchuanli:TOKEN \
|
|||||||
https://git.iwali.top/api/v1/packages/wangchuanli?type=container
|
https://git.iwali.top/api/v1/packages/wangchuanli?type=container
|
||||||
```
|
```
|
||||||
|
|
||||||
|
镜像与 **git tag 要分别核验** —— 两者是两套东西,只推镜像时 git 侧会静默地什么都没有:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 远端有哪些版本 tag(读权限即可,不需要 Token)
|
||||||
|
git ls-remote --tags origin
|
||||||
|
|
||||||
|
# 标签指向哪个提交(^(commit) 前缀可看到标签解引用后的提交)
|
||||||
|
git ls-remote --tags origin 'refs/tags/*^{}'
|
||||||
|
|
||||||
|
# 本地核对「版本号 ↔ 提交」是否对得上
|
||||||
|
git for-each-ref refs/tags --format="%(refname:short) -> %(*objectname:short) %(*subject)"
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 八、备份与恢复
|
## 八、备份与恢复
|
||||||
|
|||||||
+52
-3
@@ -3,11 +3,11 @@
|
|||||||
# Copyright (c) 2026 Wang Chuanli
|
# Copyright (c) 2026 Wang Chuanli
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# 用 Gitea Access Token 一次性完成:推代码 + 推镜像
|
# 用 Gitea Access Token 一次性完成:推代码 + 推镜像(+ 打 git 版本 tag)
|
||||||
#
|
#
|
||||||
# export GITEA_TOKEN=<在 Gitea「设置 → 应用 → 生成令牌」创建,勾 repo + write:package>
|
# export GITEA_TOKEN=<在 Gitea「设置 → 应用 → 生成令牌」创建,勾 repo + write:package>
|
||||||
# tools/push-all.sh # 推 main + 镜像 latest
|
# tools/push-all.sh # 推 main + 镜像 latest,不打版本 tag
|
||||||
# tools/push-all.sh 1.1.0 # 额外打一个版本 tag 并推送
|
# tools/push-all.sh 1.5.0 # 另外打 git tag v1.5.0 与镜像 tag 1.5.0
|
||||||
#
|
#
|
||||||
# 设计要点:
|
# 设计要点:
|
||||||
# * Token **只从环境变量读**,绝不写进 .git/config、URL 或任何文件。
|
# * Token **只从环境变量读**,绝不写进 .git/config、URL 或任何文件。
|
||||||
@@ -17,6 +17,11 @@
|
|||||||
# (不会落到 reflog / 进程列表里)。
|
# (不会落到 reflog / 进程列表里)。
|
||||||
# * git.iwali.top 有 Let's Encrypt 通配证书,**HTTPS 可用**,
|
# * git.iwali.top 有 Let's Encrypt 通配证书,**HTTPS 可用**,
|
||||||
# 所以镜像不需要配 insecure-registries。
|
# 所以镜像不需要配 insecure-registries。
|
||||||
|
#
|
||||||
|
# v1.5.0 起补上了 **git tag**(第 0 步与第 4 步):
|
||||||
|
# 在此之前脚本只打镜像 tag,于是远程仓库里永远只有软件包、没有 git tag ——
|
||||||
|
# 「某个版本对应哪个提交」只能靠翻 CHANGELOG 猜。现在版本号从
|
||||||
|
# `workbuddy_portal/__init__.py` 读,发布前先与前缀 v 的字面量对齐。
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
@@ -25,12 +30,30 @@ USER="${GITEA_USER:-wangchuanli}"
|
|||||||
REPO="${GITEA_REPO:-workbuddy-portal}"
|
REPO="${GITEA_REPO:-workbuddy-portal}"
|
||||||
BRANCH="${GITEA_BRANCH:-main}"
|
BRANCH="${GITEA_BRANCH:-main}"
|
||||||
TAG="${1:-}"
|
TAG="${1:-}"
|
||||||
|
GIT_TAG=""
|
||||||
IMAGE="$HOST/$USER/$REPO"
|
IMAGE="$HOST/$USER/$REPO"
|
||||||
|
|
||||||
: "${GITEA_TOKEN:?请先 export GITEA_TOKEN=<Gitea Access Token(repo + write:package)>}"
|
: "${GITEA_TOKEN:?请先 export GITEA_TOKEN=<Gitea Access Token(repo + write:package)>}"
|
||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
# ---------- 0. 版本一致性预检(早失败,别等代码和镜像都推完了才发现) ----------
|
||||||
|
if [ -n "$TAG" ]; then
|
||||||
|
GIT_TAG="v$TAG"
|
||||||
|
CODE_VER="$(sed -n 's/^__version__[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' \
|
||||||
|
workbuddy_portal/__init__.py | head -n 1)"
|
||||||
|
if [ "$CODE_VER" != "$TAG" ]; then
|
||||||
|
echo "ERROR: 代码里的版本是「$CODE_VER」,与要发布的「$TAG」不一致。" >&2
|
||||||
|
echo " 发布前请先把这四处改成同一个版本号(tools/check_docs.py 会校验):" >&2
|
||||||
|
echo " workbuddy_portal/__init__.py __version__" >&2
|
||||||
|
echo " Dockerfile org.opencontainers.image.version" >&2
|
||||||
|
echo " README.md 特性表里的 | 版本 | vX.Y.Z |" >&2
|
||||||
|
echo " docs/CHANGELOG.md 首个 ## [X.Y.Z] 标题" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "==> 版本预检通过:代码与要发布的版本都是 $TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
# ---------- 1. 推代码 ----------
|
# ---------- 1. 推代码 ----------
|
||||||
echo "==> 推送代码到 https://$HOST/$USER/$REPO.git ($BRANCH)"
|
echo "==> 推送代码到 https://$HOST/$USER/$REPO.git ($BRANCH)"
|
||||||
AUTH="$(printf '%s:%s' "$USER" "$GITEA_TOKEN" | base64 | tr -d '\r\n')"
|
AUTH="$(printf '%s:%s' "$USER" "$GITEA_TOKEN" | base64 | tr -d '\r\n')"
|
||||||
@@ -55,6 +78,32 @@ if [ -n "$TAG" ]; then
|
|||||||
docker push "$IMAGE:$TAG"
|
docker push "$IMAGE:$TAG"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------- 4. git 版本 tag ----------
|
||||||
|
# 放在最后:**只有代码与镜像都推成功**才落 tag。
|
||||||
|
# tag 一旦出现在远端就是「这个版本发过了」的公开声明,不该先于产物出现。
|
||||||
|
if [ -n "$GIT_TAG" ]; then
|
||||||
|
if git rev-parse -q --verify "refs/tags/$GIT_TAG" >/dev/null; then
|
||||||
|
# 已存在就只提示、不报错:典型场景是「tag 早就打好了,这次只是补推代码」。
|
||||||
|
# 指向哪个提交由 git 决定,脚本不去改写已发布的 tag —— 那等于偷偷换掉
|
||||||
|
# 「v1.5.0 到底是哪份代码」这个答案。
|
||||||
|
AT="$(git rev-parse --short "$GIT_TAG^{commit}")"
|
||||||
|
HEAD_SHORT="$(git rev-parse --short HEAD)"
|
||||||
|
echo "==> git tag $GIT_TAG 已存在(指向 $AT)"
|
||||||
|
[ "$AT" = "$HEAD_SHORT" ] || echo " 注意:它不是当前 HEAD($HEAD_SHORT)—— 若这次改了代码,tag 不会跟着动。"
|
||||||
|
else
|
||||||
|
echo "==> 创建 git 注解 tag $GIT_TAG"
|
||||||
|
git tag -a "$GIT_TAG" -m "$REPO $GIT_TAG"
|
||||||
|
fi
|
||||||
|
echo "==> 推送 git tag $GIT_TAG"
|
||||||
|
git -c credential.helper= \
|
||||||
|
-c http.extraHeader="Authorization: Basic $AUTH" \
|
||||||
|
push origin "refs/tags/$GIT_TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "完成。其他机器拉取:"
|
echo "完成。其他机器拉取:"
|
||||||
echo " docker pull $IMAGE:${TAG:-latest}"
|
echo " docker pull $IMAGE:${TAG:-latest}"
|
||||||
|
if [ -n "$GIT_TAG" ]; then
|
||||||
|
echo "代码检出该版本:"
|
||||||
|
echo " git fetch --tags && git checkout $GIT_TAG"
|
||||||
|
fi
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户