diff --git a/.github/workflows/bundle-deploy-eas-update.yml b/.github/workflows/bundle-deploy-eas-update.yml index aceac714c9..26581e597c 100644 --- a/.github/workflows/bundle-deploy-eas-update.yml +++ b/.github/workflows/bundle-deploy-eas-update.yml @@ -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 diff --git a/docs/deploy-ota.md b/docs/deploy-ota.md index 83323859e5..d582402672 100644 --- a/docs/deploy-ota.md +++ b/docs/deploy-ota.md @@ -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 don’t 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) diff --git a/scripts/useBuildNumberEnv.sh b/scripts/useBuildNumberEnv.sh index b2cbabcd55..ee8872cad9 100755 --- a/scripts/useBuildNumberEnv.sh +++ b/scripts/useBuildNumberEnv.sh @@ -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 "$@"