Files
xiaoxia-saas/scripts/render_env.sh
T
xiaoxia 9840d5d778
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 8s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 18s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 29s
CI/CD Pipeline / Build Staging API Image (push) Successful in 28s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 29s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m34s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 43s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 43s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 1m56s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Integration Tests (push) Successful in 2m22s
CI/CD Pipeline / Validate - Style (push) Successful in 2m40s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 50s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m30s
CI/CD Pipeline / Validate - Security (push) Successful in 4m53s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 5m31s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m8s
AI Code Review / AI Code Review (pull_request) Successful in 6m28s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m54s
CI/CD Pipeline / Unit Tests (push) Successful in 9m4s
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
deploy(#1718): 微信OAuth凭证纳入env模板+CI渲染,修复staging部署覆盖丢失 (#1721)
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-09-05 17:39:46 +08:00

143 lines
4.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ===========================================================
# render_env.sh — 从模板 + Secrets 渲染 .env 文件
# ===========================================================
# 用法: scripts/render_env.sh <staging|production>
#
# 输入: deploy/configs/.env.staging 或 .env.production 模板
# 输出: .env.rendered(包含真实密钥,切勿提交或打印)
#
# 环境变量映射规则:
# STAGING_xxx / PRODUCTION_xxx → xxx(去掉环境前缀)
# 共用 secrets 直接使用(如 OSS_ACCESS_KEY_ID
# ===========================================================
set -eu
TARGET_ENV="${1:-}"
if [ -z "$TARGET_ENV" ] || { [ "$TARGET_ENV" != "staging" ] && [ "$TARGET_ENV" != "production" ]; }; then
echo "ERROR: 用法: $0 <staging|production>" >&2
exit 1
fi
TEMPLATE_FILE="deploy/configs/.env.${TARGET_ENV}"
OUTPUT_FILE=".env.rendered"
if [ ! -f "$TEMPLATE_FILE" ]; then
echo "ERROR: 模板文件不存在: $TEMPLATE_FILE" >&2
exit 1
fi
# 构建环境变量映射(带环境前缀的 secrets → 模板变量名)
ENV_PREFIX=$(echo "$TARGET_ENV" | tr '[:lower:]' '[:upper:]')
# 需要映射的带环境前缀变量
MAPPED_VARS="DATABASE_URL REDIS_URL CELERY_BROKER_URL CELERY_RESULT_BACKEND JWT_SECRET_KEY"
# Staging 独有的 MinIO 变量
if [ "$TARGET_ENV" = "staging" ]; then
MAPPED_VARS="$MAPPED_VARS MINIO_ENDPOINT MINIO_ACCESS_KEY MINIO_SECRET_KEY"
fi
# 将带前缀的 secrets 导出为无前缀的环境变量
for var in $MAPPED_VARS; do
prefixed_var="${ENV_PREFIX}_${var}"
value="${!prefixed_var:-}"
if [ -n "$value" ]; then
export "$var=$value"
fi
done
# 特殊映射:CI secret 名称与模板占位符不一致的变量
# STAGING_MINIO_BUCKET → MINIO_BUCKET_NAME
if [ "$TARGET_ENV" = "staging" ]; then
if [ -n "${STAGING_MINIO_BUCKET:-}" ]; then
export "MINIO_BUCKET_NAME=$STAGING_MINIO_BUCKET"
fi
fi
# 共用 secrets 直接导出(如果存在)
SHARED_SECRETS="OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET COSYVOICE_API_KEY DASHSCOPE_API_KEY MEDIAKIT_API_KEY WECHAT_APP_ID WECHAT_APP_SECRET"
for var in $SHARED_SECRETS; do
value="${!var:-}"
# 已经在环境中了,无需额外操作
done
# 使用 Python 进行变量替换(Python 在 CI runner 中一定存在)
python3 - "$TEMPLATE_FILE" "$OUTPUT_FILE" "$ENV_PREFIX" "$MAPPED_VARS" "$SHARED_SECRETS" <<'PYTHON_SCRIPT'
import sys
import os
import re
template_file = sys.argv[1]
output_file = sys.argv[2]
env_prefix = sys.argv[3]
mapped_vars_str = sys.argv[4]
shared_secrets_str = sys.argv[5]
# 收集所有可用的替换变量
all_vars = set()
for v in mapped_vars_str.split():
all_vars.add(v)
for v in shared_secrets_str.split():
all_vars.add(v)
# 读取模板
with open(template_file, 'r') as f:
template = f.read()
# 找出模板中所有的 ${VAR} 占位符(仅检查非注释行)
pattern = re.compile(r'\$\{(\w+)\}')
placeholders = set()
for line in template.splitlines():
stripped = line.strip()
if stripped.startswith('#'):
continue
placeholders.update(pattern.findall(line))
# 检查必需变量是否已设置
missing = []
for var in placeholders:
value = os.environ.get(var, '')
if not value:
missing.append(var)
if missing:
print(f"ERROR: 以下变量未设置或为空: {', '.join(sorted(missing))}", file=sys.stderr)
print(f"请确认对应的 {env_prefix}_xxx 或共用 secrets 已在 Gitea Secrets 中配置", file=sys.stderr)
sys.exit(1)
# 执行替换
def replace_var(match):
var_name = match.group(1)
return os.environ.get(var_name, match.group(0))
rendered = pattern.sub(replace_var, template)
# 写入输出文件
with open(output_file, 'w') as f:
f.write(rendered)
# 设置文件权限为仅 owner 可读写
os.chmod(output_file, 0o600)
print(f"✅ .env 渲染完成: {template_file} → {output_file}")
print(f" 替换了 {len(placeholders)} 个变量")
PYTHON_SCRIPT
# 验证输出文件
if [ ! -f "$OUTPUT_FILE" ]; then
echo "ERROR: 渲染失败,输出文件不存在" >&2
exit 1
fi
# 检查输出文件中是否还有未替换的占位符(仅检查非注释行)
if grep -vE '^\s*#' "$OUTPUT_FILE" | grep -qE '\$\{[A-Z_]+\}'; then
echo "ERROR: 输出文件中仍有未替换的占位符:" >&2
grep -nE '\$\{[A-Z_]+\}' "$OUTPUT_FILE" | grep -v '^\s*#' >&2
exit 1
fi
echo "✅ 渲染文件校验通过,无残留占位符"
echo "⚠️ $OUTPUT_FILE 包含敏感信息,请勿提交或打印到日志"