Public Access
Take the phone's aapt2 from the SDK the job installs rather than the workload's
The android job got past restore and died in the .NET Android SDK's own tooling resolution:
warning : An error occurred trying to start process
'.../packs/Microsoft.Android.Sdk.Linux/36.1.69/tools/Linux/aapt2' … No such file or directory
error XA0111: Unsupported version of AAPT2 found at path '.../tools/Linux'
The error names the wrong problem. Nothing was found, so nothing had a version, and XA0111 points at
an Aapt2ToolPath in the project file that has never been set. The warning above it is the real message
and it is only a warning.
The pack was incomplete, and on this runner it would have stayed that way: act's host executor keeps
/usr/share/dotnet between runs, and `dotnet workload install` reads the installed-workload records and
does nothing when android is listed, whatever is on disk. So two changes, each of which stands alone.
The build and the packaging step are now given -p:Aapt2ToolPath pointing at build-tools, which this job
installs itself and can therefore vouch for. That is already the aapt2 the packaging step shells out to
for `dump badging`, so this makes one tool of what were two, and the manifest the feed publishes is now
read by the binary that wrote it. Checked rather than assumed: build-tools 36.0.0 answers aapt2 2.20 and
.NET for Android 36.1.43 builds and packages this head against it with no complaint. The version is
named once, in the step's env, because three things now depend on it agreeing with itself.
And the workload step probes for the pack file that went missing and repairs the workload when it is
absent. The probe is a witness rather than the point — the build no longer touches that binary — but a
5 MB file near the end of a 130 MB package is what a truncated extraction loses first, and r8.jar and
manifestmerger.jar are what it loses next.
This commit is contained in:
@@ -394,6 +394,10 @@ jobs:
|
||||
# versioned separately and this one is the current stable. Floating it would make the toolchain
|
||||
# a moving part of every build.
|
||||
CMDLINE_TOOLS: commandlinetools-linux-11076708_latest.zip
|
||||
# Named once here because three things now depend on it being one version: what sdkmanager
|
||||
# installs, what the build is told to use for aapt2, and what the packaging step reads the
|
||||
# versionName back with.
|
||||
BUILD_TOOLS: 36.0.0
|
||||
run: |
|
||||
set -eu
|
||||
SUDO=""
|
||||
@@ -448,22 +452,83 @@ jobs:
|
||||
# terminal. See docs/android-port.md. platform-tools comes along because aapt2 and apksigner
|
||||
# are what the packaging step actually shells out to.
|
||||
"$sdk/cmdline-tools/latest/bin/sdkmanager" \
|
||||
"platform-tools" "platforms;android-36" "build-tools;36.0.0"
|
||||
"platform-tools" "platforms;android-36" "build-tools;$BUILD_TOOLS"
|
||||
|
||||
# ============ aapt2, which the build is told to take from here and not from the workload ============
|
||||
#
|
||||
# .NET for Android ships its own aapt2 inside the workload pack, at
|
||||
# packs/Microsoft.Android.Sdk.Linux/<v>/tools/Linux/aapt2, and prefers it when Aapt2ToolPath is
|
||||
# unset. On this runner that binary could not be started at all:
|
||||
#
|
||||
# warning : An error occurred trying to start process '.../tools/Linux/aapt2' … No such file
|
||||
# error XA0111: Unsupported version of AAPT2 found at path '.../tools/Linux'
|
||||
#
|
||||
# The second line is what the build reports and it is misleading — nothing was found, so nothing
|
||||
# had a version. This runner is persistent (act's host executor, so /usr/share/dotnet survives
|
||||
# between runs), and `dotnet workload install` treats an already-listed workload as satisfied
|
||||
# whatever is actually on disk, so a pack left incomplete by an interrupted install stays
|
||||
# incomplete for every later run. That is a state no step here can detect and none can repair.
|
||||
#
|
||||
# So the build is pointed at the aapt2 from build-tools instead: Google's own, installed by the
|
||||
# line above, in a directory this job creates and can therefore vouch for. It is also already
|
||||
# the aapt2 the packaging step shells out to for `dump badging`, so this makes one tool of what
|
||||
# were two — and the manifest the feed publishes is now read by the same binary that wrote it.
|
||||
#
|
||||
# Verified rather than assumed to be usable, because the failure mode above is precisely a file
|
||||
# that exists and will not run, and because a version check here says so in one line instead of
|
||||
# as an XA0111 four minutes into a build.
|
||||
aapt2="$sdk/build-tools/$BUILD_TOOLS"
|
||||
|
||||
if ! "$aapt2/aapt2" version; then
|
||||
echo "aapt2 at $aapt2 will not run, so there is no usable one on this runner." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "AAPT2_TOOL_PATH=$aapt2" >> "$GITHUB_ENV"
|
||||
echo "Android SDK at $sdk"
|
||||
|
||||
# After the SDK, because the workload's own first-run checks look for one and are quieter when they
|
||||
# find it. --skip-sign-check is for the workload package feed, not for anything this project signs.
|
||||
#
|
||||
# The repair is here because `install` is not one. It reads the installed-workload records and does
|
||||
# nothing when android is listed, whatever is on disk — so a pack left half-extracted by an
|
||||
# interrupted run stays half-extracted forever on a runner whose filesystem persists, and every
|
||||
# later build fails on whichever file happened not to make it. This runner has already produced
|
||||
# exactly that, with a missing tools/Linux/aapt2 (see the SDK step above).
|
||||
#
|
||||
# tools/Linux/aapt2 is the probe rather than the point: the build no longer uses that binary at all.
|
||||
# It is a 5 MB file near the end of a 130 MB package, which makes it a good witness for a truncated
|
||||
# extraction — and if it is absent then r8.jar and manifestmerger.jar, which the build does need,
|
||||
# are the next things to go. Repairing costs a re-download and only happens when something is
|
||||
# already wrong; the alternative is a mystery every few months.
|
||||
- name: install the android workload
|
||||
run: dotnet workload install android --skip-sign-check
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
dotnet workload install android --skip-sign-check
|
||||
|
||||
root="$(dirname "$(readlink -f "$(command -v dotnet)")")"
|
||||
|
||||
# tools/Linux/ and not tools/, because the pack's layout is host-shaped: the Linux pack puts its
|
||||
# host binaries under a named directory and the Windows one puts aapt2.exe straight in tools/.
|
||||
# This job is linux-only, so the Linux path is the one to look for and a probe that accepted
|
||||
# either would quietly pass on a pack for the wrong host.
|
||||
if [ -d "$root/packs" ] && ! ls "$root"/packs/Microsoft.Android.Sdk.*/*/tools/Linux/aapt2 >/dev/null 2>&1; then
|
||||
echo "::warning::The android workload pack is missing files; repairing it."
|
||||
dotnet workload repair
|
||||
fi
|
||||
|
||||
- name: restore
|
||||
run: dotnet restore src/DodoSSH.Client.Android/DodoSSH.Client.Android.csproj --locked-mode
|
||||
|
||||
# Aapt2ToolPath on both this and the packaging step, not on one: it is a directory the workload
|
||||
# would otherwise pick for itself, and a build that resolved a different aapt2 than the package
|
||||
# step would be a difference nobody could see until one of them failed. See the SDK step.
|
||||
- name: build
|
||||
run: >
|
||||
dotnet build src/DodoSSH.Client.Android/DodoSSH.Client.Android.csproj
|
||||
--no-restore --configuration Release
|
||||
-p:Aapt2ToolPath="$AAPT2_TOOL_PATH"
|
||||
|
||||
# Packaging rather than only compiling, because the two failures this head is most exposed to
|
||||
# are both link-time: a native library with no android ABI, and a managed assembly that
|
||||
@@ -494,7 +559,8 @@ jobs:
|
||||
--no-restore --configuration Release \
|
||||
-t:SignAndroidPackage \
|
||||
-p:DodoChannel=nightly \
|
||||
-p:DodoNightlyVersionCode="$code"
|
||||
-p:DodoNightlyVersionCode="$code" \
|
||||
-p:Aapt2ToolPath="$AAPT2_TOOL_PATH"
|
||||
|
||||
apk="$(find src/DodoSSH.Client.Android/bin/Release -name '*-Signed.apk' | head -1)"
|
||||
if [ -z "$apk" ]; then
|
||||
@@ -505,7 +571,7 @@ jobs:
|
||||
# Read back out of the APK rather than recomputed, so what the feed advertises is what the
|
||||
# bytes say. A versionName derived a second time in shell is a second implementation of the
|
||||
# csproj's target, and the two would drift on the first change to either.
|
||||
badging="$($ANDROID_HOME/build-tools/36.0.0/aapt2 dump badging "$apk")"
|
||||
badging="$("$AAPT2_TOOL_PATH/aapt2" dump badging "$apk")"
|
||||
name="$(printf '%s' "$badging" | sed -n "s/.*versionName='\([^']*\)'.*/\1/p" | head -1)"
|
||||
|
||||
staged="$RUNNER_TEMP/android-nightly"
|
||||
|
||||
Reference in New Issue
Block a user