Skip to content

Commit e3880f1

Browse files
authored
fix(android-helper): build with the pinned build-tools version, fail on CI when unset (#2568)
build-android-helper.sh compiled with whichever build-tools directory was newest on the image while every lane that builds a helper installs exactly build-tools;36.0.0. That selection feeds d8 and aapt2, so a newer package on the runner changed the helper's bytecode and resources rather than just its packaging, and nothing said so. The script now takes the version as an input, its last positional or AGENT_DEVICE_ANDROID_BUILD_TOOLS, resolves it under $SDK_ROOT/build-tools, and checks the four tools the build actually runs instead of aapt2 alone. An unpinned build is a hard failure on CI; locally the newest-installed fallback stays and is announced on stderr. Each lane that builds a helper declares the version it installs and interpolates that same value into its sdkmanager line and the build environment, so an install and a build inside one lane cannot drift. setup-android-replay-host exports it to the packaging gate and names it in both helper cache keys, which are keyed on APK bytes; size.yml and release-android-snapshot-helper.yml declare it at job level. The fixture-repack cluster keeps its own pin: a different command family that ships no helper APK. Closes #2527
1 parent ab3d11e commit e3880f1

7 files changed

Lines changed: 73 additions & 14 deletions

File tree

‎.github/actions/setup-android-replay-host/action.yml‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ runs:
3939
echo "value=${{ hashFiles('android/snapshot-helper/AndroidManifest.xml', 'android/snapshot-helper/debug.keystore', 'android/snapshot-helper/src/**', 'android/ime-helper/AndroidManifest.xml', 'android/ime-helper/res/**', 'android/ime-helper/src/**', 'scripts/build-android-helper.sh', 'scripts/package-android-helper.sh', '.github/actions/setup-android-replay-host/action.yml') }}" >> "$GITHUB_OUTPUT"
4040
shell: bash
4141

42+
# The helper build refuses to guess its build-tools version on CI, and that version decides
43+
# the APK bytes, so both cache keys name it as well.
44+
- name: Declare the pinned Android build tools
45+
if: inputs.package-helpers == 'true'
46+
id: android-build-tools
47+
run: |
48+
BUILD_TOOLS_VERSION=36.0.0
49+
echo "AGENT_DEVICE_ANDROID_BUILD_TOOLS=$BUILD_TOOLS_VERSION" >> "$GITHUB_ENV"
50+
echo "version=$BUILD_TOOLS_VERSION" >> "$GITHUB_OUTPUT"
51+
shell: bash
52+
4253
- name: Restore packaged Android helpers
4354
if: inputs.package-helpers == 'true'
4455
id: android-helpers-cache
@@ -47,7 +58,7 @@ runs:
4758
path: |
4859
android/snapshot-helper/dist
4960
android/ime-helper/dist
50-
key: android-helpers-${{ runner.os }}-${{ runner.arch }}-api36-v${{ steps.android-helper-source.outputs.version }}-${{ steps.android-helper-source.outputs.value }}
61+
key: android-helpers-${{ runner.os }}-${{ runner.arch }}-api36-bt${{ steps.android-build-tools.outputs.version }}-v${{ steps.android-helper-source.outputs.version }}-${{ steps.android-helper-source.outputs.value }}
5162

5263
- name: Install Android helper SDK packages
5364
if: inputs.package-helpers == 'true' && steps.android-helpers-cache.outputs.cache-hit != 'true'
@@ -62,7 +73,7 @@ runs:
6273
exit 1
6374
fi
6475
yes | "$SDKMANAGER" --licenses >/dev/null || true
65-
"$SDKMANAGER" "platforms;android-36" "build-tools;36.0.0"
76+
"$SDKMANAGER" "platforms;android-36" "build-tools;$AGENT_DEVICE_ANDROID_BUILD_TOOLS"
6677
shell: bash
6778

6879
- name: Package npm-bundled Android helpers
@@ -86,4 +97,4 @@ runs:
8697
path: |
8798
android/snapshot-helper/dist
8899
android/ime-helper/dist
89-
key: android-helpers-${{ runner.os }}-${{ runner.arch }}-api36-v${{ steps.android-helper-source.outputs.version }}-${{ steps.android-helper-source.outputs.value }}
100+
key: android-helpers-${{ runner.os }}-${{ runner.arch }}-api36-bt${{ steps.android-build-tools.outputs.version }}-v${{ steps.android-helper-source.outputs.version }}-${{ steps.android-helper-source.outputs.value }}

‎.github/workflows/release-android-snapshot-helper.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ jobs:
2323
name: Publish Android Snapshot Helper
2424
runs-on: ubuntu-latest
2525
timeout-minutes: 30
26+
env:
27+
# The helper build refuses to guess its build-tools version on CI.
28+
AGENT_DEVICE_ANDROID_BUILD_TOOLS: 36.0.0
2629
steps:
2730
- name: Checkout
2831
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -46,7 +49,7 @@ jobs:
4649
exit 1
4750
fi
4851
yes | "$SDKMANAGER" --licenses >/dev/null
49-
"$SDKMANAGER" "platforms;android-36" "build-tools;36.0.0"
52+
"$SDKMANAGER" "platforms;android-36" "build-tools;$AGENT_DEVICE_ANDROID_BUILD_TOOLS"
5053
5154
- name: Check Java toolchain
5255
run: |

‎.github/workflows/size.yml‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ jobs:
3131
if: github.event.pull_request.head.repo.full_name == github.repository
3232
runs-on: ubuntu-latest
3333
timeout-minutes: 10
34+
env:
35+
# The helper build refuses to guess its build-tools version on CI.
36+
AGENT_DEVICE_ANDROID_BUILD_TOOLS: 36.0.0
3437
steps:
3538
- name: Checkout
3639
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -58,7 +61,7 @@ jobs:
5861
exit 1
5962
fi
6063
yes | "$SDKMANAGER" --licenses >/dev/null || true
61-
"$SDKMANAGER" "platforms;android-36" "build-tools;36.0.0"
64+
"$SDKMANAGER" "platforms;android-36" "build-tools;$AGENT_DEVICE_ANDROID_BUILD_TOOLS"
6265
6366
# dist is fully determined by the base commit, so reuse it across PR runs
6467
# against the same base. Startup medians are still measured fresh on this

‎CONTRIBUTING.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ packages the Apple runner source, and rebuilds both Android helper APKs. Any fai
7070
packaging. It deliberately does not stop the worktree's development daemon; use `pnpm rebuild:cli`
7171
when a running daemon needs to pick up a new TypeScript build.
7272

73+
That Android leg needs `AGENT_DEVICE_ANDROID_BUILD_TOOLS` naming the build-tools version to compile
74+
with. An unpinned build takes the newest version installed on the machine, which CI refuses to do,
75+
so name the version the CI lanes install and the published helper matches the CI-built one.
76+
7377
`pnpm package:npm` is a release guard, not a routine development command. Use the specific commands
7478
above while iterating.
7579

‎android/ime-helper/README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ VERSION="$(node -p 'require("./package.json").version')"
2424
AGENT_DEVICE_ANDROID_HELPER=ime sh ./scripts/build-android-helper.sh "$VERSION" .tmp/android-ime-helper
2525
```
2626

27+
The shared script needs its build-tools version named by `AGENT_DEVICE_ANDROID_BUILD_TOOLS`; see
28+
the [snapshot helper's Build section](../snapshot-helper/README.md#build) for the full rule.
29+
2730
## Run
2831

2932
```sh

‎android/snapshot-helper/README.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ AGENT_DEVICE_ANDROID_HELPER=snapshot sh ./scripts/build-android-helper.sh "$VERS
1919
```
2020

2121
The build uses Android SDK command-line tools directly. It expects `ANDROID_HOME` or
22-
`ANDROID_SDK_ROOT` to point at an SDK with `platforms/android-36` and matching build tools.
22+
`ANDROID_SDK_ROOT` to point at an SDK with `platforms/android-36`, and it compiles with the
23+
build-tools version named by `AGENT_DEVICE_ANDROID_BUILD_TOOLS` (or the script's last positional).
24+
CI must name that version; a local build without it uses the newest version under `build-tools`
25+
and says so on stderr.
2326
`pnpm prepack` builds the npm-bundled helper into `android/snapshot-helper/dist`; npm users get
2427
that APK in the package and the first helper-backed `snapshot` installs it automatically when
2528
missing or outdated.

‎scripts/build-android-helper.sh‎

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ if [ -z "$HELPER" ]; then
77
[ "$#" -ge 1 ] && shift
88
fi
99

10-
if [ "$#" -ne 2 ]; then
11-
echo "Usage: AGENT_DEVICE_ANDROID_HELPER=<snapshot|ime> $0 <version> <output-dir>" >&2
12-
echo " or: $0 <snapshot|ime> <version> <output-dir>" >&2
10+
if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
11+
echo "Usage: AGENT_DEVICE_ANDROID_HELPER=<snapshot|ime> $0 <version> <output-dir> [build-tools-version]" >&2
12+
echo " or: $0 <snapshot|ime> <version> <output-dir> [build-tools-version]" >&2
13+
echo "The version also comes from AGENT_DEVICE_ANDROID_BUILD_TOOLS." >&2
1314
exit 1
1415
fi
1516

1617
VERSION="$1"
1718
OUTPUT_DIR="$2"
19+
BUILD_TOOLS_VERSION="${3:-${AGENT_DEVICE_ANDROID_BUILD_TOOLS:-}}"
1820
PROJECT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
1921
MIN_SDK=23
2022
TARGET_SDK=36
@@ -56,14 +58,44 @@ if [ ! -f "$ANDROID_JAR" ]; then
5658
exit 1
5759
fi
5860

59-
BUILD_TOOLS_DIR="$(
60-
find "$SDK_ROOT/build-tools" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sort -V | tail -n 1
61-
)"
62-
if [ -z "$BUILD_TOOLS_DIR" ] || [ ! -x "$BUILD_TOOLS_DIR/aapt2" ]; then
63-
echo "Missing Android build tools under $SDK_ROOT/build-tools" >&2
61+
# d8 and aapt2 come from build-tools, so the version decides the compiled bytecode and resources,
62+
# not only packaging. CI names the version it installed; only a local build may take the newest.
63+
if [ -z "$BUILD_TOOLS_VERSION" ]; then
64+
if [ "${CI:-}" = "true" ]; then
65+
echo "AGENT_DEVICE_ANDROID_BUILD_TOOLS must name a build-tools version under $SDK_ROOT/build-tools" >&2
66+
exit 1
67+
fi
68+
NEWEST_BUILD_TOOLS_DIR="$(
69+
find "$SDK_ROOT/build-tools" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sort -V | tail -n 1
70+
)"
71+
if [ -z "$NEWEST_BUILD_TOOLS_DIR" ]; then
72+
echo "No Android build tools installed under $SDK_ROOT/build-tools" >&2
73+
exit 1
74+
fi
75+
BUILD_TOOLS_VERSION="${NEWEST_BUILD_TOOLS_DIR##*/}"
76+
echo "No build-tools version requested; newest installed is $BUILD_TOOLS_VERSION" >&2
77+
fi
78+
79+
case "$BUILD_TOOLS_VERSION" in
80+
*/* | *[[:space:]]*)
81+
echo "Not an Android build-tools version: '$BUILD_TOOLS_VERSION'" >&2
82+
exit 1
83+
;;
84+
esac
85+
86+
BUILD_TOOLS_DIR="$SDK_ROOT/build-tools/$BUILD_TOOLS_VERSION"
87+
if [ ! -d "$BUILD_TOOLS_DIR" ]; then
88+
echo "No Android build tools $BUILD_TOOLS_VERSION under $SDK_ROOT/build-tools" >&2
6489
exit 1
6590
fi
6691

92+
for BUILD_TOOL in aapt2 d8 zipalign apksigner; do
93+
if [ ! -x "$BUILD_TOOLS_DIR/$BUILD_TOOL" ]; then
94+
echo "Incomplete Android build tools: no $BUILD_TOOL in $BUILD_TOOLS_DIR" >&2
95+
exit 1
96+
fi
97+
done
98+
6799
VERSION_CODE="$(
68100
printf '%s\n' "$VERSION" | awk -F. '
69101
/^[0-9]+[.][0-9]+[.][0-9]+$/ {

0 commit comments

Comments
 (0)