Files
bsky-social-app/scripts/bundleUpdate.sh
T
Austin McKinley 020a85f029 Publish one bundle version to both OTA origins, not two
bundleUpdate.sh and denisPublish.sh each called `date +%s`, so a single dual-write
gave the same bytes two different bundle versions -- observed 1785102575 (denis)
and 1785102614 (ota1), 39 seconds apart, for commit b662cd43b.

That is not cosmetic. The bundle version is a path segment in every asset URL the
manifest hands the client:

  https://updates.bsky.app/file/1.130.0/<bundle-version>/bundles/<hash>

Both origins mint those URLs against updates.bsky.app, which resolves to whichever
origin Bunny currently points at. So each origin was serving a manifest whose
assets only IT has. A manifest fetched from one origin and assets fetched from the
other 404s -- which is exactly what a rollback of the Bunny origin does if it lands
between a client's manifest fetch and its asset fetch. The dual-write existed to
make rollback safe and was quietly making it unsafe.

Pin the version once in the job and let both scripts inherit it. Both fall back to
`date +%s` when BUNDLE_VERSION is unset, so the single-publisher callers are
unchanged: pull-request-commit.yml (denis only) and `pnpm make-deploy-bundle`.
The fallback uses `:-` rather than `-`, so an empty value also falls back --
`denis publish` rejects a non-numeric bundle version, so an empty one must never
propagate.

This does not make the two manifests byte-identical. createdAt still differs
(21:49:35Z vs 21:50:18Z for the commit above) because ota1's legacy uploader
stamps it server-side on receipt; the client posts a tarball, not a timestamp, so
nothing here can align it. That residual is inert in a way the bundle version was
not: the manifest id is content-addressed on metadata.json and is identical across
origins, so manifestHandler's `currentUpdateID == entry.Manifest.ID` check makes a
client that switches origins see the same update rather than a newer one. It goes
away with the dual-write in Phase 5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 16:30:57 -07:00

53 lines
1.9 KiB
Bash

#!/bin/bash
set -o errexit
set -o pipefail
set -o nounset
rm -rf bundleTempDir
rm -rf bundle.tar.gz
echo "Creating tarball..."
node scripts/bundleUpdate.js
if [ -z "$RUNTIME_VERSION" ]; then
RUNTIME_VERSION=$(cat package.json | jq '.version' -r)
fi
cd bundleTempDir || exit
# Shared with denisPublish.sh when both run in one job -- see the note there.
# Both origins must receive the same bundle version for the same bytes, because
# the version is part of the asset URL path.
BUNDLE_VERSION="${BUNDLE_VERSION:-$(date +%s)}"
# This MUST address ota1's own origin hostname, never updates.bsky.app.
#
# Since the 2026-07-26 cutover updates.bsky.app resolves to denis on EKS, which
# deliberately has no /v1/upload route -- publishing there is out-of-band via
# `denis publish` (see denisPublish.sh). Posting to the CDN hostname therefore
# returns 404, which is what broke this step the first time it ran after the
# flip. The dual-write was never independent of the cutover precisely because it
# addressed the hostname being cut over.
#
# This upload exists only to keep ota1 carrying current bundles so a rollback of
# the Bunny origin remains useful. It goes away with this whole script when ota1
# is decommissioned (Phase 5).
OTA1_ORIGIN="${OTA1_ORIGIN:-https://ota1.us-east.updates.bsky.network}"
DEPLOYMENT_URL="$OTA1_ORIGIN/v1/upload?runtime-version=$RUNTIME_VERSION&bundle-version=$BUNDLE_VERSION&channel=$CHANNEL_NAME&ios-build-number=$BSKY_IOS_BUILD_NUMBER&android-build-number=$BSKY_ANDROID_VERSION_CODE"
tar czvf bundle.tar.gz ./*
echo "Deploying to $DEPLOYMENT_URL..."
echo " runtime-version: $RUNTIME_VERSION"
echo " bundle-version: $BUNDLE_VERSION"
echo " channel: $CHANNEL_NAME"
echo " ios-build-number: $BSKY_IOS_BUILD_NUMBER"
echo " android-build-number: $BSKY_ANDROID_VERSION_CODE"
curl --fail-with-body -o - --form "bundle=@./bundle.tar.gz" --user "bsky:$DENIS_API_KEY" --basic "$DEPLOYMENT_URL"
cd ..
rm -rf bundleTempDir
rm -rf bundle.tar.gz