Skip to content

Commit 80fa840

Browse files
committed
update build.yml
1 parent 030d340 commit 80fa840

1 file changed

Lines changed: 67 additions & 176 deletions

File tree

.github/workflows/build.yml

Lines changed: 67 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -36,91 +36,70 @@ jobs:
3636
build-android:
3737
runs-on: ubuntu-latest
3838
steps:
39-
- name: Checkout code
40-
uses: actions/checkout@v4
39+
# ------------------------------------------------
40+
# 0️⃣ Checkout + basic setup
41+
# ------------------------------------------------
42+
- uses: actions/checkout@v4
4143

42-
- name: Set up Node.js
43-
uses: actions/setup-node@v4
44+
- uses: actions/setup-node@v4
4445
with:
45-
node-version: '20'
46-
cache: 'npm'
46+
node-version: "20"
47+
cache: npm
4748

48-
- name: Set up JDK 17
49-
uses: actions/setup-java@v4
49+
- uses: actions/setup-java@v4
5050
with:
51-
distribution: 'temurin'
52-
java-version: '17'
51+
distribution: temurin
52+
java-version: 17
5353

54-
- name: Setup Android SDK
55-
uses: android-actions/setup-android@v3
54+
- uses: android-actions/setup-android@v3
5655

57-
- name: Install dependencies
58-
run: npm install --legacy-peer-deps
56+
# ------------------------------------------------
57+
# 1️⃣ Install npm deps (Expo pre‑build)
58+
# ------------------------------------------------
59+
- run: npm ci --legacy-peer-deps
5960

60-
- name: Expo Prebuild
61-
run: npx expo prebuild --platform android --clean
61+
- run: npx expo prebuild --platform android --clean
6262

63-
- name: Setup Gradle cache
64-
uses: gradle/actions/setup-gradle@v3
63+
# ------------------------------------------------
64+
# 2️⃣ Cache Gradle (speed‑up)
65+
# ------------------------------------------------
66+
- uses: gradle/actions/setup-gradle@v3
6567
with:
6668
gradle-home-cache-cleanup: true
6769

68-
- name: Decode Keystore
70+
# ------------------------------------------------
71+
# 3️⃣ Decode the keystore (used by Gradle for signing)
72+
# ------------------------------------------------
73+
- name: Decode keystore
6974
run: |
70-
if [ -z "${{ secrets.KEYSTORE_BASE64 }}" ]; then
71-
echo "❌ Missing secret: KEYSTORE_BASE64"
72-
exit 1
73-
fi
74-
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > release.keystore
75+
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
7576
chmod 600 release.keystore
76-
ls -lh release.keystore || true
77-
echo "✅ Keystore decoded"
77+
env:
78+
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
7879

79-
- name: Make gradlew executable
80-
run: chmod +x android/gradlew
80+
# ------------------------------------------------
81+
# 4️⃣ Make gradlew executable
82+
# ------------------------------------------------
83+
- run: chmod +x android/gradlew
8184

85+
# ------------------------------------------------
86+
# 5️⃣ Build the artefacts (release or debug)
87+
# ------------------------------------------------
8288
- name: Build Release APK (unsigned)
8389
if: ${{ github.event.inputs.output_format == 'apk' || github.event.inputs.output_format == 'both' }}
8490
run: |
85-
set -e
8691
cd android
8792
./gradlew assembleRelease --no-daemon --stacktrace
8893
89-
- name: Build Release AAB
94+
- name: Build Release AAB (unsigned)
9095
if: ${{ github.event.inputs.output_format == 'aab' || github.event.inputs.output_format == 'both' }}
9196
run: |
92-
set -e
9397
cd android
9498
./gradlew bundleRelease --no-daemon --stacktrace
9599
96-
- name: Inspect environment & SDK
97-
run: |
98-
echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT"
99-
echo "Listing available build-tools:"
100-
ls -1 "$ANDROID_SDK_ROOT/build-tools" || true
101-
echo "apksigner version (if available):"
102-
for p in "$ANDROID_SDK_ROOT"/build-tools/*/apksigner; do
103-
if [ -x "$p" ]; then
104-
echo "-> $p"
105-
"$p" version || true
106-
fi
107-
done
108-
echo "java version:"
109-
java -version || true
110-
111-
- name: Inspect Keystore
112-
if: ${{ github.event.inputs.should_sign == 'true' }}
113-
env:
114-
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
115-
run: |
116-
set -e
117-
if [ ! -f release.keystore ]; then
118-
echo "❌ release.keystore not found"
119-
exit 1
120-
fi
121-
echo "=== Keystore contents ==="
122-
keytool -list -v -keystore release.keystore -storepass "${KEYSTORE_PASSWORD}" || true
123-
100+
# ------------------------------------------------
101+
# 6️⃣ (Optional) Sign the APK only – AAB stays unsigned
102+
# ------------------------------------------------
124103
- name: Sign APK
125104
if: ${{ github.event.inputs.should_sign == 'true' && (github.event.inputs.output_format == 'apk' || github.event.inputs.output_format == 'both') }}
126105
id: sign_apk
@@ -130,147 +109,59 @@ jobs:
130109
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
131110
run: |
132111
set -euo pipefail
133-
cd android || exit 1
134-
135-
echo "Finding APK (searching typical output locations)..."
136-
# find the most likely release APK (unsigned or signed)
137-
APK_PATH=$(find app/build/outputs/apk -type f -iname "*release*.apk" | sort | tail -n1 || true)
138-
139-
if [ -z "$APK_PATH" ]; then
140-
echo "❌ APK not found!"
141-
ls -R app/build/outputs || true
142-
exit 1
143-
fi
144-
145-
echo "📦 Found APK: $APK_PATH"
112+
cd android
146113
147-
# Locate build-tools
148-
if [ -d "$ANDROID_SDK_ROOT/build-tools/34.0.0" ]; then
149-
BUILD_TOOLS_PATH="$ANDROID_SDK_ROOT/build-tools/34.0.0"
150-
else
151-
BUILD_TOOLS_VERSION=$(ls -1 "$ANDROID_SDK_ROOT/build-tools" | sort -V | tail -1 || true)
152-
if [ -z "$BUILD_TOOLS_VERSION" ]; then
153-
echo "❌ No build-tools found under $ANDROID_SDK_ROOT/build-tools"
154-
exit 1
155-
fi
156-
BUILD_TOOLS_PATH="$ANDROID_SDK_ROOT/build-tools/$BUILD_TOOLS_VERSION"
157-
fi
114+
# locate the unsigned apk
115+
APK_PATH=$(find app/build/outputs/apk -type f -name "*release*.apk" | sort | tail -n1)
116+
echo "🔎 Unsigned APK: $APK_PATH"
158117
159-
echo "Build tools path: $BUILD_TOOLS_PATH"
160-
if [ ! -x "$BUILD_TOOLS_PATH/zipalign" ] || [ ! -x "$BUILD_TOOLS_PATH/apksigner" ]; then
161-
echo "❌ zipalign or apksigner not found in $BUILD_TOOLS_PATH"
162-
ls -l "$BUILD_TOOLS_PATH" || true
163-
exit 1
164-
fi
118+
# locate the newest build‑tools folder (contains zipalign & apksigner)
119+
BT=$(ls -1 "$ANDROID_SDK_ROOT/build-tools" | sort -V | tail -1)
120+
echo "Using build‑tools $BT"
121+
ZIPALIGN="$ANDROID_SDK_ROOT/build-tools/$BT/zipalign"
122+
APKSIGNER="$ANDROID_SDK_ROOT/build-tools/$BT/apksigner"
165123
166-
echo "🔧 Aligning APK..."
167-
# Always create a fresh aligned APK as input to apksigner
168-
"$BUILD_TOOLS_PATH/zipalign" -v -p 4 "$APK_PATH" release-aligned.apk
124+
# Align
125+
"$ZIPALIGN" -v -p 4 "$APK_PATH" release-aligned.apk
169126
170-
echo "🔐 Signing APK..."
171-
"$BUILD_TOOLS_PATH/apksigner" sign \
127+
# Sign
128+
"$APKSIGNER" sign \
172129
--ks ../release.keystore \
173130
--ks-key-alias "${KEY_ALIAS}" \
174131
--ks-pass "pass:${KEYSTORE_PASSWORD}" \
175132
--key-pass "pass:${KEY_PASSWORD}" \
176133
--out release-signed.apk \
177134
release-aligned.apk
178135
179-
echo "✅ APK signed: release-signed.apk"
136+
echo "✅ Signed APK ready: release-signed.apk"
180137
echo "signed_apk_path=release-signed.apk" >> $GITHUB_OUTPUT
181138
182-
- name: Verify APK signature
139+
# ------------------------------------------------
140+
# 7️⃣ Upload artefacts
141+
# ------------------------------------------------
142+
- name: Upload signed APK
183143
if: ${{ github.event.inputs.should_sign == 'true' && (github.event.inputs.output_format == 'apk' || github.event.inputs.output_format == 'both') }}
184-
env:
185-
BUILD_TOOLS_PATH: ${{ env.BUILD_TOOLS_PATH }}
186-
run: |
187-
set -euo pipefail
188-
cd android || exit 1
189-
190-
# re-detect build-tools (for safety)
191-
if [ -d "$ANDROID_SDK_ROOT/build-tools/34.0.0" ]; then
192-
BUILD_TOOLS_PATH="$ANDROID_SDK_ROOT/build-tools/34.0.0"
193-
else
194-
BUILD_TOOLS_VERSION=$(ls -1 "$ANDROID_SDK_ROOT/build-tools" | sort -V | tail -1 || true)
195-
BUILD_TOOLS_PATH="$ANDROID_SDK_ROOT/build-tools/$BUILD_TOOLS_VERSION"
196-
fi
197-
198-
if [ ! -f release-signed.apk ]; then
199-
echo "❌ release-signed.apk not found"
200-
ls -lh . || true
201-
exit 1
202-
fi
203-
204-
echo "🔍 Verifying APK signature..."
205-
# use exit code of apksigner verify to determine success
206-
if "$BUILD_TOOLS_PATH/apksigner" verify --print-certs release-signed.apk >/dev/null 2>&1; then
207-
echo "✅ APK is properly signed"
208-
echo ""
209-
echo "=== Certificate Information ==="
210-
"$BUILD_TOOLS_PATH/apksigner" verify --print-certs release-signed.apk || true
211-
else
212-
echo "❌ APK signature verification failed!"
213-
"$BUILD_TOOLS_PATH/apksigner" verify release-signed.apk || true
214-
echo ""
215-
echo "Listing release dir for debugging:"
216-
ls -l
217-
exit 1
218-
fi
219-
220-
- name: Sign AAB
221-
if: ${{ github.event.inputs.should_sign == 'true' && (github.event.inputs.output_format == 'aab' || github.event.inputs.output_format == 'both') }}
222-
env:
223-
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
224-
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
225-
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
226-
run: |
227-
set -euo pipefail
228-
cd android || exit 1
229-
230-
AAB_PATH=$(find app/build/outputs/bundle -type f -iname "*.aab" | sort | tail -n1 || true)
231-
if [ -z "$AAB_PATH" ]; then
232-
echo "❌ AAB not found!"
233-
ls -R app/build/outputs || true
234-
exit 1
235-
fi
236-
237-
echo "📦 Found AAB: $AAB_PATH"
238-
echo "🔐 Signing AAB with jarsigner..."
239-
# jarsigner may be present on the runner; this will sign the AAB container.
240-
# If you use Play App Signing by Google Play, consider uploading unsigned and let Play handle signing.
241-
jarsigner -verbose \
242-
-sigalg SHA256withRSA \
243-
-digestalg SHA-256 \
244-
-keystore ../release.keystore \
245-
-storepass "${KEYSTORE_PASSWORD}" \
246-
-keypass "${KEY_PASSWORD}" \
247-
"${AAB_PATH}" \
248-
"${KEY_ALIAS}"
249-
250-
cp "$AAB_PATH" ../release-signed.aab
251-
echo "✅ AAB signed: release-signed.aab"
252-
253-
- name: Upload APK artifact
254-
if: ${{ (github.event.inputs.output_format == 'apk' || github.event.inputs.output_format == 'both') && github.event.inputs.should_sign == 'true' }}
255144
uses: actions/upload-artifact@v4
256145
with:
257146
name: app-release-apk-${{ github.run_number }}
258147
path: android/release-signed.apk
259148
retention-days: 30
260149

261-
- name: Upload AAB artifact
262-
if: ${{ (github.event.inputs.output_format == 'aab' || github.event.inputs.output_format == 'both') && github.event.inputs.should_sign == 'true' }}
150+
- name: Upload AAB (unsigned – Play will sign it)
151+
if: ${{ github.event.inputs.output_format == 'aab' || github.event.inputs.output_format == 'both' }}
263152
uses: actions/upload-artifact@v4
264153
with:
265154
name: app-release-aab-${{ github.run_number }}
266-
path: release-signed.aab
155+
path: android/app/build/outputs/bundle/release/app-release.aab
267156
retention-days: 30
268157

269-
- name: Cleanup sensitive files
158+
# ------------------------------------------------
159+
# 8️⃣ Cleanup secret files
160+
# ------------------------------------------------
161+
- name: Cleanup
270162
if: always()
271163
run: |
272-
rm -f release.keystore || true
273-
rm -f android/release-aligned.apk || true
274-
rm -f android/release-signed.apk || true
275-
rm -f release-signed.aab || true
276-
echo "✅ Cleanup completed"
164+
rm -f release.keystore
165+
rm -f android/release-aligned.apk
166+
rm -f android/release-signed.apk
167+
echo "🧹 Cleanup done"

0 commit comments

Comments
 (0)