Skip to content

Commit ac25d78

Browse files
committed
fix(ci): locate keytool without relying on PATH, and reject WSL
Running the script from PowerShell failed with "keytool not found" even after adding Android Studio's jbr/bin to $env:PATH. Two causes. On Windows, `bash` invoked from PowerShell is frequently WSL's bash rather than Git Bash, and the two disagree about everything: WSL sees the system drive as /mnt/c, Git Bash as /c, and a Windows PATH entry that one resolves the other does not. The script now finds its own tools instead of trusting PATH — checking PATH, then JAVA_HOME (normalising a C:\ style value into the shell's own form), then the usual Android Studio and JDK locations, under each of the /c, /mnt/c and /cygdrive/c prefixes. Verified by resolving both keytool and gh with PATH stripped to /usr/bin:/bin. WSL is now refused outright rather than half-supported: it can reach a Windows keytool.exe through interop but then passes it Linux paths it cannot open, so the keystore would land somewhere unexpected. The error prints the Git Bash invocation to use instead. KEYTOOL=... can still override the search if a key lives somewhere unusual.
1 parent 627184f commit ac25d78

1 file changed

Lines changed: 76 additions & 11 deletions

File tree

scripts/setup-signing.sh

Lines changed: 76 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,74 @@ ALIAS="${ALIAS:-dash}"
1717
# Deliberately outside the repository so the key can never be committed.
1818
KEYSTORE="${KEYSTORE:-$HOME/ilink-release.jks}"
1919

20-
command -v keytool >/dev/null || { echo "keytool not found — install a JDK or add Android Studio's jbr/bin to PATH" >&2; exit 1; }
21-
command -v gh >/dev/null || { echo "gh not found — install the GitHub CLI" >&2; exit 1; }
22-
gh auth status >/dev/null 2>&1 || { echo "gh is not authenticated — run: gh auth login" >&2; exit 1; }
20+
# On Windows, `bash` launched from PowerShell is often WSL rather than Git
21+
# Bash. WSL can *find* a Windows keytool.exe through interop but then hands it
22+
# Linux paths (/home/... , /tmp/...) that it cannot open, so the keystore would
23+
# be written somewhere unexpected or not at all. Fail early with the fix rather
24+
# than half-working.
25+
if grep -qiE 'microsoft|wsl' /proc/version 2>/dev/null; then
26+
cat >&2 <<'WSL'
27+
This is running under WSL, where Windows keytool cannot use Linux paths.
28+
29+
Run it in Git Bash instead — from PowerShell:
30+
31+
& "C:\Program Files\Git\bin\bash.exe" scripts/setup-signing.sh
32+
33+
(or open "Git Bash" from the Start menu, cd to the repo, and run
34+
bash scripts/setup-signing.sh)
35+
WSL
36+
exit 1
37+
fi
38+
39+
# Resolve tools without depending on PATH. Windows shells disagree about it:
40+
# Git Bash sees C:\ as /c, WSL as /mnt/c, and a `bash` launched from
41+
# PowerShell may be either — so a PATH that works in one is empty in the other.
42+
find_tool() {
43+
local name="$1"; shift
44+
local found
45+
if found=$(command -v "$name" 2>/dev/null); then printf '%s' "$found"; return 0; fi
46+
local prefix
47+
for prefix in "" /c /mnt/c /cygdrive/c; do
48+
local candidate
49+
for candidate in "$@"; do
50+
if [ -x "${prefix}${candidate}" ]; then printf '%s' "${prefix}${candidate}"; return 0; fi
51+
if [ -x "${prefix}${candidate}.exe" ]; then printf '%s' "${prefix}${candidate}.exe"; return 0; fi
52+
done
53+
done
54+
return 1
55+
}
56+
57+
# JAVA_HOME may be a Windows path (C:\...) that this shell cannot use directly,
58+
# so normalise it into the same /c or /mnt/c form as everything else.
59+
java_home_bin() {
60+
[ -n "${JAVA_HOME:-}" ] || return 0
61+
printf '%s' "$JAVA_HOME" \
62+
| sed -e 's|\\|/|g' -e 's|^\([A-Za-z]\):|/\L\1|' \
63+
| sed -e 's|$|/bin/keytool|'
64+
}
65+
66+
KEYTOOL=$(find_tool keytool \
67+
"$(java_home_bin)" \
68+
"/Program Files/Android/Android Studio/jbr/bin/keytool" \
69+
"/Program Files/Android/Android Studio1/jbr/bin/keytool" \
70+
"/Program Files/Java/jdk-21/bin/keytool" \
71+
"/Program Files/Java/jdk-17/bin/keytool" \
72+
"/Program Files/Eclipse Adoptium/jdk-17/bin/keytool" \
73+
|| true)
74+
[ -n "$KEYTOOL" ] || {
75+
echo "keytool not found." >&2
76+
echo "Tried PATH, JAVA_HOME, and the usual Android Studio / JDK locations." >&2
77+
echo "Set it explicitly, e.g.:" >&2
78+
echo " KEYTOOL='/c/Program Files/Android/Android Studio/jbr/bin/keytool' bash scripts/setup-signing.sh" >&2
79+
exit 1
80+
}
81+
82+
GH=$(find_tool gh "/Program Files/GitHub CLI/gh" "/Program Files (x86)/GitHub CLI/gh" || true)
83+
[ -n "$GH" ] || { echo "gh not found — install the GitHub CLI" >&2; exit 1; }
84+
"$GH" auth status >/dev/null 2>&1 || { echo "gh is not authenticated — run: gh auth login" >&2; exit 1; }
85+
86+
echo "keytool : $KEYTOOL"
87+
echo "gh : $GH"
2388

2489
echo "Repository : $REPO"
2590
echo "Keystore : $KEYSTORE"
@@ -42,7 +107,7 @@ else
42107
# One password for both is normal for a release keystore and keeps Gradle simple.
43108
KEY_PW="$STORE_PW"
44109

45-
keytool -genkeypair -v \
110+
"$KEYTOOL" -genkeypair -v \
46111
-keystore "$KEYSTORE" \
47112
-alias "$ALIAS" \
48113
-keyalg RSA -keysize 4096 -validity 10000 \
@@ -54,7 +119,7 @@ else
54119
fi
55120
export STORE_PW KEY_PW
56121

57-
SIGNER=$(keytool -list -v -keystore "$KEYSTORE" -alias "$ALIAS" \
122+
SIGNER=$("$KEYTOOL" -list -v -keystore "$KEYSTORE" -alias "$ALIAS" \
58123
-storepass:env STORE_PW 2>/dev/null \
59124
| awk '/SHA256:/ {gsub(":", ""); print tolower($2); exit}')
60125
printf '%s' "$SIGNER" | grep -Eq '^[0-9a-f]{64}$' || {
@@ -68,14 +133,14 @@ trap 'rm -f "$B64"' EXIT
68133

69134
echo
70135
echo "Uploading secrets to the '$REPO' prod environment..."
71-
gh secret set DASH_RELEASE_KEYSTORE_B64 --env prod --repo "$REPO" < "$B64"
72-
printf '%s' "$STORE_PW" | gh secret set DASH_KEYSTORE_PASSWORD --env prod --repo "$REPO"
73-
printf '%s' "$KEY_PW" | gh secret set DASH_KEY_PASSWORD --env prod --repo "$REPO"
74-
printf '%s' "$ALIAS" | gh secret set DASH_KEY_ALIAS --env prod --repo "$REPO"
75-
printf '%s' "$SIGNER" | gh secret set DASH_EXPECTED_SIGNER_SHA --env prod --repo "$REPO"
136+
"$GH" secret set DASH_RELEASE_KEYSTORE_B64 --env prod --repo "$REPO" < "$B64"
137+
printf '%s' "$STORE_PW" | "$GH" secret set DASH_KEYSTORE_PASSWORD --env prod --repo "$REPO"
138+
printf '%s' "$KEY_PW" | "$GH" secret set DASH_KEY_PASSWORD --env prod --repo "$REPO"
139+
printf '%s' "$ALIAS" | "$GH" secret set DASH_KEY_ALIAS --env prod --repo "$REPO"
140+
printf '%s' "$SIGNER" | "$GH" secret set DASH_EXPECTED_SIGNER_SHA --env prod --repo "$REPO"
76141

77142
echo
78143
echo "Done. Secrets now set (names only):"
79-
gh secret list --env prod --repo "$REPO"
144+
"$GH" secret list --env prod --repo "$REPO"
80145
echo
81146
echo "Back up $KEYSTORE somewhere encrypted and off this machine before releasing."

0 commit comments

Comments
 (0)