ci: 复用部署服务器缓存并支持 HTTPS 同源登录

This commit is contained in:
2026-10-09 21:11:44 +08:00
parent 2cad6d7533
commit ac936d2a1a
14 changed files with 158 additions and 47 deletions
+6 -2
View File
@@ -10,7 +10,7 @@
- 应用配置:服务器 `configs/.env`,权限 600;日志:服务器 `logs/`,由容器 UID 10001 写入并轮转。
- PostgreSQL、Redis 使用已有内网服务;不额外部署数据库容器,不覆盖数据、身份或加密主密钥。
仓库 Actions 已启用,部署使用 `DEPLOY_PASSWORD`、`DEPLOY_KNOWN_HOSTS` 两个仓库 Secret。服务器地址、用户和目录在工作流中明确配置;SSH 严格校验已知服务器公钥。可选 `VEYRA_ENV_FILE` 仅用于新服务器首次创建配置,已有文件永不覆盖。当前服务器已通过 SSH 安全初始化,无需设置此可选 Secret。
仓库 Actions 已启用,部署使用 `DEPLOY_PASSWORD`、`DEPLOY_KNOWN_HOSTS` 两个仓库 Secret。服务器地址、用户和目录在工作流中明确配置;SSH 严格校验已知服务器公钥。服务器配置需在首次部署前初始化;当前服务器已通过 SSH 安全初始化。发布不传输或覆盖配置。
应用环境文件必须采用无外层引号的 `KEY=VALUE` 格式。Compose 使用 `env_file.format: raw`,保留密码中的 `$`、`#` 等字符,不把应用配置作为 Compose 插值文件。需要 Docker、Compose >=2.30、bash、flock、gzip、sha256sum;当前服务器 Compose 2.36.2 满足要求。
@@ -18,7 +18,7 @@
1. 使用 Gitea job token 下载当前提交归档,与参考项目保持一致,避免 Git HTTP pack 检出问题。
2. Docker 内检查 App 类型、12 项客户端测试、iOS/Android Hermes 导出;管理端类型检查、构建、Go embed;gofmt、go vet 与 Go race 测试。构建阶段使用已验证可达的 `https://goproxy.cn,direct` 下载 Go 依赖,保留默认 checksum 校验;运行镜像不包含此构建设置。PostgreSQL 集成测试使用独立、用后清理的 CI 容器,不访问开发库。部署脚本也有成功、校验失败、迁移失败、健康失败回滚、配置保留测试。
3. 所有检查通过才构建 `sundynix/veyra:<完整提交 SHA>`,打包压缩并生成 SHA-256 校验文件,通过 SSH 传入服务器的独立发布目录。
3. Runner 只传提交源码,检查和构建在部署服务器独立 builds/<SHA> 目录中执行,复用服务器 Docker 依赖层缓存;使用独立构建锁避免并发资源争用。所有检查通过才构建 `sundynix/veyra:<完整提交 SHA>`,在服务器本地打包并生成 SHA-256 校验文件。不在 Runner 重复下载基础镜像,也不跨主机传输大型镜像。
4. 服务器加锁串行发布,校验压缩包、加载镜像,执行同一可执行文件的 `-command db-create` 和 `-command db-migrate`,再启动 Compose。
5. `/readyz` 检查 PostgreSQL 与 Redis。新版本就绪后才更新 `.current-image`;失败则恢复上一版镜像与 Compose,首次部署失败则停止应用。迁移失败不替换运行中的服务。不会自动回退数据库迁移;后续迁移应保持与上一版应用兼容,破坏性迁移需单独设计。
@@ -39,3 +39,7 @@ go build -trimpath -o bin/veyra .
服务器排查使用 `docker compose --env-file /dev/null -f docker-compose.yml`,同时将 `VEYRA_IMAGE` 设为 `.current-image` 中的值。不要将含凭据的 `docker compose config`、环境文件或容器完整 inspect 输出到日志;配置语法检查使用 `config --quiet`。
配置语义参考 [Gitea Actions](https://docs.gitea.com/usage/actions/) 与 [Docker Compose env_file](https://docs.docker.com/reference/compose-file/services/#env_file)。
## HTTPS 反向代理
域名 `veyra.sundynix.cn` 的 Nginx 将全部页面与 API 代理至 `http://192.168.100.132:8080`,传递原始 Host。服务器 configs/.env 设置 `PUBLIC_ORIGIN=https://veyra.sundynix.cn`,使 HTTPS Origin 校验和 Secure Cookie 正确工作;应用不信任任意 X-Forwarded-Proto。域名 Nginx 由用户按已提供配置操作。
+1
View File
@@ -22,5 +22,6 @@ for ((i=0; i<60; i++)); do
done
if [[ "$ready" != true ]]; then echo 'CI PostgreSQL did not become ready' >&2; exit 1; fi
docker run --rm --network "$network" \
-v veyra-go-test-cache:/root/.cache/go-build \
-e VEYRA_TEST_DATABASE_URL='postgres://veyra_test:test_only@postgres:5432/veyra_test?sslmode=disable' \
"veyra-test:$run_id"
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
: "${SSHPASS:?DEPLOY_PASSWORD is required}"
: "${DEPLOY_KNOWN_HOSTS:?DEPLOY_KNOWN_HOSTS is required}"
[[ "$DEPLOY_HOST" =~ ^[a-zA-Z0-9.-]+$ && "$DEPLOY_USER" =~ ^[a-zA-Z0-9_-]+$ ]] || exit 2
[[ "$COMMIT_SHA" =~ ^[0-9a-f]{40}$ && "$REMOTE_DIR" =~ ^/[a-zA-Z0-9_/-]+$ && "$REMOTE_DIR" != / && "$REMOTE_DIR" != *..* ]] || exit 2
known_hosts="$(mktemp)"
archive="$(mktemp)"
trap 'rm -f "$known_hosts" "$archive"' EXIT
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > "$known_hosts"
chmod 600 "$known_hosts"
options=(-o StrictHostKeyChecking=yes -o "UserKnownHostsFile=$known_hosts" -o ConnectTimeout=15)
target="$DEPLOY_USER@$DEPLOY_HOST"
case "${1:-}" in
verify)
build="$REMOTE_DIR/builds/$COMMIT_SHA"
tar --exclude=.git --exclude=node_modules --exclude=.env --exclude=logs --exclude=bin -czf "$archive" .
sshpass -e ssh "${options[@]}" "$target" "umask 077; mkdir -p '$build'"
sshpass -e scp "${options[@]}" "$archive" "$target:$build/source.tar.gz"
sshpass -e ssh "${options[@]}" "$target" "cd '$build'; tar -xzf source.tar.gz; rm source.tar.gz; bash deploy/remote-build.sh '$REMOTE_DIR' '$COMMIT_SHA'"
;;
deploy)
sshpass -e ssh "${options[@]}" "$target" "bash '$REMOTE_DIR/releases/$COMMIT_SHA/release.sh' '$REMOTE_DIR' '$COMMIT_SHA'"
;;
*) exit 2 ;;
esac
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
root="${1:?Deployment directory required}"
sha="${2:?Commit SHA required}"
[[ "$root" =~ ^/[a-zA-Z0-9_/-]+$ && "$root" != / && "$root" != *..* && "$sha" =~ ^[0-9a-f]{40}$ ]] || exit 2
exec 9>"$root/.build.lock"
flock -w 1800 9
cd "$root/builds/$sha"
bash deploy/check.sh
docker build -t "sundynix/veyra:$sha" .
release="$root/releases/$sha"
umask 077
mkdir -p "$release"
cp deploy/docker-compose.yml deploy/release.sh "$release/"
docker save "sundynix/veyra:$sha" | gzip > "$release/image.tar.gz"
(cd "$release" && sha256sum image.tar.gz > image.tar.gz.sha256)
echo "Verified image prepared: $sha"