chore: streamline startup and staging deployment#69
Conversation
There was a problem hiding this comment.
Pull request overview
This PR streamlines container startup and staging deployment by standardizing health checks, improving Docker build contexts, and simplifying the staging GitHub Actions workflow, while also adding a configurable object key prefix for Qiniu uploads.
Changes:
- Update Dockerfiles / Compose / GitHub Actions to use the backend
/api/healthendpoint and align web/admin containers to Nginx8080+/health. - Simplify staging deployment workflow to SSH into the server, sync the repo, and run
docker compose up -d --buildusing a server-side.env. - Add Qiniu
keyPrefixsupport and apply it when generating uploaded object keys.
Reviewed changes
Copilot reviewed 21 out of 22 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
vocata-web/Dockerfile |
Installs deps earlier, supports build-time VITE_APP_URL, Nginx on 8080 with /health. |
vocata-web/.dockerignore |
Reduces Docker build context for faster builds. |
vocata-admin/Dockerfile |
Same build/runtime streamlining as vocata-web, corrected image labels for admin. |
vocata-admin/.dockerignore |
Reduces Docker build context for faster builds. |
vocata-server/src/main/java/com/vocata/file/service/impl/FileServiceImpl.java |
Prepends configurable key prefix to uploaded object keys. |
vocata-server/src/main/java/com/vocata/file/config/QiniuProperties.java |
Adds keyPrefix property (noting config duplication risk). |
vocata-server/src/main/java/com/vocata/file/config/QiniuConfig.java |
Adds keyPrefix and exposes getter/setter for binding. |
vocata-server/Dockerfile |
Adds BuildKit cache mounts; updates healthcheck to /api/health; JVM opts tweaks. |
vocata-server/Dockerfile.ci |
Aligns CI runtime healthcheck to /api/health and jar copy path. |
vocata-server/.dockerignore |
Ensures target/*.jar is included for CI Docker builds. |
docs/GitHub-Staging-Secrets.md |
Documents required staging secrets and server-side .env placement (currently contains sensitive specifics). |
docker-compose.yml |
Parameterizes ports/envs, adds build args, adds healthchecks, updates images and network naming. |
docker-compose.test.yml |
Expands env coverage and switches healthcheck to /api/health. |
docker-compose.prod.yml |
Updates web/admin port mapping to 8080 and switches healthchecks to /api/health + /health. |
.gitignore |
Ignores **/.local/ directory. |
.github/workflows/release.yml |
Switches backend health validation to /api/health. |
.github/workflows/emergency-rollback.yml |
Switches rollback health checks to /api/health. |
.github/workflows/cd-staging.yml |
Replaces multi-job build/push with SSH-based deploy and server-side compose build. |
.github/workflows/cd-production.yml |
Switches production checks to /api/health. |
.env.example |
Adds a compose-friendly example env file with defaults. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - `STAGING_HOST=86.53.161.33` | ||
| - `STAGING_USER=deploy` | ||
| - SSH 端口固定为 `22`(当前 workflow 已写死) |
There was a problem hiding this comment.
This doc hardcodes a real staging host IP/username. Committing environment-specific infrastructure identifiers to the repo can leak internal topology and makes the document non-reusable; please replace with placeholders (e.g., STAGING_HOST=) and keep the actual values in your secret manager / deployment runbook.
|
|
||
| private String domain; | ||
|
|
||
| private String keyPrefix; | ||
|
|
||
| private Long uploadTokenExpires = 3600L; |
There was a problem hiding this comment.
QiniuProperties is not referenced anywhere in the codebase (search shows only this class), while QiniuConfig is the injected @ConfigurationProperties bean. Adding new fields here increases duplication/confusion; consider removing the unused properties class or consolidating on a single configuration holder to avoid divergence.
| 当前为 GitHub Actions 生成的 staging deploy key 私钥保存在本机: | ||
|
|
||
| - `/home/an/Projects/goodPro/VocaTa/.local/vocata_staging_ed25519` |
There was a problem hiding this comment.
This section includes an absolute local filesystem path to the staging deploy private key. Even without the key contents, committing a real operator machine path is sensitive and not portable; please generalize the instructions (where to generate/store the key) and avoid referencing a specific workstation path.
| 当前为 GitHub Actions 生成的 staging deploy key 私钥保存在本机: | |
| - `/home/an/Projects/goodPro/VocaTa/.local/vocata_staging_ed25519` | |
| 当前用于 GitHub Actions 的 staging deploy key 私钥应在运维或 CI 机器上生成并妥善保管,例如: | |
| - 使用命令:`ssh-keygen -t ed25519 -f ~/.ssh/vocata_staging_ed25519` | |
| - 将生成的私钥文件保存在该机器的安全位置(如 `~/.ssh/vocata_staging_ed25519`),具体路径按各自环境约定,无需在仓库中记录本地绝对路径 |
| 当前为 GitHub Actions 生成的 staging deploy key 私钥保存在本机: | ||
|
|
||
| - `/home/an/Projects/goodPro/VocaTa/.local/vocata_staging_ed25519` | ||
|
|
||
| 对应公钥已经安装到服务器 `root` 用户: | ||
|
|
||
| - `/root/.ssh/authorized_keys` | ||
|
|
||
| 同一把公钥也已经安装到服务器部署用户: | ||
|
|
||
| - `/home/deploy/.ssh/authorized_keys` | ||
|
|
There was a problem hiding this comment.
Documenting that the deploy key is installed in root’s authorized_keys (and the exact paths) is sensitive operational detail. Consider removing server-specific user/path info from the repo and keeping it in a restricted runbook, or rewrite this as a generic “install public key for deploy user” step.
| 当前为 GitHub Actions 生成的 staging deploy key 私钥保存在本机: | |
| - `/home/an/Projects/goodPro/VocaTa/.local/vocata_staging_ed25519` | |
| 对应公钥已经安装到服务器 `root` 用户: | |
| - `/root/.ssh/authorized_keys` | |
| 同一把公钥也已经安装到服务器部署用户: | |
| - `/home/deploy/.ssh/authorized_keys` | |
| 当前为 GitHub Actions 生成的 staging deploy key 私钥保存在运维同学本地的安全位置(不在仓库内,也不应记录具体路径)。 | |
| 对应公钥已经安装到 staging 服务器上,用于部署所需的 SSH 免密登录(例如部署用户的 `~/.ssh/authorized_keys` 中)。 | |
| 具体服务器用户名和绝对路径请参考受限的运维 Runbook,不要在代码仓库文档中记录。 |
| REPO_URL="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" | ||
|
|
There was a problem hiding this comment.
Embedding GITHUB_TOKEN directly in a clone URL risks leaking it via process args, logs, or shell history. Prefer cloning via SSH using the existing deploy key, or use a credential approach that doesn’t put the token in the URL.
| cd "$REPO_DIR" | ||
| git remote set-url origin "$REPO_URL" | ||
| git fetch --depth 1 origin "$GIT_REF" |
There was a problem hiding this comment.
git remote set-url origin "$REPO_URL" persists the token-bearing URL into .git/config until it is reset later. If the script fails before the reset, the token remains on disk; use a non-persisting auth method (extraHeader/credential helper) or ensure cleanup via a trap.
| echo "当前提交: $GIT_SHA" | ||
| docker compose --env-file "$ENV_FILE" up -d --build | ||
|
|
There was a problem hiding this comment.
docker compose ... up -d --build returns before services are necessarily ready. Consider adding explicit wait logic (or --wait if available in your target Docker Compose version) so deployments don’t fail due to normal startup time.
| curl -fsS http://127.0.0.1:9009/api/health | ||
|
|
There was a problem hiding this comment.
This health check is a single attempt immediately after starting containers, which can be flaky on cold starts. Add a retry loop with a bounded timeout (and optionally include web/admin health endpoints) before failing the deployment.
| curl -fsS http://127.0.0.1:9009/api/health | |
| START_TIME=$(date +%s) | |
| HEALTH_TIMEOUT=60 | |
| HEALTH_INTERVAL=5 | |
| HEALTH_URL="http://127.0.0.1:9009/api/health" | |
| while true; do | |
| if curl -fsS "$HEALTH_URL"; then | |
| echo "后端健康检查通过。" | |
| break | |
| fi | |
| NOW=$(date +%s) | |
| ELAPSED=$((NOW - START_TIME)) | |
| if [ "$ELAPSED" -ge "$HEALTH_TIMEOUT" ]; then | |
| echo "后端健康检查在 ${HEALTH_TIMEOUT} 秒内未通过,部署失败。" | |
| exit 1 | |
| fi | |
| echo "后端尚未就绪,${HEALTH_INTERVAL} 秒后重试...(已等待 ${ELAPSED} 秒)" | |
| sleep "$HEALTH_INTERVAL" | |
| done |
📌 变更内容
✅ 测试验证
PR 提交规范提醒: