This commit is contained in:
@@ -93,6 +93,8 @@
|
|||||||
|
|
||||||
`api-server` 不放入 Docker,也不直接暴露公网端口。发布时替换版本目录并重启 `genarrative-api.service`。
|
`api-server` 不放入 Docker,也不直接暴露公网端口。发布时替换版本目录并重启 `genarrative-api.service`。
|
||||||
|
|
||||||
|
全量发布流水线的 `DATABASE` 参数必须同时传给 Stdb 发布和 API 发布:Stdb 发布负责把 wasm 发布到目标数据库,API 发布必须在重启 `genarrative-api.service` 前把同一个库名写入 `/etc/genarrative/api-server.env` 的 `GENARRATIVE_SPACETIME_DATABASE`,并同步 `GENARRATIVE_SPACETIME_SERVER_URL`。否则 api-server 会继续读取环境文件中的旧库名,出现 wasm 已发布到新库但 HTTP facade 仍访问旧库的错位。
|
||||||
|
|
||||||
## Nginx 规则
|
## Nginx 规则
|
||||||
|
|
||||||
生产正式入口只保留必要路由:
|
生产正式入口只保留必要路由:
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ pipeline {
|
|||||||
string(name: 'CURRENT_LINK', defaultValue: '/opt/genarrative/current', description: '当前版本软链接')
|
string(name: 'CURRENT_LINK', defaultValue: '/opt/genarrative/current', description: '当前版本软链接')
|
||||||
string(name: 'SERVICE_NAME', defaultValue: 'genarrative-api.service', description: 'systemd 服务名')
|
string(name: 'SERVICE_NAME', defaultValue: 'genarrative-api.service', description: 'systemd 服务名')
|
||||||
string(name: 'HEALTH_URL', defaultValue: 'http://127.0.0.1:8082/healthz', description: '本机健康检查地址')
|
string(name: 'HEALTH_URL', defaultValue: 'http://127.0.0.1:8082/healthz', description: '本机健康检查地址')
|
||||||
|
string(name: 'API_ENV_FILE', defaultValue: '/etc/genarrative/api-server.env', description: 'api-server 环境文件')
|
||||||
|
string(name: 'DATABASE', defaultValue: 'genarrative-prod', description: 'api-server 连接的 SpacetimeDB database')
|
||||||
|
string(name: 'SPACETIME_SERVER_URL', defaultValue: 'http://127.0.0.1:3101', description: 'api-server 连接的 SpacetimeDB server URL')
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
@@ -45,6 +48,15 @@ pipeline {
|
|||||||
if (!params.BUILD_NUMBER_TO_DEPLOY?.trim()) {
|
if (!params.BUILD_NUMBER_TO_DEPLOY?.trim()) {
|
||||||
error('BUILD_NUMBER_TO_DEPLOY 不能为空。')
|
error('BUILD_NUMBER_TO_DEPLOY 不能为空。')
|
||||||
}
|
}
|
||||||
|
if (!params.DATABASE?.trim()) {
|
||||||
|
error('DATABASE 不能为空。')
|
||||||
|
}
|
||||||
|
if (!(params.DATABASE.trim() ==~ /^[a-z0-9]+(-[a-z0-9]+)*$/)) {
|
||||||
|
error("DATABASE 必须匹配 ^[a-z0-9]+(-[a-z0-9]+)*$: ${params.DATABASE}")
|
||||||
|
}
|
||||||
|
if (!params.API_ENV_FILE?.trim()) {
|
||||||
|
error('API_ENV_FILE 不能为空。')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +117,10 @@ pipeline {
|
|||||||
--release-root "${RELEASE_ROOT}" \
|
--release-root "${RELEASE_ROOT}" \
|
||||||
--current-link "${CURRENT_LINK}" \
|
--current-link "${CURRENT_LINK}" \
|
||||||
--service "${SERVICE_NAME}" \
|
--service "${SERVICE_NAME}" \
|
||||||
--health-url "${HEALTH_URL}"
|
--health-url "${HEALTH_URL}" \
|
||||||
|
--api-env-file "${API_ENV_FILE}" \
|
||||||
|
--database "${DATABASE}" \
|
||||||
|
--spacetime-server-url "${SPACETIME_SERVER_URL}"
|
||||||
'
|
'
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ pipeline {
|
|||||||
booleanParam(name: 'CONFIRM_RELEASE_DEPLOY_AGENT', value: params.CONFIRM_RELEASE_DEPLOY_AGENT),
|
booleanParam(name: 'CONFIRM_RELEASE_DEPLOY_AGENT', value: params.CONFIRM_RELEASE_DEPLOY_AGENT),
|
||||||
string(name: 'BUILD_JOB_NAME', value: params.API_BUILD_JOB_NAME),
|
string(name: 'BUILD_JOB_NAME', value: params.API_BUILD_JOB_NAME),
|
||||||
string(name: 'BUILD_NUMBER_TO_DEPLOY', value: env.API_BUILD_NUMBER),
|
string(name: 'BUILD_NUMBER_TO_DEPLOY', value: env.API_BUILD_NUMBER),
|
||||||
|
string(name: 'DATABASE', value: params.DATABASE),
|
||||||
|
string(name: 'SPACETIME_SERVER_URL', value: params.SPACETIME_SERVER_URL ?: ''),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ set -euo pipefail
|
|||||||
usage() {
|
usage() {
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
用法:
|
用法:
|
||||||
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--health-url http://127.0.0.1:8082/healthz]
|
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--health-url http://127.0.0.1:8082/healthz] [--api-env-file /etc/genarrative/api-server.env] [--database genarrative-prod] [--spacetime-server-url http://127.0.0.1:3101]
|
||||||
|
|
||||||
说明:
|
说明:
|
||||||
进入维护模式,校验并发布 api-server 单文件,更新 current 链接,重启 systemd 服务并执行 healthz 检查。
|
进入维护模式,校验并发布 api-server 单文件,更新 current 链接,重启 systemd 服务并执行 healthz 检查。
|
||||||
|
若传入 --database,会在重启前把 GENARRATIVE_SPACETIME_DATABASE 写入 api-server 环境文件,避免服务继续读取旧库。
|
||||||
失败时保留维护模式。
|
失败时保留维护模式。
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@@ -23,6 +24,36 @@ require_argument() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate_spacetime_database_name() {
|
||||||
|
local database="$1"
|
||||||
|
|
||||||
|
if [[ ! "${database}" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
|
||||||
|
echo "[production-api-deploy] --database 必须匹配 SpacetimeDB 数据库名规则 ^[a-z0-9]+(-[a-z0-9]+)*$,只能使用小写字母、数字,并用单个短横线分隔: ${database}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
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)"
|
||||||
|
|
||||||
|
if grep -qE "^${key}=" "${file_path}"; then
|
||||||
|
sed -E "s|^${key}=.*|${key}=${value}|" "${file_path}" >"${temp_path}"
|
||||||
|
else
|
||||||
|
cp "${file_path}" "${temp_path}"
|
||||||
|
printf "%s=%s\n" "${key}" "${value}" >>"${temp_path}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat "${temp_path}" >"${file_path}"
|
||||||
|
rm -f "${temp_path}"
|
||||||
|
}
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
SOURCE_DIR=""
|
SOURCE_DIR=""
|
||||||
VERSION=""
|
VERSION=""
|
||||||
@@ -30,6 +61,9 @@ RELEASE_ROOT="/opt/genarrative/releases"
|
|||||||
CURRENT_LINK="/opt/genarrative/current"
|
CURRENT_LINK="/opt/genarrative/current"
|
||||||
SERVICE_NAME="genarrative-api.service"
|
SERVICE_NAME="genarrative-api.service"
|
||||||
HEALTH_URL="http://127.0.0.1:8082/healthz"
|
HEALTH_URL="http://127.0.0.1:8082/healthz"
|
||||||
|
API_ENV_FILE="/etc/genarrative/api-server.env"
|
||||||
|
DATABASE=""
|
||||||
|
SPACETIME_SERVER_URL=""
|
||||||
DEPLOY_COMPLETED=0
|
DEPLOY_COMPLETED=0
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
@@ -62,6 +96,18 @@ while [[ $# -gt 0 ]]; do
|
|||||||
HEALTH_URL="${2:?缺少 --health-url 的值}"
|
HEALTH_URL="${2:?缺少 --health-url 的值}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--api-env-file)
|
||||||
|
API_ENV_FILE="${2:?缺少 --api-env-file 的值}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--database)
|
||||||
|
DATABASE="${2:?缺少 --database 的值}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--spacetime-server-url)
|
||||||
|
SPACETIME_SERVER_URL="${2:?缺少 --spacetime-server-url 的值}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "[production-api-deploy] 未知参数: $1" >&2
|
echo "[production-api-deploy] 未知参数: $1" >&2
|
||||||
usage >&2
|
usage >&2
|
||||||
@@ -72,6 +118,10 @@ done
|
|||||||
|
|
||||||
require_argument "${SOURCE_DIR}" "--source-dir"
|
require_argument "${SOURCE_DIR}" "--source-dir"
|
||||||
|
|
||||||
|
if [[ -n "${DATABASE}" ]]; then
|
||||||
|
validate_spacetime_database_name "${DATABASE}"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ ! -d "${SOURCE_DIR}" ]]; then
|
if [[ ! -d "${SOURCE_DIR}" ]]; then
|
||||||
echo "[production-api-deploy] 发布目录不存在: ${SOURCE_DIR}" >&2
|
echo "[production-api-deploy] 发布目录不存在: ${SOURCE_DIR}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
@@ -117,6 +167,16 @@ if [[ -f "${SOURCE_DIR}/release-manifest.json" ]]; then
|
|||||||
cp "${SOURCE_DIR}/release-manifest.json" "${RELEASE_DIR}/release-manifest.api-server.json"
|
cp "${SOURCE_DIR}/release-manifest.json" "${RELEASE_DIR}/release-manifest.api-server.json"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${DATABASE}" ]]; then
|
||||||
|
echo "[production-api-deploy] 写入 api-server SpacetimeDB database: ${DATABASE} -> ${API_ENV_FILE}"
|
||||||
|
write_env_value "${API_ENV_FILE}" "GENARRATIVE_SPACETIME_DATABASE" "${DATABASE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "${SPACETIME_SERVER_URL}" ]]; then
|
||||||
|
echo "[production-api-deploy] 写入 api-server SpacetimeDB server: ${SPACETIME_SERVER_URL} -> ${API_ENV_FILE}"
|
||||||
|
write_env_value "${API_ENV_FILE}" "GENARRATIVE_SPACETIME_SERVER_URL" "${SPACETIME_SERVER_URL}"
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p "$(dirname "${CURRENT_LINK}")"
|
mkdir -p "$(dirname "${CURRENT_LINK}")"
|
||||||
ln -sfn "${RELEASE_DIR}" "${CURRENT_LINK}"
|
ln -sfn "${RELEASE_DIR}" "${CURRENT_LINK}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user