fix(deploy): 把 WECHAT_MINI_SUBSCRIBE_TEMPLATES 加进 ENV_PAYLOAD(远端 unbound variable)

上一次只补了 step 的 env: 映射,但那只是【本地】runner 侧;
远端脚本的变量是靠 ENV_PAYLOAD 逐个 export 过去的。于是远端
set -euxo pipefail 读到未定义的  直接退出:
  bash: line 71: WECHAT_MINI_SUBSCRIBE_TEMPLATES: unbound variable
部署到生产服务器这一步就这样挂了。

现在两处都齐:step env: 映射 + ENV_PAYLOAD 的 export(并用  兜底,
Secret 没配也不会 unbound)。

验证(Git Bash 实测):
- printf 占位符 21 个 vs 参数 21 个一致,payload 含新变量
- source 生成的 env 脚本(set -u)→ 变量有定义、JSON 原样保留
- Secret 为空 → 定义为空字符串,同样安全
- 另外扫了整个远端脚本:引用的 29 个大写变量都有来源(payload 或自赋值)
This commit is contained in:
2026-09-27 15:37:58 +08:00
parent 64a81393b5
commit 17f2aa7fcd
+7 -3
View File
@@ -899,14 +899,15 @@ jobs:
ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "whoami; docker --version; docker compose version" ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "whoami; docker --version; docker compose version"
ENV_SH="/tmp/deploy_env_$$" ENV_SH="/tmp/deploy_env_$$"
ENV_PAYLOAD="$(printf 'export IMAGE_NEW=%q\nexport IMAGE_LATEST=%q\nexport DEPLOY_PATH=%q\nexport GITEA_HOST=%q\nexport GH_PROXY_PREFIX=%q\nexport REGISTRY_PULL_USER=%q\nexport REGISTRY_PULL_TOKEN=%q\nexport IMAGE_NAME=%q\nexport NUXT_PUBLIC_SITE_URL=%q\nexport GITHUB_SERVER_URL=%q\nexport GITHUB_REPOSITORY=%q\nexport GITHUB_REF_NAME=%q\nexport OAUTH_REDIRECT_URI=%q\nexport OAUTH_STATE_SECRET=%q\nexport AGGREGATE_OAUTH_APP_ID=%q\nexport AGGREGATE_OAUTH_APP_KEY=%q\nexport AGGREGATE_OAUTH_LOGIN_TYPE=%q\nexport AGGREGATE_OAUTH_ENDPOINT=%q\nexport WECHAT_MINI_APPID=%q\nexport WECHAT_MINI_SECRET=%q\n' \ ENV_PAYLOAD="$(printf 'export IMAGE_NEW=%q\nexport IMAGE_LATEST=%q\nexport DEPLOY_PATH=%q\nexport GITEA_HOST=%q\nexport GH_PROXY_PREFIX=%q\nexport REGISTRY_PULL_USER=%q\nexport REGISTRY_PULL_TOKEN=%q\nexport IMAGE_NAME=%q\nexport NUXT_PUBLIC_SITE_URL=%q\nexport GITHUB_SERVER_URL=%q\nexport GITHUB_REPOSITORY=%q\nexport GITHUB_REF_NAME=%q\nexport OAUTH_REDIRECT_URI=%q\nexport OAUTH_STATE_SECRET=%q\nexport AGGREGATE_OAUTH_APP_ID=%q\nexport AGGREGATE_OAUTH_APP_KEY=%q\nexport AGGREGATE_OAUTH_LOGIN_TYPE=%q\nexport AGGREGATE_OAUTH_ENDPOINT=%q\nexport WECHAT_MINI_APPID=%q\nexport WECHAT_MINI_SECRET=%q\nexport WECHAT_MINI_SUBSCRIBE_TEMPLATES=%q\n' \
"${IMAGE_NEW}" "${IMAGE_LATEST}" "${DEPLOY_PATH}" "${GITEA_HOST}" "${GH_PROXY_PREFIX}" \ "${IMAGE_NEW}" "${IMAGE_LATEST}" "${DEPLOY_PATH}" "${GITEA_HOST}" "${GH_PROXY_PREFIX}" \
"${REGISTRY_PULL_USER}" "${REGISTRY_PULL_TOKEN}" "${IMAGE_NAME}" "${NUXT_PUBLIC_SITE_URL}" \ "${REGISTRY_PULL_USER}" "${REGISTRY_PULL_TOKEN}" "${IMAGE_NAME}" "${NUXT_PUBLIC_SITE_URL}" \
"${GITHUB_SERVER_URL}" "${GITHUB_REPOSITORY}" "${GITHUB_REF_NAME}" \ "${GITHUB_SERVER_URL}" "${GITHUB_REPOSITORY}" "${GITHUB_REF_NAME}" \
"${OAUTH_REDIRECT_URI}" "${OAUTH_STATE_SECRET}" \ "${OAUTH_REDIRECT_URI}" "${OAUTH_STATE_SECRET}" \
"${AGGREGATE_OAUTH_APP_ID}" "${AGGREGATE_OAUTH_APP_KEY}" \ "${AGGREGATE_OAUTH_APP_ID}" "${AGGREGATE_OAUTH_APP_KEY}" \
"${AGGREGATE_OAUTH_LOGIN_TYPE}" "${AGGREGATE_OAUTH_ENDPOINT}" \ "${AGGREGATE_OAUTH_LOGIN_TYPE}" "${AGGREGATE_OAUTH_ENDPOINT}" \
"${WECHAT_MINI_APPID}" "${WECHAT_MINI_SECRET}")" "${WECHAT_MINI_APPID}" "${WECHAT_MINI_SECRET}" \
"${WECHAT_MINI_SUBSCRIBE_TEMPLATES:-}")"
printf '%s' "${ENV_PAYLOAD}" | ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "cat > ${ENV_SH}" printf '%s' "${ENV_PAYLOAD}" | ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "cat > ${ENV_SH}"
echo "[Deploy] env script written to ${ENV_SH} on remote" echo "[Deploy] env script written to ${ENV_SH} on remote"
ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "set -e; ls -la ${ENV_SH}; grep -q IMAGE_NEW ${ENV_SH} && echo '[Deploy] env_sh IMAGE_NEW line OK'" ssh "${SSH_OPTS[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "set -e; ls -la ${ENV_SH}; grep -q IMAGE_NEW ${ENV_SH} && echo '[Deploy] env_sh IMAGE_NEW line OK'"
@@ -993,7 +994,10 @@ jobs:
upsert_env_key WECHAT_MINI_SECRET "${WECHAT_MINI_SECRET}" || MERGE_OK=0 upsert_env_key WECHAT_MINI_SECRET "${WECHAT_MINI_SECRET}" || MERGE_OK=0
# 微信订阅消息模板(JSON)。仓库 Secret 里没设这项时 upsert_env_key 直接返回, # 微信订阅消息模板(JSON)。仓库 Secret 里没设这项时 upsert_env_key 直接返回,
# 不会清掉服务器 .env 里手工配置的值。 # 不会清掉服务器 .env 里手工配置的值。
upsert_env_key WECHAT_MINI_SUBSCRIBE_TEMPLATES "${WECHAT_MINI_SUBSCRIBE_TEMPLATES}" || MERGE_OK=0 # ⚠️ 变量必须同时在【本 step 的 env:】【ENV_PAYLOAD 的 export 列表】两处出现:
# 远端脚本是 `set -euxo pipefail`,只在一处声明 → 另一端就是 unbound variable,
# 整个部署会在这里挂掉(第 90 轮踩过)。这里再补 `:-` 兜底。
upsert_env_key WECHAT_MINI_SUBSCRIBE_TEMPLATES "${WECHAT_MINI_SUBSCRIBE_TEMPLATES:-}" || MERGE_OK=0
rm -f "${ENV_FILE}.tmp.$$" rm -f "${ENV_FILE}.tmp.$$"
if [ "${MERGE_OK}" = "1" ]; then if [ "${MERGE_OK}" = "1" ]; then
echo "[Runtime-env] 运行期配置已合并写入 ${ENV_FILE}(OAuth=${AGGREGATE_OAUTH_APP_ID:+已配置} WECHAT_MINI_APPID=${WECHAT_MINI_APPID:+已配置})" echo "[Runtime-env] 运行期配置已合并写入 ${ENV_FILE}(OAuth=${AGGREGATE_OAUTH_APP_ID:+已配置} WECHAT_MINI_APPID=${WECHAT_MINI_APPID:+已配置})"