From f441fd49c0a87c9669b9987988ae9386848de9c4 Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 8 Jul 2026 22:30:46 +0800 Subject: [PATCH] Add lucky gift deployment support --- .dockerignore | 6 +- AGENTS.md | 22 +-- README.md | 71 ++++++++-- deploy/README.md | 4 +- deploy/mysql/initdb/999_local_grants.sql | 1 + deploy/rocketmq/broker.conf | 3 + deploy/server.mjs | 3 +- .../docker/deploy-platform.env.example | 2 +- .../docker/luck-gateway.env.example | 7 + .../docker/lucky-gift-service.env.example | 5 + .../docker/robot-service.env.example | 4 + .../systemd/hyapp-luck-gateway.service | 23 ++++ .../systemd/hyapp-lucky-gift-service.service | 23 ++++ .../systemd/hyapp-robot-service.service | 23 ++++ deploy/tencent_tat/README.md | 17 ++- deploy/tencent_tat/edgeone_purge.py | 2 +- ...hyapp-services.inventory.prod.example.json | 53 +++++++ .../tencent_tat/hyapp_admin_server_deploy.py | 129 +++++++++--------- .../tests/test_hyapp_admin_server_deploy.py | 15 +- .../tencent_tat/validate_rendered_configs.py | 21 ++- src/pages/cdn-refresh/CdnRefreshPage.tsx | 4 +- 21 files changed, 328 insertions(+), 110 deletions(-) create mode 100644 deploy/standalone/docker/luck-gateway.env.example create mode 100644 deploy/standalone/docker/lucky-gift-service.env.example create mode 100644 deploy/standalone/docker/robot-service.env.example create mode 100644 deploy/standalone/systemd/hyapp-luck-gateway.service create mode 100644 deploy/standalone/systemd/hyapp-lucky-gift-service.service create mode 100644 deploy/standalone/systemd/hyapp-robot-service.service diff --git a/.dockerignore b/.dockerignore index a49e52a..2c1e518 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,6 @@ dist .DS_Store *.tsbuildinfo npm-debug.log* -deploy/tencent-tat/inventory.prod.json -deploy/tencent-tat/deploy-platform.inventory.prod.json -deploy/tencent-tat/hyapp-services.inventory.prod.json +deploy/tencent_tat/inventory.prod.json +deploy/tencent_tat/deploy-platform.inventory.prod.json +deploy/tencent_tat/hyapp-services.inventory.prod.json diff --git a/AGENTS.md b/AGENTS.md index e215210..2232e61 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,14 +36,20 @@ ## 生产特殊服务 -1. `admin-server` 不在标准 prod inventory 的滚动服务清单里;它部署在 Saudi 机器 `43.164.70.49` / `10.2.1.2`,实例 `ins-p11begwe`。 -2. `admin-server` 的 systemd 是 `hyapp-admin-server`,容器是 `hyapp-admin-server`,镜像是 `10.2.1.3:18082/hyapp/admin-server:`,配置是 `/etc/hyapp/admin-server/config.yaml`,Docker env 是 `/etc/hyapp/admin-server/docker.env`,监听 `10.2.1.2:13100`。 -3. 更新 `admin-server` 时,由 deploy 机器 `43.164.75.199` 在 `/opt/deploy/sources/hyapp-server` 拉取 Gitea `git@gitea.haiyihy.com:hy/hyapp-server.git` 的 `origin/main`,构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 Tencent TAT 到 `ins-p11begwe` 修改 docker env 的 `IMAGE` 后重启 `hyapp-admin-server`。线上只允许发布 `origin/main`;发布后必须验证容器镜像 tag、systemd `active`、`13100` 监听和 `healthz/readyz`。`hyapp_admin_server_deploy.py` 是旧广州机器二进制发布脚本,不适用于当前生产 `admin-server`。 -4. HyApp `cron-service` 当前部署在 Saudi 主服务机器 `new-app-1`,实例 `ins-fi5zufpk`,内网 `10.2.1.4`。 -5. `cron-service` 的 systemd 是 `hyapp-cron-service`,容器是 `hyapp-cron-service`,配置是 `/etc/hyapp/cron-service/config.yaml`,Docker env 是 `/etc/hyapp/cron-service/docker.env`,监听 `13007`。 -6. `cron-service` 当前不在标准 prod inventory 的 `services` 清单里;更新时构建并推送 `10.2.1.3:18082/hyapp/cron-service:`,通过 Tencent TAT 到 `new-app-1` 修改 docker env 的 `IMAGE` 后重启 `hyapp-cron-service`。 -7. 更新 `cron-service` 后必须验证镜像 tag、Docker health、systemd `active` 和 `13007` 监听。 -8. 腾讯云 `ap-singapore` 的实例名 `cron` 机器是 `ins-nt6bsay0` / `10.3.1.14`;当前没有 HyApp `hyapp-cron-service`,不要把它当成 HyApp `cron-service` 发布目标。 +1. `admin-server` 不在标准 prod inventory 的滚动服务清单里;它部署在 Saudi `admin-platform` 机器 `ins-p11begwe`,公网 `43.164.70.49`,内网 `10.2.1.2`。 +2. `admin-server` 的 systemd 是 `hyapp-admin-server`,容器是 `hyapp-admin-server`,配置是 `/etc/hyapp/admin-server/config.yaml`,Docker env 是 `/etc/hyapp/admin-server/docker.env`,migration 目录是 `/opt/hyapp/admin-server/migrations`,监听 `10.2.1.2:13100`。 +3. 更新 `admin-server` 必须只发布 `origin/main`:deploy 机从 Gitea 拉取 `git@gitea.haiyihy.com:hy/hyapp-server.git` 的 `origin/main`,构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 Tencent TAT 到 `ins-p11begwe` 修改 `/etc/hyapp/admin-server/docker.env` 的 `IMAGE` 后重启 `hyapp-admin-server`。 +4. `admin-platform` 机器已经配置 Docker 直拉内网 Harbor:`/etc/docker/daemon.json` 包含 insecure registry `10.2.1.3:18082`,`/root/.docker/config.json` 包含 Harbor 登录凭据;如果 `docker pull 10.2.1.3:18082/...` 失败,优先检查这两处。 +5. 更新 `admin-server` 后必须验证:`systemctl is-active hyapp-admin-server`、容器镜像 tag/digest、`ss -lntp | grep 13100`、`curl http://10.2.1.2:13100/healthz`、`curl http://10.2.1.2:13100/readyz`、Caddy 容器 `yumi-admin-caddy` 运行、公网 `https://admin-acc.global-interaction.com/` 返回 `200`、未登录 `https://admin-acc.global-interaction.com/api/v1/auth/me` 返回 `401`。 +6. Saudi `admin-platform` 机器同时承接两个 5 秒轮询的前端 watcher:`chatapp3-admin-watch.service` 和 `hyapp-admin-platform-watch.service`。它们只在远端 commit 变化或静态目录缺失时构建,不应每 5 秒重复 build。 +7. `chatapp3-admin-watch.service` 使用 `/opt/chatapp3-admin/bin/watch-build.sh`,部署脚本是 `/opt/chatapp3-admin/bin/deploy-once.sh`,仓库是 `git@gitea.haiyihy.com:hy/chatapp3-admin.git` 的 `main`,构建后写入 `/opt/yumi-admin/frontend-admin/site/yumiadmin-acc`,公网入口是 `https://yumiadmin-acc.global-interaction.com`。前端 API 配置必须是 `https://yumiadmin-acc.global-interaction.com/console`,Caddy 的 `/console/*` 通过 Saudi 内网 CLB `https://10.2.1.12` 回源,并保持上游 Host/SNI 为 `jvapi.haiyihy.com`。 +8. `hyapp-admin-platform-watch.service` 使用 `/opt/hyapp-admin-platform/bin/watch-build.sh`,部署脚本是 `/opt/hyapp-admin-platform/bin/deploy-once.sh`,仓库是 `https://gitea.haiyihy.com/hy/hyapp-admin-platform.git` 的 `main`,构建后写入 `/opt/yumi-admin/frontend-admin/site/hyapp-admin-platform`,公网入口是 `https://admin-acc.global-interaction.com`。前端 API 配置必须保持同源 `/api`,Caddy 的 `/api/*` 回源到 `10.2.1.2:13100`。 +9. 更新或排查这两个 Saudi 前端 watcher 后必须验证:`systemctl is-active chatapp3-admin-watch hyapp-admin-platform-watch`、对应 `.last_built_commit` / `.deployed_commit`、`journalctl -u ...` 或 `/opt/*/logs/deploy.log`,以及公网首页 `200`、未登录 API `401`。 +10. HyApp `cron-service` 当前部署在 Saudi 主服务机器 `new-app-1`,实例 `ins-fi5zufpk`,内网 `10.2.1.4`。 +11. `cron-service` 的 systemd 是 `hyapp-cron-service`,容器是 `hyapp-cron-service`,配置是 `/etc/hyapp/cron-service/config.yaml`,Docker env 是 `/etc/hyapp/cron-service/docker.env`,监听 `13007`。 +12. `cron-service` 当前不在标准 prod inventory 的 `services` 清单里;更新时构建并推送 `10.2.1.3:18082/hyapp/cron-service:`,通过 Tencent TAT 到 `new-app-1` 修改 docker env 的 `IMAGE` 后重启 `hyapp-cron-service`。 +13. 更新 `cron-service` 后必须验证镜像 tag、Docker health、systemd `active` 和 `13007` 监听。 +14. 腾讯云 `ap-singapore` 的实例名 `cron` 机器是 `ins-nt6bsay0` / `10.3.1.14`;当前没有 HyApp `hyapp-cron-service`,不要把它当成 HyApp `cron-service` 发布目标。 ## 测试 server / testbox diff --git a/README.md b/README.md index 486e13d..0d1e66e 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ make up - API:`POST /deploy/api/edgeone/purge-url` - 类型:当前只开放 EdgeOne URL 刷新 - 默认站点:`global-interaction.com` / `zone-3qwew52ihaj2` -- 默认允许域名:`h5.global-interaction.com` +- 默认允许域名:`h5.global-interaction.com`、`vivagames.global-interaction.com`、`asset.global-interaction.com` - 参数:`urls`、`confirmed=true` - 验证:接口等待 EdgeOne 任务结束后返回 `jobId`、`status`、`tasks` - 禁止:页面刷新任意未配置域名;需要新增域名时先改 `EDGEONE_ALLOWED_HOSTS` @@ -79,21 +79,74 @@ make up ### admin-server -- 机器:公网 `43.164.70.49`,内网 `10.2.1.2` -- 腾讯云实例:`ins-p11begwe` -- 区域:`me-saudi-arabia` +- 机器:Saudi `admin-platform`,CVM `ins-p11begwe`,公网 `43.164.70.49`,内网 `10.2.1.2` - systemd:`hyapp-admin-server` - 容器:`hyapp-admin-server` -- 镜像:`10.2.1.3:18082/hyapp/admin-server:` - 配置:`/etc/hyapp/admin-server/config.yaml` - Docker env:`/etc/hyapp/admin-server/docker.env` -- migrations:`/opt/hyapp/admin-server/migrations` +- migration 目录:`/opt/hyapp/admin-server/migrations` +- 镜像仓库:`10.2.1.3:18082/hyapp/admin-server:` - 监听:`10.2.1.2:13100` -- 验证:`systemctl is-active hyapp-admin-server`、`docker inspect hyapp-admin-server --format '{{.Config.Image}}'`、`ss -lntp | grep 13100`、`curl -fsS http://10.2.1.2:13100/healthz`、`curl -fsS http://10.2.1.2:13100/readyz` +- 验证:`systemctl is-active hyapp-admin-server`、`docker ps --filter name=hyapp-admin-server`、`ss -lntp | grep 13100`、`curl http://10.2.1.2:13100/healthz`、`curl http://10.2.1.2:13100/readyz` -`admin-server` 当前不是二进制直传部署,而是和其他 HyApp 后端一样通过内网 Harbor 镜像发布。发布时先在 deploy 机器 `43.164.75.199` 的 `/opt/deploy/sources/hyapp-server` 拉取 Gitea `git@gitea.haiyihy.com:hy/hyapp-server.git` 的 `origin/main`,构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 Tencent TAT 到 `ins-p11begwe` 修改 `/etc/hyapp/admin-server/docker.env` 中的 `IMAGE` 并重启 `hyapp-admin-server`。线上只允许发布 `origin/main`;发布后必须确认容器镜像 tag、systemd `active`、端口监听、`healthz/readyz` 正常。 +`admin-server` 更新只允许发布 `origin/main`。deploy 机拉取 Gitea `git@gitea.haiyihy.com:hy/hyapp-server.git` 的 `origin/main`,构建并推送 `10.2.1.3:18082/hyapp/admin-server:`;然后通过 Tencent TAT 到 `ins-p11begwe` 修改 `/etc/hyapp/admin-server/docker.env` 的 `IMAGE`,执行 `systemctl restart hyapp-admin-server`。`admin-platform` 已配置 Docker 直拉内网 Harbor:`/etc/docker/daemon.json` 包含 insecure registry `10.2.1.3:18082`,`/root/.docker/config.json` 包含 Harbor 登录凭据。 -注意:`deploy/tencent_tat/hyapp_admin_server_deploy.py` 是旧广州机器 `134.175.160.86 / 172.16.0.6` 的二进制发布链路,不适用于当前 Saudi `admin-server`。除非先更新脚本目标和部署模型,否则不要用它发布生产 `admin-server`。 +发布后必须确认:systemd `active`、容器镜像 tag/digest 正确、`10.2.1.2:13100` 监听、`healthz/readyz` 正常、Caddy 容器 `yumi-admin-caddy` 运行、`https://admin-acc.global-interaction.com/` 返回 `200`、未登录 `https://admin-acc.global-interaction.com/api/v1/auth/me` 返回 `401`。 + +### Saudi admin-platform 前端 + +- 机器:公网 `43.164.70.49`,内网 `10.2.1.2` +- CVM:`ins-p11begwe` +- 区域:`me-saudi-arabia` +- Caddy 容器:`yumi-admin-caddy` +- Caddy 宿主机目录:`/opt/yumi-admin/frontend-admin` +- 静态根目录:`/opt/yumi-admin/frontend-admin/site` +- Node 运行时:`/opt/node-v22.18.0-linux-x64` + +这台机器承接两个加速后台前端,都是本机拉 Gitea、构建、替换 Caddy 静态目录: + +| 入口 | watcher | 仓库 | 静态目录 | API 回源 | +| --- | --- | --- | --- | --- | +| `https://yumiadmin-acc.global-interaction.com` | `chatapp3-admin-watch.service` | `git@gitea.haiyihy.com:hy/chatapp3-admin.git` `main` | `/opt/yumi-admin/frontend-admin/site/yumiadmin-acc` | `/console/*` -> Saudi 内网 CLB `https://10.2.1.12`,Host/SNI `jvapi.haiyihy.com` | +| `https://admin-acc.global-interaction.com` | `hyapp-admin-platform-watch.service` | `https://gitea.haiyihy.com/hy/hyapp-admin-platform.git` `main` | `/opt/yumi-admin/frontend-admin/site/hyapp-admin-platform` | `/api/*` -> `http://10.2.1.2:13100` | + +两个 watcher 都是 5 秒循环,入口脚本分别是: + +```bash +/opt/chatapp3-admin/bin/watch-build.sh +/opt/hyapp-admin-platform/bin/watch-build.sh +``` + +实际部署脚本分别是: + +```bash +/opt/chatapp3-admin/bin/deploy-once.sh +/opt/hyapp-admin-platform/bin/deploy-once.sh +``` + +部署完成标记: + +```bash +/opt/chatapp3-admin/.last_built_commit +/opt/hyapp-admin-platform/.deployed_commit +``` + +排查或变更后必须验证: + +```bash +systemctl is-active chatapp3-admin-watch.service hyapp-admin-platform-watch.service +tail -n 100 /opt/chatapp3-admin/logs/deploy.log +tail -n 100 /opt/hyapp-admin-platform/logs/deploy.log +curl -I https://yumiadmin-acc.global-interaction.com/ +curl -I https://admin-acc.global-interaction.com/ +``` + +未登录 API 返回 `401` 是正常结果,用来证明反代已经打到后端鉴权层: + +```bash +curl -sS https://yumiadmin-acc.global-interaction.com/console/ +curl -sS https://admin-acc.global-interaction.com/api/v1/admin/apps +``` ### cron-service diff --git a/deploy/README.md b/deploy/README.md index ad27660..7e62660 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -42,14 +42,14 @@ npm run deploy:serve 真实接口: - `GET /deploy/api/health`:只返回凭据是否存在,不返回密钥明文。 -- `POST /deploy/api/edgeone/purge-url`:提交 EdgeOne URL 刷新任务,必须带 `confirmed=true`;只允许 `EDGEONE_ALLOWED_HOSTS` 中的域名,默认 `h5.global-interaction.com`。 +- `POST /deploy/api/edgeone/purge-url`:提交 EdgeOne URL 刷新任务,必须带 `confirmed=true`;只允许 `EDGEONE_ALLOWED_HOSTS` 中的域名,默认 `h5.global-interaction.com`、`vivagames.global-interaction.com`、`asset.global-interaction.com`。 - `GET /deploy/api/hyapp/inventory`:读取 HyApp 生产 inventory。 - `GET /deploy/api/hyapp/plan?services=gateway-service,room-service`:生成发布计划,不执行远端动作。 - `GET /deploy/api/hyapp/discover?services=user-service&remote=1`:通过 Tencent TAT 连接 deploy 机器 `43.164.75.199`,再由 deploy 机器 SSH 到业务机器读取真实实例、systemd、Docker、镜像、资源、端口和 CLB 权重。 - `GET /deploy/api/hyapp/discover?services=user-service&remote=1&includeConfig=1`:读取详情 YAML,密钥字段脱敏。 - `GET /deploy/api/hyapp/resources?remote=1`:数据资源状态。链路:TAT -> deploy;业务服务器配置 SSH 失败后 TAT 兜底。 - `POST /deploy/api/hyapp/deploy`:真实发布,必须带 `confirmed=true`;测试时使用 `dryRun=true`。 -- `POST /deploy/api/hyapp/admin-server/deploy`:历史二进制发布入口,目标是旧广州机器 `134.175.160.86 / 172.16.0.6`,不适用于当前生产 `admin-server`。当前生产 `admin-server` 在 `43.164.70.49 / 10.2.1.2`(实例 `ins-p11begwe`)以 Docker 方式运行,应构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 TAT 更新 `/etc/hyapp/admin-server/docker.env` 的 `IMAGE` 并重启 `hyapp-admin-server`。 +- `POST /deploy/api/hyapp/admin-server/deploy`:生产 `admin-server` 固定发布入口,必须带 `confirmed=true`;发布只允许 `origin/main`,deploy 机构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 Tencent TAT 到 Saudi `admin-platform` 实例 `ins-p11begwe` 更新 `/etc/hyapp/admin-server/docker.env` 的 `IMAGE` 并重启 `hyapp-admin-server`,最后验证 `10.2.1.2:13100` 的 `healthz/readyz`、Caddy 和公网入口。 - `POST /deploy/api/hyapp/restart`:真实重启,必须带 `confirmed=true`;测试时使用 `dryRun=true`。 - `GET /deploy/api/hyapp/testbox/status`:读取测试机 test 分支、timer 和 Compose/systemd 服务状态。 - `POST /deploy/api/hyapp/testbox/service`:测试机服务 `update/start/stop/restart`,必须带 `confirmed=true`。 diff --git a/deploy/mysql/initdb/999_local_grants.sql b/deploy/mysql/initdb/999_local_grants.sql index 1af9b24..1e22504 100644 --- a/deploy/mysql/initdb/999_local_grants.sql +++ b/deploy/mysql/initdb/999_local_grants.sql @@ -12,6 +12,7 @@ GRANT ALL PRIVILEGES ON hyapp_admin.* TO 'hyapp'@'%'; GRANT ALL PRIVILEGES ON hyapp_cron.* TO 'hyapp'@'%'; GRANT ALL PRIVILEGES ON hyapp_game.* TO 'hyapp'@'%'; GRANT ALL PRIVILEGES ON hyapp_notice.* TO 'hyapp'@'%'; +GRANT ALL PRIVILEGES ON hyapp_robot.* TO 'hyapp'@'%'; GRANT ALL PRIVILEGES ON hyapp_statistics.* TO 'hyapp'@'%'; FLUSH PRIVILEGES; diff --git a/deploy/rocketmq/broker.conf b/deploy/rocketmq/broker.conf index e6cf93e..66f8946 100644 --- a/deploy/rocketmq/broker.conf +++ b/deploy/rocketmq/broker.conf @@ -6,4 +6,7 @@ fileReservedTime = 48 brokerRole = ASYNC_MASTER flushDiskType = ASYNC_FLUSH autoCreateTopicEnable = true +# Docker Desktop 上宿主机二进制通过 NameServer 拿到 broker 地址后不能访问容器内网 IP; +# 本地调试默认跑宿主机 Go 服务,所以广播 compose 映射到宿主机的 broker 端口。 +brokerIP1 = 127.0.0.1 listenPort = 10911 diff --git a/deploy/server.mjs b/deploy/server.mjs index 4206f31..cc7f9c2 100644 --- a/deploy/server.mjs +++ b/deploy/server.mjs @@ -27,7 +27,8 @@ const tencentEnvFile = process.env.TENCENT_ENV_FILE || ""; const credentialFile = resolve(process.env.TENCENT_CREDENTIALS_FILE || join(rootDir, ".env")); const deployEnv = { ...process.env }; const edgeoneConfig = { - allowedHosts: process.env.EDGEONE_ALLOWED_HOSTS || "h5.global-interaction.com", + allowedHosts: + process.env.EDGEONE_ALLOWED_HOSTS || "h5.global-interaction.com,vivagames.global-interaction.com,asset.global-interaction.com", zoneId: process.env.EDGEONE_ZONE_ID || "zone-3qwew52ihaj2", zoneName: process.env.EDGEONE_ZONE_NAME || "global-interaction.com", }; diff --git a/deploy/standalone/docker/deploy-platform.env.example b/deploy/standalone/docker/deploy-platform.env.example index 0e4d10d..ef86c2f 100644 --- a/deploy/standalone/docker/deploy-platform.env.example +++ b/deploy/standalone/docker/deploy-platform.env.example @@ -3,7 +3,7 @@ CONTAINER_NAME=hyapp-deploy-platform STOP_TIMEOUT_SEC=15 EDGEONE_ZONE_ID=zone-3qwew52ihaj2 EDGEONE_ZONE_NAME=global-interaction.com -EDGEONE_ALLOWED_HOSTS=h5.global-interaction.com +EDGEONE_ALLOWED_HOSTS=h5.global-interaction.com,vivagames.global-interaction.com,asset.global-interaction.com DEPLOY_ADMIN_SERVER_COMMAND_TIMEOUT_MS=1800000 # Tencent Cloud credentials are required for remote TAT queries and EdgeOne refresh. diff --git a/deploy/standalone/docker/luck-gateway.env.example b/deploy/standalone/docker/luck-gateway.env.example new file mode 100644 index 0000000..ca2b065 --- /dev/null +++ b/deploy/standalone/docker/luck-gateway.env.example @@ -0,0 +1,7 @@ +# luck-gateway is intentionally env-only: it exposes the simplified external lucky gift HTTP entry and delegates all rules to lucky-gift-service. +IMAGE=10.2.1.3:18082/hyapp/luck-gateway:REPLACE_WITH_RELEASE_TAG +CONTAINER_NAME=hyapp-luck-gateway +STOP_TIMEOUT_SEC=60 +LUCK_GATEWAY_HTTP_ADDR=:13014 +LUCKY_GIFT_GRPC_ADDR=lucky-gift-service.internal:13013 +LUCK_GATEWAY_ALLOWED_APPS=aslan,yumi diff --git a/deploy/standalone/docker/lucky-gift-service.env.example b/deploy/standalone/docker/lucky-gift-service.env.example new file mode 100644 index 0000000..32037be --- /dev/null +++ b/deploy/standalone/docker/lucky-gift-service.env.example @@ -0,0 +1,5 @@ +# Image is immutable per release; TAT deploy rewrites only IMAGE before restarting systemd. +IMAGE=10.2.1.3:18082/hyapp/lucky-gift-service:REPLACE_WITH_RELEASE_TAG +CONTAINER_NAME=hyapp-lucky-gift-service +CONFIG_PATH=/etc/hyapp/lucky-gift-service/config.yaml +STOP_TIMEOUT_SEC=90 diff --git a/deploy/standalone/docker/robot-service.env.example b/deploy/standalone/docker/robot-service.env.example new file mode 100644 index 0000000..c0e351c --- /dev/null +++ b/deploy/standalone/docker/robot-service.env.example @@ -0,0 +1,4 @@ +IMAGE=10.2.1.3:18082/hyapp/robot-service:REPLACE_WITH_RELEASE_TAG +CONTAINER_NAME=hyapp-robot-service +CONFIG_PATH=/etc/hyapp/robot-service/config.yaml +STOP_TIMEOUT_SEC=60 diff --git a/deploy/standalone/systemd/hyapp-luck-gateway.service b/deploy/standalone/systemd/hyapp-luck-gateway.service new file mode 100644 index 0000000..d200226 --- /dev/null +++ b/deploy/standalone/systemd/hyapp-luck-gateway.service @@ -0,0 +1,23 @@ +[Unit] +Description=Hyapp luck-gateway container +Requires=docker.service +After=network-online.target docker.service +Wants=network-online.target +StartLimitIntervalSec=120 +StartLimitBurst=3 + +[Service] +Type=simple +EnvironmentFile=/etc/hyapp/luck-gateway/docker.env +ExecStartPre=-/usr/bin/env docker rm -f ${CONTAINER_NAME} +ExecStart=/usr/bin/env docker run --name=${CONTAINER_NAME} --rm --network=host --init --pull=never --stop-signal=SIGTERM --stop-timeout=${STOP_TIMEOUT_SEC} --env-file=/etc/hyapp/luck-gateway/docker.env --env=TZ=UTC --log-driver=json-file --log-opt=max-size=100m --log-opt=max-file=5 --health-cmd="wget -q -O - http://127.0.0.1:13014/healthz/ready >/dev/null" --health-interval=5s --health-timeout=3s --health-retries=6 --health-start-period=10s ${IMAGE} +ExecStop=/usr/bin/env docker stop --time=${STOP_TIMEOUT_SEC} ${CONTAINER_NAME} +Restart=on-failure +RestartSec=5s +TimeoutStartSec=60 +TimeoutStopSec=90 +KillMode=none +LimitNOFILE=1048576 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/standalone/systemd/hyapp-lucky-gift-service.service b/deploy/standalone/systemd/hyapp-lucky-gift-service.service new file mode 100644 index 0000000..26fbd85 --- /dev/null +++ b/deploy/standalone/systemd/hyapp-lucky-gift-service.service @@ -0,0 +1,23 @@ +[Unit] +Description=Hyapp lucky-gift-service container +Requires=docker.service +After=network-online.target docker.service +Wants=network-online.target +StartLimitIntervalSec=120 +StartLimitBurst=3 + +[Service] +Type=simple +EnvironmentFile=/etc/hyapp/lucky-gift-service/docker.env +ExecStartPre=-/usr/bin/env docker rm -f ${CONTAINER_NAME} +ExecStart=/usr/bin/env docker run --name=${CONTAINER_NAME} --rm --network=host --init --pull=never --stop-signal=SIGTERM --stop-timeout=${STOP_TIMEOUT_SEC} --env=TZ=UTC --log-driver=json-file --log-opt=max-size=100m --log-opt=max-file=5 --mount=type=bind,src=${CONFIG_PATH},dst=/app/config.yaml,readonly --health-cmd="/app/grpc-health-probe -addr=127.0.0.1:13013 -service=lucky-gift-service" --health-interval=5s --health-timeout=3s --health-retries=6 --health-start-period=10s ${IMAGE} +ExecStop=/usr/bin/env docker stop --time=${STOP_TIMEOUT_SEC} ${CONTAINER_NAME} +Restart=on-failure +RestartSec=5s +TimeoutStartSec=60 +TimeoutStopSec=120 +KillMode=none +LimitNOFILE=1048576 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/standalone/systemd/hyapp-robot-service.service b/deploy/standalone/systemd/hyapp-robot-service.service new file mode 100644 index 0000000..e51da2b --- /dev/null +++ b/deploy/standalone/systemd/hyapp-robot-service.service @@ -0,0 +1,23 @@ +[Unit] +Description=Hyapp robot-service container +Requires=docker.service +After=network-online.target docker.service +Wants=network-online.target +StartLimitIntervalSec=120 +StartLimitBurst=3 + +[Service] +Type=simple +EnvironmentFile=/etc/hyapp/robot-service/docker.env +ExecStartPre=-/usr/bin/env docker rm -f ${CONTAINER_NAME} +ExecStart=/usr/bin/env docker run --name=${CONTAINER_NAME} --rm --network=host --init --pull=never --stop-signal=SIGTERM --stop-timeout=${STOP_TIMEOUT_SEC} --env=TZ=UTC --log-driver=json-file --log-opt=max-size=100m --log-opt=max-file=5 --mount=type=bind,src=${CONFIG_PATH},dst=/app/config.yaml,readonly --health-cmd="wget -q -O - http://127.0.0.1:13111/healthz/ready >/dev/null" --health-interval=5s --health-timeout=3s --health-retries=6 --health-start-period=10s ${IMAGE} +ExecStop=/usr/bin/env docker stop --time=${STOP_TIMEOUT_SEC} ${CONTAINER_NAME} +Restart=on-failure +RestartSec=5s +TimeoutStartSec=60 +TimeoutStopSec=90 +KillMode=none +LimitNOFILE=1048576 + +[Install] +WantedBy=multi-user.target diff --git a/deploy/tencent_tat/README.md b/deploy/tencent_tat/README.md index 98c7194..bc88130 100644 --- a/deploy/tencent_tat/README.md +++ b/deploy/tencent_tat/README.md @@ -148,18 +148,17 @@ python3 deploy/tencent_tat/hyapp_data_resources.py resources \ --inventory deploy/tencent_tat/hyapp-services.inventory.prod.json ``` -生产 `admin-server` 当前运行在 Saudi 机器 `43.164.70.49 / 10.2.1.2`(实例 `ins-p11begwe`),以 Docker 容器 `hyapp-admin-server` 运行: +生产 `admin-server` 固定从 Gitea `origin/main` 发布,当前运行在 Saudi `admin-platform` 机器 `ins-p11begwe` / `10.2.1.2`,不是广州独立机。发布链路是 deploy 机本机构建镜像并推送 Harbor,然后用 Tencent TAT 到 `ins-p11begwe` 更新 Docker env: -- systemd:`hyapp-admin-server` -- 镜像:`10.2.1.3:18082/hyapp/admin-server:` -- Docker env:`/etc/hyapp/admin-server/docker.env` -- 配置:`/etc/hyapp/admin-server/config.yaml` -- migrations:`/opt/hyapp/admin-server/migrations` -- 监听:`10.2.1.2:13100` +```bash +docker build -f server/admin/Dockerfile \ + -t 10.2.1.3:18082/hyapp/admin-server: . +docker push 10.2.1.3:18082/hyapp/admin-server: +``` -发布时先在 deploy 机器 `/opt/deploy/sources/hyapp-server` 拉取 `git@gitea.haiyihy.com:hy/hyapp-server.git` 的 `origin/main`,构建并推送 `10.2.1.3:18082/hyapp/admin-server:`,再通过 TAT 到 `ins-p11begwe` 修改 `/etc/hyapp/admin-server/docker.env` 中的 `IMAGE` 并重启 `hyapp-admin-server`。生产不允许切换到其他分支;发布后必须验证 `systemctl is-active hyapp-admin-server`、容器镜像 tag、`10.2.1.2:13100` 监听、`/healthz` 和 `/readyz`。 +`admin-platform` 机器已配置 Docker 直拉内网 Harbor:`/etc/docker/daemon.json` 包含 insecure registry `10.2.1.3:18082`,`/root/.docker/config.json` 包含 Harbor 登录凭据。TAT 到 `ins-p11begwe` 后只更新 `/etc/hyapp/admin-server/docker.env` 的 `IMAGE`,再执行 `systemctl restart hyapp-admin-server`。 -注意:`hyapp_admin_server_deploy.py` 是旧广州机器 `134.175.160.86 / 172.16.0.6` 的二进制发布脚本,不适用于当前生产 `admin-server`。除非先更新脚本目标和部署模型,否则不要用它发布生产 `admin-server`。 +发布后必须验证 `systemctl is-active hyapp-admin-server`、容器镜像 tag/digest、`10.2.1.2:13100` 的 `/healthz` 和 `/readyz`、`yumi-admin-caddy` 容器运行、公网 `https://admin-acc.global-interaction.com/` 返回 `200`、未登录 `https://admin-acc.global-interaction.com/api/v1/auth/me` 返回 `401`。生产不允许切换到其他分支。 规则: diff --git a/deploy/tencent_tat/edgeone_purge.py b/deploy/tencent_tat/edgeone_purge.py index dbbe72f..df797ab 100644 --- a/deploy/tencent_tat/edgeone_purge.py +++ b/deploy/tencent_tat/edgeone_purge.py @@ -14,7 +14,7 @@ from urllib.parse import urlparse, urlunparse DEFAULT_EDGEONE_ZONE_ID = "zone-3qwew52ihaj2" DEFAULT_EDGEONE_ZONE_NAME = "global-interaction.com" -DEFAULT_EDGEONE_ALLOWED_HOSTS = "h5.global-interaction.com" +DEFAULT_EDGEONE_ALLOWED_HOSTS = "h5.global-interaction.com,vivagames.global-interaction.com,asset.global-interaction.com" TERMINAL_STATUSES = {"success", "failed", "timeout", "canceled"} diff --git a/deploy/tencent_tat/hyapp-services.inventory.prod.example.json b/deploy/tencent_tat/hyapp-services.inventory.prod.example.json index 853caff..19e6687 100644 --- a/deploy/tencent_tat/hyapp-services.inventory.prod.example.json +++ b/deploy/tencent_tat/hyapp-services.inventory.prod.example.json @@ -24,6 +24,7 @@ "wallet-service", "user-service", "activity-service", + "lucky-gift-service", "cron-service", "game-service", "notice-service", @@ -38,6 +39,7 @@ "owner": "后端平台", "related_services": [ "gateway-service", + "luck-gateway", "room-service", "user-service" ] @@ -200,6 +202,37 @@ "drain_seconds": 5 } }, + "lucky-gift-service": { + "unit": "hyapp-lucky-gift-service", + "container": "hyapp-lucky-gift-service", + "env_file": "/etc/hyapp/lucky-gift-service/docker.env", + "image_template": "${REGISTRY}/lucky-gift-service:${TAG}", + "target_port": 13013, + "hosts": [ + "new-app-activity-1", + "new-app-activity-2" + ], + "clb": { + "enabled": false, + "drain_seconds": 0 + } + }, + "luck-gateway": { + "unit": "hyapp-luck-gateway", + "container": "hyapp-luck-gateway", + "env_file": "/etc/hyapp/luck-gateway/docker.env", + "config_required": false, + "image_template": "${REGISTRY}/luck-gateway:${TAG}", + "target_port": 13014, + "hosts": [ + "gateway-1", + "gateway-2" + ], + "clb": { + "enabled": false, + "drain_seconds": 0 + } + }, "notice-service": { "unit": "hyapp-notice-service", "container": "hyapp-notice-service", @@ -238,6 +271,26 @@ "drain_seconds": 5 } }, + "robot-service": { + "unit": "hyapp-robot-service", + "container": "hyapp-robot-service", + "env_file": "/etc/hyapp/robot-service/docker.env", + "config_path": "/etc/hyapp/robot-service/config.yaml", + "image_template": "${REGISTRY}/robot-service:${TAG}", + "target_port": 13011, + "hosts": [ + "new-app-1", + "new-app-2" + ], + "clb": { + "enabled": true, + "load_balancer_id": "lb-epvnr4o0", + "listener_ids": [ + "lbl-pd35q9go" + ], + "drain_seconds": 5 + } + }, "statistics-service": { "unit": "hyapp-statistics-service", "container": "hyapp-statistics-service", diff --git a/deploy/tencent_tat/hyapp_admin_server_deploy.py b/deploy/tencent_tat/hyapp_admin_server_deploy.py index d6e32bb..c678d24 100644 --- a/deploy/tencent_tat/hyapp_admin_server_deploy.py +++ b/deploy/tencent_tat/hyapp_admin_server_deploy.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse import json +import os import shlex import sys from pathlib import Path @@ -15,33 +16,15 @@ from deploy.tencent_tat.hyapp_tat_deploy import build_tat_client, load_env_file, DEFAULT_REPO_URL = "git@gitea.haiyihy.com:hy/hyapp-server.git" DEFAULT_SOURCE_DIR = "/opt/deploy/sources/hyapp-server" DEFAULT_BRANCH = "main" +DEFAULT_ADMIN_REGION = "ap-guangzhou" +DEFAULT_ADMIN_INSTANCE_ID = "ins-0x5mjwmc" DEFAULT_ADMIN_HOST = "134.175.160.86" DEFAULT_ADMIN_BIND_ADDR = "172.16.0.6" DEFAULT_ADMIN_PORT = 13100 -def shell_join(items: list[str]) -> str: - return " ".join(shlex.quote(item) for item in items) - - -def admin_endpoint(host: str, user: str) -> str: - return f"{user}@{host}" if user else host - - def build_remote_script(args: argparse.Namespace) -> str: - endpoint = admin_endpoint(args.admin_host, args.admin_user) dry_run = "1" if args.dry_run else "0" - ssh_option_args = [ - "-o", - "BatchMode=yes", - "-o", - "StrictHostKeyChecking=accept-new", - "-o", - f"ConnectTimeout={args.ssh_connect_timeout}", - ] - ssh_opts = ["ssh", *ssh_option_args] - scp_cmd = shell_join(["timeout", str(args.transfer_timeout_seconds), "scp", *ssh_option_args]) - admin_ssh = shell_join([*ssh_opts, endpoint]) return f"""#!/usr/bin/env bash set -euo pipefail @@ -50,35 +33,45 @@ REPO_URL={shlex.quote(args.repo_url)} SOURCE_DIR={shlex.quote(args.source_dir)} BRANCH={shlex.quote(args.branch)} DRY_RUN={dry_run} -ADMIN_ENDPOINT={shlex.quote(endpoint)} ADMIN_BIND_ADDR={shlex.quote(args.admin_bind_addr)} ADMIN_PORT={shlex.quote(str(args.admin_port))} -ADMIN_SSH={shlex.quote(admin_ssh)} export GIT_SSH_COMMAND="ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new -o ConnectTimeout=15" +export GOPROXY="${{GOPROXY:-https://goproxy.cn|https://proxy.golang.org|direct}}" +export GOSUMDB="${{GOSUMDB:-sum.golang.org}}" +echo "admin_host=$(hostname)" echo "repo=$REPO_URL" echo "source_dir=$SOURCE_DIR" echo "branch=$BRANCH" -echo "admin_endpoint=$ADMIN_ENDPOINT" if [ "$DRY_RUN" = "1" ]; then + echo "git=$(git --version 2>/dev/null || true)" + echo "go=$(go version 2>/dev/null || true)" target_commit="$(git ls-remote "$REPO_URL" "refs/heads/$BRANCH" | awk '{{print $1}}')" if [ -z "$target_commit" ]; then echo "cannot resolve origin/$BRANCH" >&2 exit 12 fi echo "target_commit=$target_commit" - $ADMIN_SSH "ADMIN_BIND_ADDR='$ADMIN_BIND_ADDR' ADMIN_PORT='$ADMIN_PORT' bash -s" <<'REMOTE' -set -e -echo "admin_active=$(systemctl is-active hyapp-admin-server || true)" -ss -lntp | grep "$ADMIN_PORT" || true -curl -fsS -m 3 "http://$ADMIN_BIND_ADDR:$ADMIN_PORT/healthz" || true -echo -REMOTE + echo "admin_active=$(systemctl is-active hyapp-admin-server || true)" + ss -lntp | grep "$ADMIN_PORT" || true + curl -fsS -m 3 "http://$ADMIN_BIND_ADDR:$ADMIN_PORT/healthz" || true + echo exit 0 fi +if ! command -v git >/dev/null 2>&1 || ! command -v go >/dev/null 2>&1; then + if command -v dnf >/dev/null 2>&1; then + dnf install -y git golang + elif command -v yum >/dev/null 2>&1; then + yum install -y git golang + else + echo "git/go missing and no supported package manager found" >&2 + exit 13 + fi +fi + if [ -d "$SOURCE_DIR/.git" ]; then cd "$SOURCE_DIR" git remote set-url origin "$REPO_URL" @@ -95,42 +88,25 @@ git clean -fd commit="$(git rev-parse HEAD)" short_commit="$(git rev-parse --short HEAD)" -build_id="$(date +%Y%m%d%H%M%S)-$short_commit" -build_image="hyapp/admin-server-build:$build_id" -local_binary="/tmp/admin-server-$build_id" -remote_binary="/tmp/admin-server-$build_id" +build_binary="/tmp/admin-server-$short_commit" echo "commit=$commit" -echo "build_id=$build_id" +echo "go=$(go version)" -docker build -t "$build_image" -f server/admin/Dockerfile . -container_id="$(docker create "$build_image")" -trap 'docker rm -f "$container_id" >/dev/null 2>&1 || true' EXIT -docker cp "$container_id:/app/server" "$local_binary" -docker rm "$container_id" >/dev/null -trap - EXIT -chmod 0755 "$local_binary" -binary_sha="$(sha256sum "$local_binary" | awk '{{print $1}}')" -binary_size="$(stat -c %s "$local_binary")" +cd "$SOURCE_DIR/server/admin" +GOWORK=off go mod download +GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o "$build_binary" ./cmd/server +chmod 0755 "$build_binary" +binary_sha="$(sha256sum "$build_binary" | awk '{{print $1}}')" +binary_size="$(stat -c %s "$build_binary")" echo "binary_sha=$binary_sha" echo "binary_size=$binary_size" -{scp_cmd} "$local_binary" "$ADMIN_ENDPOINT:$remote_binary" - -$ADMIN_SSH "REMOTE_BINARY='$remote_binary' EXPECTED_SHA='$binary_sha' ADMIN_BIND_ADDR='$ADMIN_BIND_ADDR' ADMIN_PORT='$ADMIN_PORT' COMMIT='$commit' bash -s" <<'REMOTE' -set -euo pipefail - BIN=/opt/hyapp/admin-server/admin-server BACKUP="$BIN.bak.$(date +%Y%m%d%H%M%S)" -actual_sha="$(sha256sum "$REMOTE_BINARY" | awk '{{print $1}}')" -if [ "$actual_sha" != "$EXPECTED_SHA" ]; then - echo "uploaded binary sha mismatch: $actual_sha != $EXPECTED_SHA" >&2 - exit 21 -fi - cp "$BIN" "$BACKUP" -install -o root -g root -m 0755 "$REMOTE_BINARY" "$BIN.new" +install -o root -g root -m 0755 "$build_binary" "$BIN.new" mv "$BIN.new" "$BIN" systemctl restart hyapp-admin-server @@ -160,17 +136,41 @@ echo "installed_sha=$(sha256sum "$BIN" | awk '{{print $1}}')" echo "listener=$(ss -lntp | grep "$ADMIN_BIND_ADDR:$ADMIN_PORT" || true)" echo "healthz=$(cat /tmp/hyapp-admin-healthz.out)" echo "readyz=$(cat /tmp/hyapp-admin-readyz.out)" -REMOTE """ def run_deploy(args: argparse.Namespace) -> dict[str, Any]: inventory = load_inventory(args.inventory) - client = build_tat_client(inventory) + admin_inventory = { + "region": args.admin_region, + "deploy_server": {"instance_id": args.admin_instance_id}, + "hosts": {"admin-server": {"instance_id": args.admin_instance_id, "private_ip": args.admin_bind_addr}}, + "services": { + "admin-server": { + "unit": "hyapp-admin-server", + "container": "hyapp-admin-server", + "env_file": "/etc/hyapp/admin-server/config.yaml", + "target_port": args.admin_port, + "hosts": ["admin-server"], + } + }, + } + previous_region = None + region_was_set = "TENCENTCLOUD_REGION" in os.environ + if region_was_set: + previous_region = os.environ["TENCENTCLOUD_REGION"] + os.environ["TENCENTCLOUD_REGION"] = args.admin_region + try: + client = build_tat_client(admin_inventory) + finally: + if region_was_set and previous_region is not None: + os.environ["TENCENTCLOUD_REGION"] = previous_region + elif not region_was_set: + os.environ.pop("TENCENTCLOUD_REGION", None) script = build_remote_script(args) result = run_tat_shell( client, - instance_id=inventory["deploy_server"]["instance_id"], + instance_id=args.admin_instance_id, script=script, command_name="hyapp-admin-server-deploy", timeout_seconds=args.timeout_seconds, @@ -179,29 +179,30 @@ def run_deploy(args: argparse.Namespace) -> dict[str, Any]: output = str(result.get("output") or "") return { "adminHost": args.admin_host, + "adminInstanceId": args.admin_instance_id, + "adminRegion": args.admin_region, "dryRun": args.dry_run, "ok": result.get("status") == "SUCCESS", "output": output[-12000:], "sourceDir": args.source_dir, "status": result.get("status"), - "target": inventory.get("deploy_server") or {}, + "target": admin_inventory.get("deploy_server") or {}, } def build_parser() -> argparse.ArgumentParser: - parser = argparse.ArgumentParser(description="Deploy production admin-server from Gitea origin/main through the deploy host.") + parser = argparse.ArgumentParser(description="Deploy production admin-server by pulling Gitea origin/main on the Guangzhou admin host.") parser.add_argument("action", choices=["deploy"]) parser.add_argument("--env-file", default="") parser.add_argument("--inventory", default="deploy/tencent_tat/hyapp-services.inventory.prod.example.json") parser.add_argument("--repo-url", default=DEFAULT_REPO_URL) parser.add_argument("--source-dir", default=DEFAULT_SOURCE_DIR) parser.add_argument("--branch", default=DEFAULT_BRANCH) + parser.add_argument("--admin-region", default=DEFAULT_ADMIN_REGION) + parser.add_argument("--admin-instance-id", default=DEFAULT_ADMIN_INSTANCE_ID) parser.add_argument("--admin-host", default=DEFAULT_ADMIN_HOST) - parser.add_argument("--admin-user", default="") parser.add_argument("--admin-bind-addr", default=DEFAULT_ADMIN_BIND_ADDR) parser.add_argument("--admin-port", type=int, default=DEFAULT_ADMIN_PORT) - parser.add_argument("--ssh-connect-timeout", type=int, default=15) - parser.add_argument("--transfer-timeout-seconds", type=int, default=300) parser.add_argument("--timeout-seconds", type=int, default=1800) parser.add_argument("--dry-run", action="store_true") parser.add_argument("--yes", action="store_true") diff --git a/deploy/tencent_tat/tests/test_hyapp_admin_server_deploy.py b/deploy/tencent_tat/tests/test_hyapp_admin_server_deploy.py index 2ff8737..d5127ee 100644 --- a/deploy/tencent_tat/tests/test_hyapp_admin_server_deploy.py +++ b/deploy/tencent_tat/tests/test_hyapp_admin_server_deploy.py @@ -15,21 +15,26 @@ class AdminServerDeployScriptTests(unittest.TestCase): args = argparse.Namespace( admin_bind_addr="172.16.0.6", admin_host="134.175.160.86", + admin_instance_id="ins-0x5mjwmc", admin_port=13100, - admin_user="", + admin_region="ap-guangzhou", branch="main", dry_run=False, repo_url="git@gitea.haiyihy.com:hy/hyapp-server.git", source_dir="/opt/deploy/sources/hyapp-server", - ssh_connect_timeout=15, - transfer_timeout_seconds=300, ) script = admin_deploy.build_remote_script(args) self.assertIn("git fetch --prune origin \"$BRANCH\"", script) self.assertIn("git checkout -B \"$BRANCH\" \"origin/$BRANCH\"", script) - self.assertIn("docker build -t \"$build_image\" -f server/admin/Dockerfile .", script) - self.assertIn("timeout 300 scp", script) + self.assertIn("git clone \"$REPO_URL\" \"$SOURCE_DIR\"", script) + self.assertIn("GOWORK=off go mod download", script) + self.assertIn("GOWORK=off CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o \"$build_binary\" ./cmd/server", script) + self.assertNotIn("docker build", script) + self.assertNotIn("docker push", script) + self.assertNotIn("docker pull", script) + self.assertNotIn("10.2.1.3:18082", script) + self.assertNotIn("timeout 300 scp", script) self.assertNotIn("rsync -az --partial", script) self.assertIn("systemctl restart hyapp-admin-server", script) self.assertIn("http://$ADMIN_BIND_ADDR:$ADMIN_PORT/healthz", script) diff --git a/deploy/tencent_tat/validate_rendered_configs.py b/deploy/tencent_tat/validate_rendered_configs.py index 6001289..c61c9ac 100644 --- a/deploy/tencent_tat/validate_rendered_configs.py +++ b/deploy/tencent_tat/validate_rendered_configs.py @@ -72,7 +72,15 @@ def selected_hosts(service: dict[str, Any], raw_hosts: str) -> list[str]: return requested -def validate_service_templates(hyapp_root: Path, service_name: str) -> list[str]: +def service_config_required(service: dict[str, Any]) -> bool: + # 少数边缘入口是 env-only 进程,例如 luck-gateway 只承载 HTTP 转发边界; + # inventory 显式标记后跳过 YAML contract 校验,避免为了校验脚本伪造无效 config。 + return bool(service.get("config_required", True)) + + +def validate_service_templates(hyapp_root: Path, service_name: str, service: dict[str, Any]) -> list[str]: + if not service_config_required(service): + return [] errors: list[str] = [] config_dir = hyapp_root / "services" / service_name / "configs" configs = {name: load_yaml(config_dir / name) for name in CONFIG_FILENAMES} @@ -87,7 +95,9 @@ def validate_service_templates(hyapp_root: Path, service_name: str) -> list[str] return errors -def validate_rendered_config(hyapp_root: Path, service_name: str, host_name: str, rendered_dir: Path) -> list[str]: +def validate_rendered_config(hyapp_root: Path, service_name: str, service: dict[str, Any], host_name: str, rendered_dir: Path) -> list[str]: + if not service_config_required(service): + return [] contract = load_yaml(hyapp_root / "services" / service_name / "configs" / "config.tencent.example.yaml") rendered_path = rendered_dir / host_name / service_name / "config.yaml" rendered = load_yaml(rendered_path) @@ -117,11 +127,12 @@ def main(argv: list[str]) -> int: rendered_dir = Path(args.rendered_dir).expanduser().resolve() if args.rendered_dir else None errors: list[str] = [] for service_name in selected_service_names(inventory, args.services): - errors.extend(validate_service_templates(hyapp_root, service_name)) + service = inventory["services"][service_name] + errors.extend(validate_service_templates(hyapp_root, service_name, service)) if rendered_dir is None: continue - for host_name in selected_hosts(inventory["services"][service_name], args.hosts): - errors.extend(validate_rendered_config(hyapp_root, service_name, host_name, rendered_dir)) + for host_name in selected_hosts(service, args.hosts): + errors.extend(validate_rendered_config(hyapp_root, service_name, service, host_name, rendered_dir)) if errors: print(json.dumps({"ok": False, "errors": errors}, ensure_ascii=False, indent=2), file=sys.stderr) return 1 diff --git a/src/pages/cdn-refresh/CdnRefreshPage.tsx b/src/pages/cdn-refresh/CdnRefreshPage.tsx index 28d01b2..4fff8ab 100644 --- a/src/pages/cdn-refresh/CdnRefreshPage.tsx +++ b/src/pages/cdn-refresh/CdnRefreshPage.tsx @@ -7,7 +7,7 @@ import { Button } from "../../shared/ui/Button"; import { StatusBadge, type StatusBadgeStatus } from "../../shared/ui/StatusBadge"; import styles from "./CdnRefreshPage.module.css"; -const defaultUrlText = "https://h5.global-interaction.com/"; +const defaultUrlText = "https://vivagames.global-interaction.com/"; function parseUrls(text: string) { return Array.from( @@ -148,7 +148,7 @@ export function CdnRefreshPage() {
EdgeOne - h5.global-interaction.com + h5.global-interaction.com, vivagames.global-interaction.com, asset.global-interaction.com