feat(微信订阅): 接入歌曲排期模板并加固部署流程
订阅消息(小程序侧唯一能主动触达用户的通道): - 新增 server/utils/wechatSubscribeFields.ts:按微信字段类型裁剪值(thing≤20、 phrase 必须 5 个汉字、time/date/character_string 各自上限),空白压成一行, 北京时间 time 由 playTime 的开始时间生成,解析不出退化为当天 00:00。 - wechatSubscribeService 内置 SONG_SELECTED 模板(站长新给的那个模板 ID), 并转发上述纯函数;notificationService.createSongSelectedNotification 现在会带上 playDate/playTime/sequence,三个排期接口(schedule / publish / bulk-publish)补传 sequence。 - 新增 test/wechatSubscribeFields.test.mjs(10 例,node --test 全绿)。 - test-subscribe 管理接口支持 vars 覆盖并返回真实发送值,方便站长核对字段名。 部署流程(Gitea Actions 容器里没有 buildx 插件,旧流程在此硬失败): - 每个 job 各自安装/探测 docker-buildx(v0.19.3,走 gh-proxy 再退直连), 不把 `buildx version` 当唯一依据;装不上时降级为普通 `docker build` 继续发布, 不再因为缺插件整条流水线失败。 注意:SONG_SELECTED 的字段名(thing2/date4/time1/character_string3/phrase5)是按常见 命名推断的,需在公众平台后台核对;不一致时用环境变量覆盖,模板 ID 变更后老用户需重新授权。
This commit is contained in:
+172
-23
@@ -519,7 +519,63 @@ jobs:
|
||||
echo "环境准备完成"
|
||||
cat /etc/os-release 2>/dev/null | head -4 || true
|
||||
docker --version
|
||||
docker buildx version || echo "buildx 未安装"
|
||||
docker buildx version 2>&1 | head -1 || echo "buildx 子命令不可用"
|
||||
|
||||
- name: 确保 Docker Buildx 插件可用(缺失则装官方插件,否则回退 docker build)
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
||||
# 症状:`docker buildx create --name xxx` 报
|
||||
# unknown flag: --name / See 'docker --help'
|
||||
# 打出的是 docker 的总帮助 → 说明 `buildx` 子命令没落到真插件上,docker CLI 把
|
||||
# `--name` 当自己的顶层 flag 解析了。这里先探一次并按需装官方插件,不能等 build-image
|
||||
# 作业才炸(各 job 是独立容器,装了也得在该 job 里再装一次)。
|
||||
ensure_buildx() {
|
||||
# 不用 `docker buildx version` 当唯一依据:这种“子命令没落到真插件上”的坏状态里
|
||||
# 它仍可能返回 0。优先相信插件文件在位,其次才信命令。
|
||||
if [ -x "${HOME}/.docker/cli-plugins/docker-buildx" ] \
|
||||
|| [ -x /usr/local/lib/docker/cli-plugins/docker-buildx ] \
|
||||
|| { docker buildx version >/dev/null 2>&1 && docker buildx create --help 2>/dev/null | grep -q -- '--name'; }; then
|
||||
echo "[buildx] 插件可用:$(docker buildx version 2>&1 | head -1)"
|
||||
return 0
|
||||
fi
|
||||
echo "[buildx] 未发现可用插件,从官方 release 安装"
|
||||
ARCH="$(uname -m)"
|
||||
case "${ARCH}" in
|
||||
x86_64|amd64) BUILDX_ARCH=amd64 ;;
|
||||
aarch64|arm64) BUILDX_ARCH=arm64 ;;
|
||||
*) echo "[buildx] 不支持的架构 ${ARCH},跳过安装"; return 1 ;;
|
||||
esac
|
||||
BUILDX_VER="v0.19.3"
|
||||
BUILDX_BIN="buildx-${BUILDX_VER}.linux-${BUILDX_ARCH}"
|
||||
BUILDX_DIR="${HOME}/.docker/cli-plugins"
|
||||
mkdir -p "${BUILDX_DIR}"
|
||||
if curl -fsSL --retry 3 --connect-timeout 20 -o "${BUILDX_DIR}/docker-buildx" \
|
||||
"${GH_PROXY_PREFIX}https://github.com/docker/buildx/releases/download/${BUILDX_VER}/${BUILDX_BIN}" \
|
||||
|| curl -fsSL --retry 3 --connect-timeout 20 -o "${BUILDX_DIR}/docker-buildx" \
|
||||
"https://github.com/docker/buildx/releases/download/${BUILDX_VER}/${BUILDX_BIN}"; then
|
||||
chmod +x "${BUILDX_DIR}/docker-buildx"
|
||||
echo "[buildx] 已安装到 ${BUILDX_DIR}/docker-buildx"
|
||||
else
|
||||
rm -f "${BUILDX_DIR}/docker-buildx"
|
||||
echo "[buildx] 下载失败(GitHub 与 ${GH_PROXY_PREFIX} 都不通)"
|
||||
fi
|
||||
if ! docker buildx version >/dev/null 2>&1 && command -v sudo >/dev/null 2>&1; then
|
||||
echo "[buildx] 当前 docker 不认 ~/.docker/cli-plugins,改写系统插件目录"
|
||||
sudo mkdir -p /usr/local/lib/docker/cli-plugins
|
||||
sudo cp -f "${BUILDX_DIR}/docker-buildx" /usr/local/lib/docker/cli-plugins/docker-buildx 2>/dev/null || true
|
||||
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx 2>/dev/null || true
|
||||
fi
|
||||
[ -x "${BUILDX_DIR}/docker-buildx" ] || [ -x /usr/local/lib/docker/cli-plugins/docker-buildx ]
|
||||
}
|
||||
|
||||
if ensure_buildx && docker buildx create --help 2>/dev/null | grep -q -- '--name'; then
|
||||
echo "[buildx] 自检通过(create 支持 --name)"
|
||||
echo "BUILDX_INSTALLED=yes" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "[buildx] 自检未通过,镜像构建作业将自动回退 docker build(不阻塞部署)"
|
||||
echo "BUILDX_INSTALLED=no" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: 检出代码
|
||||
run: |
|
||||
@@ -669,7 +725,61 @@ jobs:
|
||||
BRANCH="${GITHUB_REF_NAME:-main}"
|
||||
git clone --depth 1 -b "${BRANCH}" "${REPO_URL}" .
|
||||
|
||||
- name: 初始化 Docker Buildx builder (为本作业重新创建)
|
||||
- name: 确保 Docker Buildx 插件可用(本作业容器内独立安装)
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
||||
# 每个 job 跑在独立容器里,meta-warmup 装的插件这里看不到,必须自己再确保一次。
|
||||
# 症状回顾:`docker buildx create --name xxx` 报 unknown flag: --name(打出的是 docker
|
||||
# 总帮助)→ buildx 子命令没落到真插件上。装完仍不可用则不报错,交给后面的 docker build 兜底。
|
||||
# 判定同 meta-warmup:优先看插件文件是否在位,不把 `docker buildx version` 当唯一依据。
|
||||
if [ -x "${HOME}/.docker/cli-plugins/docker-buildx" ] \
|
||||
|| [ -x /usr/local/lib/docker/cli-plugins/docker-buildx ] \
|
||||
|| { docker buildx version >/dev/null 2>&1 && docker buildx create --help 2>/dev/null | grep -q -- '--name'; }; then
|
||||
echo "[buildx] 插件已可用:$(docker buildx version 2>&1 | head -1)"
|
||||
echo "BUILDX_USABLE=yes" >> "$GITHUB_ENV"
|
||||
exit 0
|
||||
fi
|
||||
echo "[buildx] 未发现可用插件,从官方 release 安装"
|
||||
ARCH="$(uname -m)"
|
||||
case "${ARCH}" in
|
||||
x86_64|amd64) BUILDX_ARCH=amd64 ;;
|
||||
aarch64|arm64) BUILDX_ARCH=arm64 ;;
|
||||
*) echo "[buildx] 不支持的架构 ${ARCH}"; echo "BUILDX_USABLE=no" >> "$GITHUB_ENV"; exit 0 ;;
|
||||
esac
|
||||
BUILDX_VER="v0.19.3"
|
||||
BUILDX_BIN="buildx-${BUILDX_VER}.linux-${BUILDX_ARCH}"
|
||||
BUILDX_DIR="${HOME}/.docker/cli-plugins"
|
||||
mkdir -p "${BUILDX_DIR}"
|
||||
if curl -fsSL --retry 3 --connect-timeout 20 -o "${BUILDX_DIR}/docker-buildx" \
|
||||
"${GH_PROXY_PREFIX}https://github.com/docker/buildx/releases/download/${BUILDX_VER}/${BUILDX_BIN}" \
|
||||
|| curl -fsSL --retry 3 --connect-timeout 20 -o "${BUILDX_DIR}/docker-buildx" \
|
||||
"https://github.com/docker/buildx/releases/download/${BUILDX_VER}/${BUILDX_BIN}"; then
|
||||
chmod +x "${BUILDX_DIR}/docker-buildx"
|
||||
echo "[buildx] 已安装到 ${BUILDX_DIR}/docker-buildx"
|
||||
else
|
||||
rm -f "${BUILDX_DIR}/docker-buildx"
|
||||
echo "[buildx] 下载失败(GitHub 与 ${GH_PROXY_PREFIX} 都不通)"
|
||||
fi
|
||||
if ! docker buildx version >/dev/null 2>&1 && command -v sudo >/dev/null 2>&1; then
|
||||
sudo mkdir -p /usr/local/lib/docker/cli-plugins
|
||||
sudo cp -f "${BUILDX_DIR}/docker-buildx" /usr/local/lib/docker/cli-plugins/docker-buildx 2>/dev/null || true
|
||||
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx 2>/dev/null || true
|
||||
fi
|
||||
if [ -x "${BUILDX_DIR}/docker-buildx" ] || [ -x /usr/local/lib/docker/cli-plugins/docker-buildx ]; then
|
||||
if docker buildx create --help 2>/dev/null | grep -q -- '--name'; then
|
||||
echo "[buildx] 自检通过"
|
||||
echo "BUILDX_USABLE=yes" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "[buildx] 插件在位但 create 仍不认识 --name,改用 docker build 兜底"
|
||||
echo "BUILDX_USABLE=no" >> "$GITHUB_ENV"
|
||||
fi
|
||||
else
|
||||
echo "[buildx] 安装未成功,改用 docker build 兜底"
|
||||
echo "BUILDX_USABLE=no" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: 初始化 Docker Buildx builder (为本作业重新创建,不可用则回退 docker build)
|
||||
env:
|
||||
REGISTRY_USER: ${{ secrets.REGISTRY_USER || github.actor }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN || github.token }}
|
||||
@@ -708,17 +818,35 @@ jobs:
|
||||
done
|
||||
[ "${PULLED}" = "1" ] || { echo "ERROR: 无法拉取 buildkitd 基础镜像"; exit 1; }
|
||||
printf '%s' "${REGISTRY_TOKEN}" | docker login "${GITEA_HOST}" -u "${REGISTRY_USER}" --password-stdin
|
||||
|
||||
# buildx 插件不可用时(`docker buildx create --name` 报 unknown flag: --name,
|
||||
# 说明子命令没落到真插件上),不再硬失败,转用普通 docker build 继续部署。
|
||||
if [ "${BUILDX_USABLE:-no}" != "yes" ] \
|
||||
|| ! docker buildx version >/dev/null 2>&1 \
|
||||
|| ! docker buildx create --help 2>/dev/null | grep -q -- '--name'; then
|
||||
echo "[buildx] 本作业不可用,跳过 builder 初始化,将由 docker build 回退构建"
|
||||
echo "BUILDX_USABLE=no" >> "$GITHUB_ENV"
|
||||
rm -f "${BKK_CFG}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
docker buildx rm "${BUILDER_NAME}" 2>/dev/null || true
|
||||
docker buildx create \
|
||||
--name "${BUILDER_NAME}" \
|
||||
--driver docker-container \
|
||||
--use \
|
||||
--config "${BKK_CFG}" \
|
||||
--buildkitd-flags '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host' \
|
||||
--driver-opt network=host \
|
||||
--driver-opt "image=${BUILDKIT_IMAGE}"
|
||||
if docker buildx create \
|
||||
--name "${BUILDER_NAME}" \
|
||||
--driver docker-container \
|
||||
--use \
|
||||
--config "${BKK_CFG}" \
|
||||
--buildkitd-flags '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host' \
|
||||
--driver-opt network=host \
|
||||
--driver-opt "image=${BUILDKIT_IMAGE}" \
|
||||
&& docker buildx inspect --bootstrap; then
|
||||
echo "[buildx] builder ${BUILDER_NAME} 就绪,使用 buildx 构建(含分层缓存)"
|
||||
echo "BUILDX_USABLE=yes" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "[buildx] builder 创建或启动失败,回退 docker build(不使用分层缓存)"
|
||||
echo "BUILDX_USABLE=no" >> "$GITHUB_ENV"
|
||||
fi
|
||||
rm -f "${BKK_CFG}"
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
- name: 复用 meta-warmup 结果(与 Preflight 并发省 ~5min)
|
||||
run: |
|
||||
@@ -777,18 +905,39 @@ jobs:
|
||||
echo "使用 BuildKit 分层缓存加速(默认不写 --no-cache)"
|
||||
fi
|
||||
|
||||
docker buildx build \
|
||||
--file ./Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
--load \
|
||||
--provenance=false \
|
||||
"${BUILD_ARGS[@]}" \
|
||||
--tag "${IMG_FULL}" \
|
||||
--tag "${IMG_LATEST}" \
|
||||
--label "org.opencontainers.image.source=${OCS_SOURCE}" \
|
||||
--label "org.opencontainers.image.revision=${OCS_REVISION}" \
|
||||
--label "org.opencontainers.image.created=${OCS_CREATED}" \
|
||||
.
|
||||
# BUILDX_USABLE 由「初始化 Docker Buildx builder」步骤写入 GITHUB_ENV:
|
||||
# yes → buildx(分层缓存 + --load 打进本地 daemon)
|
||||
# no → 普通 docker build 兜底(无分层缓存;依赖 daemon.json 的 registry-mirrors
|
||||
# 或 Dockerfile 里的 DOCKER_MIRROR build-arg 拉基础镜像)
|
||||
# 注意:--provenance 只有 buildx 认,回退时必须去掉。
|
||||
if [ "${BUILDX_USABLE:-yes}" = "yes" ]; then
|
||||
echo "[build] 使用 docker buildx build"
|
||||
docker buildx build \
|
||||
--file ./Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
--load \
|
||||
--provenance=false \
|
||||
"${BUILD_ARGS[@]}" \
|
||||
--tag "${IMG_FULL}" \
|
||||
--tag "${IMG_LATEST}" \
|
||||
--label "org.opencontainers.image.source=${OCS_SOURCE}" \
|
||||
--label "org.opencontainers.image.revision=${OCS_REVISION}" \
|
||||
--label "org.opencontainers.image.created=${OCS_CREATED}" \
|
||||
.
|
||||
else
|
||||
echo "[build] buildx 不可用,回退 docker build(生效的 mirror 由 daemon.json 决定)"
|
||||
docker info 2>/dev/null | sed -n '/Registry Mirrors/,/^$/p' || true
|
||||
docker build \
|
||||
--file ./Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
"${BUILD_ARGS[@]}" \
|
||||
--tag "${IMG_FULL}" \
|
||||
--tag "${IMG_LATEST}" \
|
||||
--label "org.opencontainers.image.source=${OCS_SOURCE}" \
|
||||
--label "org.opencontainers.image.revision=${OCS_REVISION}" \
|
||||
--label "org.opencontainers.image.created=${OCS_CREATED}" \
|
||||
.
|
||||
fi
|
||||
|
||||
docker image inspect "${IMG_FULL}" >/dev/null
|
||||
docker image inspect "${IMG_LATEST}" >/dev/null
|
||||
|
||||
Reference in New Issue
Block a user