Enter build numbers manually for production OTA deploys (#11289)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-07-29 14:48:42 +03:00
committed by GitHub
parent 27e4f84f3f
commit b57827f23f
3 changed files with 60 additions and 55 deletions
+32 -3
View File
@@ -17,6 +17,14 @@ on:
type: string
description: Runtime version (in x.x.x format) that this update is for
required: true
iosBuildNumber:
type: string
description: iOS build number of the native build this update targets
(required for production)
androidVersionCode:
type: string
description: Android version code of the native build this update
targets (required for production)
# Deploys happen via EAS using EXPO_TOKEN; the GITHUB_TOKEN only checks out code
permissions:
@@ -61,9 +69,22 @@ jobs:
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
if: ${{ inputs.runtimeVersion }}
run: |
if [ -z "$RUNTIME_VERSION" ]; then
[[ "$RUNTIME_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "Version is valid" || exit 1
fi
[[ "$RUNTIME_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "Version is valid" || exit 1
# Production OTAs are bound to the specific native build they target, so
# the build numbers must be entered manually rather than read from the
# global EAS counters, which advance with every testflight build and so
# point past older production releases
- name: 🧐 Validate build numbers
if: ${{ inputs.channel == 'production' }}
env:
IOS_BUILD_NUMBER: ${{ inputs.iosBuildNumber }}
ANDROID_VERSION_CODE: ${{ inputs.androidVersionCode }}
run: |
[[ "$IOS_BUILD_NUMBER" =~ ^[0-9]+$ ]] ||
(echo "A numeric iosBuildNumber is required for production updates" && exit 1)
[[ "$ANDROID_VERSION_CODE" =~ ^[0-9]+$ ]] ||
(echo "A numeric androidVersionCode is required for production updates" && exit 1)
- name: ⬇️ Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -253,6 +274,10 @@ jobs:
env:
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
CHANNEL_NAME: ${{ inputs.channel || 'testflight' }}
# When set (required for production), these take precedence over the
# global EAS counters inside the use-build-number wrapper
BSKY_IOS_BUILD_NUMBER: ${{ inputs.iosBuildNumber }}
BSKY_ANDROID_VERSION_CODE: ${{ inputs.androidVersionCode }}
- name: 📦 Package Bundle and 🚀 Deploy (legacy ota1)
if: ${{ !steps.fingerprint.outputs.includes-changes &&
@@ -262,6 +287,10 @@ jobs:
DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
CHANNEL_NAME: ${{ inputs.channel || 'testflight' }}
# When set (required for production), these take precedence over the
# global EAS counters inside the use-build-number wrapper
BSKY_IOS_BUILD_NUMBER: ${{ inputs.iosBuildNumber }}
BSKY_ANDROID_VERSION_CODE: ${{ inputs.androidVersionCode }}
buildIfNecessaryIOS:
name: Build and Submit iOS
+13 -47
View File
@@ -63,30 +63,7 @@ Run this and commit the result as the last commit on the OTA branch.
pnpm intl:release
```
### 6. Manually set build numbers
Log in to the EAS CLI with `eas login` and manually set the build numbers to the
values you found in **Step 1**.
> [!NOTE]
> If you dont already have the EAS CLI, you can install it with `pnpm add -g eas-cli`.
```sh
> npx eas build:version:set -p ios
>
> Project @blueskysocial/bluesky with bundle identifier "xyz.blueskyweb.app" is configured with buildNumber 1011.
> ✔ What version would you like to set? … 1009
>
> npx eas build:version:set -p android
>
> Project @blueskysocial/bluesky with application ID "xyz.blueskyweb.app" is configured with versionCode 641.
> ✔ What version would you like to set? … 639
```
👉 **Save the previous values,** in this case `1011` and `641`, so you can reset
them after the OTA completes.
### 7. Run the GitHub actions
### 6. Run the GitHub actions
You'll need to run two separate actions: one to deploy the iOS/Android OTA
itself, and one to build the web Docker container.
@@ -96,14 +73,20 @@ and run the action.
| Steps | |
| ----- | --- |
| Select your OTA branch `1.x.0-ota-x`, select `production` in the dropdown, enter the git tag of the latest release `1.x.0`, and click "Run workflow" | ![workflow](./img/ota_action.png) |
| Select your OTA branch `1.x.0-ota-x`, select `production` in the dropdown, enter the git tag of the latest release `1.x.0`, enter the iOS build number and Android version code you found in **Step 1**, and click "Run workflow" | ![workflow](./img/ota_action.png) |
> [!NOTE]
> Production OTAs are bound to the specific native build they target, so the
> workflow requires the build numbers to be entered manually. There is no need
> to change the global EAS build counters (and doing so is no longer necessary
> for OTAs - they are only used when producing new native builds).
> [!NOTE]
> If you do enter an incorrect version here, the deployment will either:
> - Fail, because the action cannot find a commit with your misentered version
> - Succeed, but with no users receiving the update. This is because the version
> you entered will not properly correlate to a _build number_ as well, so no
> clients in the wild will be able to receive the update.
> - Succeed, but with no users receiving the update. This is because the
> version and build numbers you entered will not match any clients in the
> wild, so none will be able to receive the update.
**For web,** head to [Actions >
build-and-push-bskyweb-aws](https://github.com/bluesky-social/social-app/actions/workflows/build-and-push-bskyweb-aws.yaml)
@@ -113,13 +96,13 @@ and run the action.
| ----- | --- |
| Select your OTA branch `1.x.0-ota-x` and click "Run workflow" | ![workflow](./img/web_action.png) |
### 8. Deploy web
### 7. Deploy web
Once the web Docker container build finishes, go to your `1.x.0-ota-x` branch,
copy the most recent commit hash. Post this hash in `#ops-deploys` and request
someone with web deploy access deploy the built container.
### 9. Confirm successful deployment
### 8. Confirm successful deployment
In about five minutes, the new deployment should be deployed and devices will
begin downloading and installing in the background.
@@ -130,23 +113,6 @@ build from your device and re-install from the App Store. Then, you'll need to:
- Quit and reopen the app
- Check the `Settings > About` page and confirm the hash matches the most recent hash on your OTA branch
### 10. Reset build numbers
Grab the build numbers you saved in **Step 5** and reverse the EAS CLI commands
to reset the build numbers.
```sh
> npx eas build:version:set -p ios
>
> Project @blueskysocial/bluesky with bundle identifier "xyz.blueskyweb.app" is configured with buildNumber 1009.
> ✔ What version would you like to set? … 1011
>
> npx eas build:version:set -p android
>
> Project @blueskysocial/bluesky with application ID "xyz.blueskyweb.app" is configured with versionCode 639.
> ✔ What version would you like to set? … 641
```
## Overview diagram
![OTA Deployment](./img/ota-flow.png)
+15 -5
View File
@@ -3,9 +3,19 @@ set -o errexit
set -o pipefail
set -o nounset
outputIos=$(eas build:version:get -p ios)
outputAndroid=$(eas build:version:get -p android)
BSKY_IOS_BUILD_NUMBER=${outputIos#*buildNumber - }
BSKY_ANDROID_VERSION_CODE=${outputAndroid#*versionCode - }
# Build numbers already present in the environment take precedence over the
# global EAS counters. Production OTA deploys rely on this to target the
# specific native build they are for, since the counters advance with every
# testflight build.
if [ -z "${BSKY_IOS_BUILD_NUMBER:-}" ]; then
outputIos=$(eas build:version:get -p ios)
BSKY_IOS_BUILD_NUMBER=${outputIos#*buildNumber - }
fi
bash -c "BSKY_IOS_BUILD_NUMBER=$BSKY_IOS_BUILD_NUMBER BSKY_ANDROID_VERSION_CODE=$BSKY_ANDROID_VERSION_CODE $*"
if [ -z "${BSKY_ANDROID_VERSION_CODE:-}" ]; then
outputAndroid=$(eas build:version:get -p android)
BSKY_ANDROID_VERSION_CODE=${outputAndroid#*versionCode - }
fi
export BSKY_IOS_BUILD_NUMBER BSKY_ANDROID_VERSION_CODE
exec "$@"