From 014e88afaa19522ef6c1598820b563699d316bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8E=86=E5=86=B0=E9=83=81-hermes=E7=89=88?= Date: Wed, 6 May 2026 17:23:06 +0800 Subject: [PATCH] ci: allow api env update via sudo --- scripts/deploy/production-api-deploy.sh | 86 ++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 10 deletions(-) diff --git a/scripts/deploy/production-api-deploy.sh b/scripts/deploy/production-api-deploy.sh index 30c26e0f..55601b18 100644 --- a/scripts/deploy/production-api-deploy.sh +++ b/scripts/deploy/production-api-deploy.sh @@ -37,21 +37,87 @@ write_env_value() { local file_path="$1" local key="$2" local value="$3" - local temp_path - mkdir -p "$(dirname "${file_path}")" - touch "${file_path}" - temp_path="$(mktemp)" + local can_write_direct=0 - if grep -qE "^${key}=" "${file_path}"; then - sed -E "s|^${key}=.*|${key}=${value}|" "${file_path}" >"${temp_path}" + if [[ -e "${file_path}" ]]; then + [[ -w "${file_path}" ]] && can_write_direct=1 else - cp "${file_path}" "${temp_path}" - printf "%s=%s\n" "${key}" "${value}" >>"${temp_path}" + mkdir -p "$(dirname "${file_path}")" + [[ -w "$(dirname "${file_path}")" ]] && can_write_direct=1 fi - cat "${temp_path}" >"${file_path}" - rm -f "${temp_path}" + # api-server 环境文件通常由 server-provision 以 root:root 0600 创建。 + # 发布流水线可能以非 root Jenkins 用户运行,因此仅在不能直接写入时使用 sudo -n,避免因为 env 文件权限导致 API 发布中断。 + if [[ "$(id -u)" -eq 0 || "${can_write_direct}" -eq 1 ]]; then + python3 - "${file_path}" "${key}" "${value}" <<'PY' +import os +import sys +from pathlib import Path + +file_path = Path(sys.argv[1]) +key = sys.argv[2] +value = sys.argv[3] +was_missing = not file_path.exists() +file_path.parent.mkdir(parents=True, exist_ok=True) + +lines = [] +if file_path.exists(): + lines = file_path.read_text(encoding="utf-8").splitlines() + +updated = False +next_lines = [] +for line in lines: + if line.startswith(f"{key}="): + next_lines.append(f"{key}={value}") + updated = True + else: + next_lines.append(line) + +if not updated: + next_lines.append(f"{key}={value}") + +file_path.write_text("\n".join(next_lines) + "\n", encoding="utf-8") +if was_missing: + os.chmod(file_path, 0o600) +PY + else + if ! sudo -n true >/dev/null 2>&1; then + echo "[production-api-deploy] 当前用户无权写入 ${file_path},且 sudo -n 不可用;请给部署用户配置免密写入该环境文件或以 root 执行发布。" >&2 + exit 1 + fi + sudo -n python3 - "${file_path}" "${key}" "${value}" <<'PY' +import os +import sys +from pathlib import Path + +file_path = Path(sys.argv[1]) +key = sys.argv[2] +value = sys.argv[3] +was_missing = not file_path.exists() +file_path.parent.mkdir(parents=True, exist_ok=True) + +lines = [] +if file_path.exists(): + lines = file_path.read_text(encoding="utf-8").splitlines() + +updated = False +next_lines = [] +for line in lines: + if line.startswith(f"{key}="): + next_lines.append(f"{key}={value}") + updated = True + else: + next_lines.append(line) + +if not updated: + next_lines.append(f"{key}={value}") + +file_path.write_text("\n".join(next_lines) + "\n", encoding="utf-8") +if was_missing: + os.chmod(file_path, 0o600) +PY + fi } SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"