H5 离线包 & 外部落地页 · 发布流程

仓库 beex-app-h5(Nuxt)· 后端登记/发布在 beex-service + beex-admin-service · 印尼 ID

一次提交 · 三个制品

同一个 Git commit、同一条流水线,产出三个独立发布、但同源的制品。三者是同一份 H5 代码的不同交付形态。

制品面向触达方式发布节奏
INTERNAL 离线包App 内 H5(内部包)仅 Native 版本 88.88.88登记 DRAFT → 扫码验收 → 发布(人工)
RELEASE 离线包App 内 H5(线上包)其余所有 Native 版本登记 DRAFT → 灰度 → 发布(人工)
PUBLIC_LANDING 落地页浏览器(无 App 时)WA 裂变/分享打开的脱离式落地页先发测试环境验收 → 手动发线上
流水线 .yunxiao/h5-id-offline-package-channels.yml(pipeline 4987658)→ npm run deploy:oss-cdn:channelsscripts/deploy-h5-package-channels.sh:构建 INTERNAL + RELEASE 离线包(登记为 DRAFT),并把落地页发到测试环境

制品与去向对照

制品OSS 桶对象 / 域名连接后端是否含调试/内部配置
INTERNALbeex-id-test-h5packages/internal/<ver>/beex-h5.zip内嵌 生产 + 测试 配置是(88 内部包,含文案审校/调试)
RELEASEbeex-id-prod-h5packages/release/<ver>/beex-h5.zip仅 生产配置
落地页 · testbeex-id-test-h5h5-id-test.beexofficial.com 网站根api-id-test
落地页 · prodbeex-id-prod-h5h5-id.beexofficial.com 网站根api-id
注意去向重叠:离线包 zip 和落地页网站根都放在同一批桶里,但路径/角色完全不同——packages/…/beex-h5.zip 是 App 离线包;桶根的 index.html + /_nuxt 是浏览器落地页。发离线包不动落地页,发落地页不动离线包。

离线包:构建 + 登记(DRAFT)

流水线按渠道各构建一次并上传 zip,然后调用 admin 登记接口。登记接口只允许创建 DRAFT,不能直接发布。

  • 渠道选择由 Native 版本决定,不是业务环境:88.88.88 → INTERNAL(envCode=id-test,min/max native 都锁 88.88.88);其余版本 → RELEASE(envCode=id)。
  • 每个包的 manifest.jsonpackageChannel(INTERNAL / RELEASE),供 App 侧强校验。
  • 登记:POST /api/v1/admin/h5-packages(INTERNAL 发到 admin-api-id-test,RELEASE 发到 admin-api-id),服务端返回 DRAFT。
为什么不能"流水线一键发布":登记接口显式拒绝 PUBLISHED——"H5 包登记接口只允许创建 DRAFT,测试、灰度和发布必须使用对应的发布动作"。发布是刻意分离的人工门禁(见下)。

离线包:发布门禁(灰度 / 验收 → 上线)

admin 后台(beex-admin-page 的 H5 发布页)由管理员操作,需飞书 OAuth 管理员会话(登记走 token 旁路,发布/灰度动作不行)。

生产包(RELEASE,id)DRAFT 灰度 gray-releaseGRAY 发布 publishPUBLISHED

测试包(INTERNAL,id-test)DRAFT 扫码验收(TEST_PASSED 发布 publish
  • 接口:POST /api/v1/admin/h5-packages/{id}/gray-releasePOST /api/v1/admin/h5-packages/{id}/publishpublish 会强校验前置状态(非 GRAY / TEST_PASSED 直接报错)。
  • verify 门禁:以 PUBLISHED 发布时,流水线 verify-published-channels.sh 会拉两个渠道的 /latest 包、校验其 manifest.packageChannel,缺失/不匹配即阻断发布
  • 发布后 rolloutPercent(默认 100)决定放量比例;进入 /latest 后 App 下次检查即可获取。
只有登记(DRAFT)不等于上线。真正让用户拿到,必须走上面的灰度/验收 + 发布动作。

离线包:App 侧选渠道与校验

  • App 用 GET /api/v1/app/h5-package/latest?countryCode&envCode&platform&nativeVersion&buildNumber&deviceId 拉最新包;envCode 由 App 按 Native 版本推导(88.88.88 → id-test,其余 → id)。
  • App 严格校验下载包 manifest.packageChannel 是否与期望渠道一致;packageChannel 的历史包按仓库分区兼容放行(不再硬拒收),有明确渠道但不匹配则拒收。
  • 校验失败(下载/渠道不符)→ 回退内置包,不影响启动。

落地页:是什么

三个页面,同一个 Nuxt SPA 里的 hash 路由(PUBLIC_LANDING 构建只保留这三条路由、剥掉完整 App 页面):

页面路由场景
邀请/#/invite/<code>邀请裂变落地
商品分享/#/share/<code>商品分享落地
蜜源圈/#/honey/<code>内容/爆品分享落地
  • 用 RELEASE 渠道构建(固定正式 API 口径、无调试入口/内部配置)+ H5_PUBLIC_LANDING=true(Web 绝对资源路径 /_nuxt/、hash 路由、只三页)。
  • 直接把构建产物传到 OSS 网站根 + 刷 CDN,没有 DRAFT/发布状态,传即生效(与离线包的门禁不同)。

落地页:test → prod 门禁

先到测试环境验收通过,才能发布到线上环境。

流水线每次部署 落地页只发 测试环境h5-id-test.beexofficial.com,连 api-id-test

验收通过后(人工一步) bash scripts/publish-public-landing.sh prod 线上h5-id.beexofficial.com,连 api-id
  • 脚本 scripts/publish-public-landing.sh <test|prod>:按目标环境覆盖后端 API 与桶/CDN 后构建并上传。
  • 流水线里 deploy_public_landing 默认 H5_PUBLIC_LANDING_ENV=test——所以常规部署不会碰线上落地页
  • nuxt.configH5_PUBLIC_LANDING_API_BASE / H5_PUBLIC_LANDING_SITE_URL 覆盖「生产环境」的 API/站点,让 apiBaseenvironmentConfigs 都指向所选后端。
已验证:流水线部署后测试站 h5-id-test 更新且连 api-id-test;线上站 h5-id 保持不变——门禁生效。

落地页:WhatsApp 分享承接(OG 预览)

分享到 WhatsApp 的应是 www.beexofficial.com 下的服务端短链,由服务端渲染 Open Graph(商品图、标题)后再 302 跳到 H5 落地页。

WhatsApp 消息里的链接 www.beexofficial.com/id/s/<code>(或 /invite/…、蜜源圈) 服务端渲染 OG + 302 h5-id.beexofficial.com/#/… 落地页
  • 服务端承接已在 beex-serviceAffiliateSharePageController/id/s/{code})、InviteShareService/invite/{code})、HoneyFeedPageController
不要直接分享带 # 的 H5 地址(如 h5-id.beexofficial.com/#/share/CODE):# 后的路由服务端读不到,WhatsApp 抓不到具体内容 → 预览是空的、没有商品图/标题。

环境 / 桶 / CDN 映射(ID)

用途OSS 桶域名后端 APIAdmin API(登记)
离线包 INTERNALbeex-id-test-h5h5-id-test.beexofficial.comadmin-api-id-test
离线包 RELEASEbeex-id-prod-h5h5-id.beexofficial.comadmin-api-id
落地页 testbeex-id-test-h5h5-id-test.beexofficial.comapi-id-test
落地页 prodbeex-id-prod-h5h5-id.beexofficial.comapi-id

命令速查

构建 + 登记两个离线包(DRAFT)+ 落地页发测试

# 触发云效流水线(自动 push 当前 commit)
bash scripts/run-yunxiao-pipeline.sh --push
# 产出:INTERNAL/RELEASE 离线包登记为 DRAFT;落地页发到 h5-id-test(测试)

落地页:验收通过后发线上

bash scripts/publish-public-landing.sh prod   # 发 h5-id.beexofficial.com(连 api-id)
bash scripts/publish-public-landing.sh test   # 仅重发测试站(默认)

离线包:正式发布(admin 后台人工)

#(在 beex-admin-page H5 发布页,需飞书管理员会话)
# 生产包:DRAFT → 灰度(gray-release) → 发布(publish)
# 测试包:DRAFT → 扫码验收(TEST_PASSED) → 发布(publish)

发布前自检两个渠道 latest 是否带 packageChannel

bash scripts/verify-published-channels.sh https://api-id.beexofficial.com ID

常见坑

  • DRAFT ≠ 上线。离线包跑完流水线只是登记 DRAFT,必须再走灰度/验收 + 发布动作,用户才拿得到。
  • 落地页传即生效、无灰度。所以引入了 test → prod 门禁:常规流水线只发测试站,线上要单独 publish-public-landing.sh prod。历史上落地页曾因"流水线只发离线包、跳过网站根"而长期停在旧版。
  • packageChannel 的历史包。升级后的 App 对包做严格渠道校验;历史遗留包(manifest 无 packageChannel)需用 deploy-h5-package-channels.sh 重新构建发布带上渠道标记。
  • 分享一定走 www 服务端短链,别用 #/ 直连,否则 WhatsApp 无 OG 预览。
  • 离线包 vs 网站根同桶不同路径。别把 packages/…/beex-h5.zip(App 包)和桶根 index.html(落地页)搞混。