@@ -939,6 +939,72 @@ preview:pr-comment:
939939 - app/mobile/**/*
940940 - app/scripts/**/*
941941
942+ # Staging OTA auto-deploy. Mirrors the web staging deploy (build a static bundle,
943+ # publish to dev-assets, serve from there): bundle the staging variant, stage the
944+ # (unsigned) Expo Updates output, upload bundle+assets to the dev-assets CDN under
945+ # an immutable per-SHA prefix, and print the native_ota_bundles JSON. The staging
946+ # backend (dev-api.couchershq.org/native/ota/manifest) builds the served manifest
947+ # from that flag, with asset URLs pointing at what this job uploaded. Runs on
948+ # develop only. Production publishing goes through the tools/ ops deploy.
949+ build:mobile-ota-staging :
950+ needs : ["protos"]
951+ stage : build
952+ image : node:22
953+ inherit :
954+ default : false
955+ variables :
956+ APP_VARIANT : staging
957+ EXPO_PUBLIC_COUCHERS_ENV : preview
958+ EXPO_PUBLIC_API_BASE_URL : https://dev-api.couchershq.org
959+ EXPO_PUBLIC_WEB_BASE_URL : https://next.couchershq.org
960+ OTA_PLATFORMS : " ios android"
961+ script :
962+ - cd app/mobile
963+ - npm ci
964+ - npm run build:protos
965+ - npx expo config --type public --json > ota-expo-config.json
966+ - |
967+ for P in $OTA_PLATFORMS; do
968+ rm -rf dist
969+ npx expo export --platform "$P"
970+ RV=$(npx expo-updates fingerprint:generate --platform "$P" 2>/dev/null | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>process.stdout.write(JSON.parse(s).hash))')
971+ echo "fingerprint($P) = $RV"
972+ # The asset URLs baked into the manifest must resolve to the upload location
973+ # below; the CDN host maps <sha>--ota-staging -> the /ota-staging/<sha>/ prefix.
974+ node scripts/ota-stage.mjs --platform "$P" --runtime-version "$RV" --base-url "https://$CI_COMMIT_SHORT_SHA--ota-staging.$PREVIEW_DOMAIN" --dist dist --out ota-staging-out --expo-config ota-expo-config.json
975+ done
976+ - node scripts/ota-growthbook-flag.mjs --out ota-staging-out --platforms "$OTA_PLATFORMS" | tee ota-staging-out/native_ota_bundles.json
977+ artifacts :
978+ paths :
979+ - app/mobile/ota-staging-out/
980+ expire_in : 1 week
981+ rules :
982+ - if : ($BUILD_MOBILE == "true") && ($CI_COMMIT_BRANCH == $RELEASE_BRANCH)
983+
984+ deploy:mobile-ota-staging :
985+ needs : ["build:mobile-ota-staging"]
986+ stage : deploy
987+ image : registry.gitlab.com/gitlab-org/cloud-deploy/aws-base:latest
988+ inherit :
989+ # no docker login
990+ default : false
991+ variables :
992+ OTA_PLATFORMS : " ios android"
993+ script :
994+ - |
995+ for P in $OTA_PLATFORMS; do
996+ D="app/mobile/ota-staging-out/$P"
997+ # Only the bundle + assets go on the CDN; the manifest is served by the backend.
998+ aws s3 cp "$D/bundle.hbc" "s3://$AWS_PREVIEW_BUCKET/ota-staging/$CI_COMMIT_SHORT_SHA/$P/bundle.hbc" --content-type application/javascript
999+ if [ -d "$D/assets" ]; then
1000+ aws s3 cp "$D/assets/" "s3://$AWS_PREVIEW_BUCKET/ota-staging/$CI_COMMIT_SHORT_SHA/$P/assets/" --recursive
1001+ fi
1002+ done
1003+ - echo "Bundle + assets uploaded. Paste this into the staging GrowthBook 'native_ota_bundles' flag:"
1004+ - cat app/mobile/ota-staging-out/native_ota_bundles.json
1005+ rules :
1006+ - if : ($BUILD_MOBILE == "true") && ($CI_COMMIT_BRANCH == $RELEASE_BRANCH)
1007+
9421008preview:protos :
9431009 needs : ["protos"]
9441010 stage : preview
0 commit comments