Improve workflow reliability and code clarity
- Update GitHub Actions to use latest versions and full clone - Add retry logic to Gradle build steps in workflows - Refactor BridgeModule for clearer variable naming and method usage - Simplify UpdaterModule timeout assignment
This commit is contained in:
parent
ce244b6e58
commit
25cadd08a8
4 changed files with 160 additions and 121 deletions
22
.github/workflows/build.yml
vendored
22
.github/workflows/build.yml
vendored
|
|
@ -7,21 +7,33 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
|
||||
- name: "Setup Gradle"
|
||||
uses: gradle/gradle-build-action@v2
|
||||
|
||||
- name: "Grant execution permission"
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: "Build APKs"
|
||||
run: ./gradlew build
|
||||
run: |
|
||||
# Retry the Gradle build up to 3 times to mitigate transient cache/service errors
|
||||
ATTEMPT=0
|
||||
until [ $ATTEMPT -ge 3 ]
|
||||
do
|
||||
./gradlew build --no-daemon --stacktrace && break
|
||||
ATTEMPT=$((ATTEMPT+1))
|
||||
echo "Gradle build failed, retrying ($ATTEMPT/3)..."
|
||||
sleep 5
|
||||
done
|
||||
if [ $ATTEMPT -ge 3 ]; then
|
||||
echo "Gradle build failed after 3 attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: "Setup directories"
|
||||
run: |
|
||||
|
|
|
|||
160
.github/workflows/release.yml
vendored
160
.github/workflows/release.yml
vendored
|
|
@ -1,77 +1,99 @@
|
|||
name: Build Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
versionName:
|
||||
required: true
|
||||
description: This releases version name
|
||||
default: "1.0.0"
|
||||
versionCode:
|
||||
required: true
|
||||
description: This releases version code
|
||||
default: "1000"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
versionName:
|
||||
required: true
|
||||
description: This releases version name
|
||||
default: "1.0.0"
|
||||
versionCode:
|
||||
required: true
|
||||
description: This releases version code
|
||||
default: "1000"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2.0.10
|
||||
- name: Setup JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: 17
|
||||
|
||||
- name: Set Version
|
||||
uses: chkfung/android-version-actions@v1.1
|
||||
with:
|
||||
gradlePath: app/build.gradle.kts
|
||||
versionCode: ${{github.event.inputs.versionCode}}
|
||||
versionName: ${{github.event.inputs.versionName}}
|
||||
|
||||
- name: Bump Version
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add app/build.gradle.kts
|
||||
if ! git diff --quiet app/build.gradle.kts; then
|
||||
git commit -m "chore: Bump version to ${{github.event.inputs.versionName}} (${{github.event.inputs.versionCode}})"
|
||||
git push
|
||||
else
|
||||
echo "No changes to version file, skipping commit"
|
||||
fi
|
||||
|
||||
- name: Build Signed APK
|
||||
run: |
|
||||
echo "${{ secrets.keystore }}" | base64 -d > $GITHUB_WORKSPACE/signing-key.jks
|
||||
chmod +x ./gradlew
|
||||
./gradlew packageReleaseUniversalApk \
|
||||
-Pandroid.injected.signing.store.file=$GITHUB_WORKSPACE/signing-key.jks \
|
||||
-Pandroid.injected.signing.store.password=${{ secrets.keystore_password }} \
|
||||
-Pandroid.injected.signing.key.alias=${{ secrets.key_alias }} \
|
||||
-Pandroid.injected.signing.key.password=${{ secrets.key_password }}
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
mv app/build/outputs/apk_from_bundle/release/app-release-universal.apk ./app-release.apk
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
tag="${{ github.event.inputs.versionCode }}"
|
||||
git tag "$tag"
|
||||
git push origin "$tag"
|
||||
gh release create "$tag" \
|
||||
--title "${{ github.event.inputs.versionName }}" \
|
||||
--generate-notes \
|
||||
./*.apk
|
||||
env:
|
||||
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v2.0.10
|
||||
|
||||
- name: Set Version
|
||||
uses: chkfung/android-version-actions@v1.1
|
||||
with:
|
||||
gradlePath: app/build.gradle.kts
|
||||
versionCode: ${{github.event.inputs.versionCode}}
|
||||
versionName: ${{github.event.inputs.versionName}}
|
||||
|
||||
- name: Bump Version
|
||||
continue-on-error: true
|
||||
run: |
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
git add app/build.gradle.kts
|
||||
if ! git diff --quiet app/build.gradle.kts; then
|
||||
git commit -m "chore: Bump version to ${{github.event.inputs.versionName}} (${{github.event.inputs.versionCode}})"
|
||||
git push
|
||||
else
|
||||
echo "No changes to version file, skipping commit"
|
||||
fi
|
||||
|
||||
- name: Build Signed APK
|
||||
run: |
|
||||
# Ensure keystore secret is present
|
||||
if [ -z "${{ secrets.keystore }}" ]; then
|
||||
echo "Keystore secret missing, aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "${{ secrets.keystore }}" | base64 -d > $GITHUB_WORKSPACE/signing-key.jks
|
||||
chmod +x ./gradlew
|
||||
|
||||
# Retry gradle up to 3 times to mitigate transient network/cache service issues
|
||||
ATTEMPT=0
|
||||
until [ $ATTEMPT -ge 3 ]
|
||||
do
|
||||
./gradlew packageReleaseUniversalApk \
|
||||
-Pandroid.injected.signing.store.file=$GITHUB_WORKSPACE/signing-key.jks \
|
||||
-Pandroid.injected.signing.store.password=${{ secrets.keystore_password }} \
|
||||
-Pandroid.injected.signing.key.alias=${{ secrets.key_alias }} \
|
||||
-Pandroid.injected.signing.key.password=${{ secrets.key_password }} --no-daemon --stacktrace && break
|
||||
|
||||
ATTEMPT=$((ATTEMPT+1))
|
||||
echo "Gradle build failed, retrying ($ATTEMPT/3)..."
|
||||
sleep 5
|
||||
done
|
||||
|
||||
if [ $ATTEMPT -ge 3 ]; then
|
||||
echo "Gradle build failed after 3 attempts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Release
|
||||
run: |
|
||||
mv app/build/outputs/apk_from_bundle/release/app-release-universal.apk ./app-release.apk
|
||||
git config --local user.email "actions@github.com"
|
||||
git config --local user.name "GitHub Actions"
|
||||
tag="${{ github.event.inputs.versionCode }}"
|
||||
git tag "$tag"
|
||||
git push origin "$tag"
|
||||
gh release create "$tag" \
|
||||
--title "${{ github.event.inputs.versionName }}" \
|
||||
--generate-notes \
|
||||
./*.apk
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -98,11 +98,10 @@ class UpdaterModule : Module() {
|
|||
|
||||
// Retries don't need timeout
|
||||
if (activity != null) {
|
||||
timeout {
|
||||
requestTimeoutMillis =
|
||||
if (!bundle.exists()) TIMEOUT
|
||||
else TIMEOUT_CACHED
|
||||
}
|
||||
val timeoutMs =
|
||||
if (!bundle.exists()) TIMEOUT
|
||||
else TIMEOUT_CACHED
|
||||
timeout { requestTimeoutMillis = timeoutMs }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ typealias BridgeMethodArgs = ArrayList<Any>
|
|||
*/
|
||||
class BridgeModule : Module() {
|
||||
private lateinit var readableMapGetString: Method
|
||||
private lateinit var readableMapToHashMap: Method
|
||||
private lateinit var readableMapToHashMapMethod: Method
|
||||
private lateinit var argumentsMakeNative: Method
|
||||
|
||||
companion object {
|
||||
|
|
@ -126,43 +126,46 @@ class BridgeModule : Module() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) =
|
||||
with(packageParam) {
|
||||
val arguments = classLoader.loadClass("com.facebook.react.bridge.Arguments")
|
||||
val readableMap = classLoader.loadClass("com.facebook.react.bridge.ReadableMap")
|
||||
val promise = classLoader.loadClass("com.facebook.react.bridge.Promise")
|
||||
override fun onLoad(packageParam: XC_LoadPackage.LoadPackageParam) {
|
||||
with(packageParam) {
|
||||
val arguments = classLoader.loadClass("com.facebook.react.bridge.Arguments")
|
||||
val readableMap = classLoader.loadClass("com.facebook.react.bridge.ReadableMap")
|
||||
val promise = classLoader.loadClass("com.facebook.react.bridge.Promise")
|
||||
|
||||
val promiseResolve = promise.method("resolve", Object::class.java)
|
||||
argumentsMakeNative = arguments.method("makeNativeObject", Object::class.java)
|
||||
readableMapGetString = readableMap.method("getString", String::class.java)
|
||||
readableMapToHashMap = readableMap.method("toHashMap")
|
||||
val promiseResolve = promise.method("resolve", Object::class.java)
|
||||
argumentsMakeNative = arguments.method("makeNativeObject", Object::class.java)
|
||||
readableMapGetString = readableMap.method("getString", String::class.java)
|
||||
readableMapToHashMapMethod = readableMap.method("toHashMap")
|
||||
|
||||
classLoader.loadClass("com.horcrux.svg.RNSVGRenderableManager").hookMethod(
|
||||
"getBBox",
|
||||
Double::class.javaObjectType,
|
||||
readableMap
|
||||
) {
|
||||
before {
|
||||
callBridgeMethod(readableMapToHashMap(args[1]!!))?.let {
|
||||
result = it.toNativeObject()
|
||||
}
|
||||
classLoader.loadClass("com.horcrux.svg.RNSVGRenderableManager").hookMethod(
|
||||
"getBBox",
|
||||
Double::class.javaObjectType,
|
||||
readableMap
|
||||
) {
|
||||
before {
|
||||
callBridgeMethod(readableMapToHashMapConverter(args[1]!!))?.let {
|
||||
result = it.toNativeObject()
|
||||
}
|
||||
}
|
||||
|
||||
classLoader.loadClass("com.facebook.react.modules.blob.FileReaderModule")
|
||||
.hookMethod("readAsDataURL", readableMap, promise) {
|
||||
before {
|
||||
val (readableMap, promise) = args
|
||||
callBridgeMethod(readableMapToHashMap(readableMap!!))?.let {
|
||||
promiseResolve.invoke(promise, it.toNativeObject())
|
||||
result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return@with
|
||||
}
|
||||
|
||||
classLoader.loadClass("com.facebook.react.modules.blob.FileReaderModule").hookMethod(
|
||||
"readAsDataURL",
|
||||
readableMap,
|
||||
promise
|
||||
) {
|
||||
before {
|
||||
// Avoid shadowing the outer `readableMap` and `promise` variables
|
||||
val (readableMapArg, promiseArg) = args
|
||||
callBridgeMethod(readableMapToHashMapConverter(readableMapArg!!))?.let {
|
||||
promiseResolve.invoke(promiseArg, it.toNativeObject())
|
||||
result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Any?.toNativeObject(): Any? =
|
||||
argumentsMakeNative.invoke(
|
||||
null,
|
||||
|
|
@ -172,18 +175,21 @@ class BridgeModule : Module() {
|
|||
}
|
||||
)
|
||||
|
||||
private fun readableMapToHashMap(map: Any): HashMap<String, Any?> {
|
||||
@Suppress("UNCHECKED_CAST") return readableMapToHashMap.invoke(map) as HashMap<String, Any?>
|
||||
private fun readableMapToHashMapConverter(map: Any): HashMap<String, Any?> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return readableMapToHashMapMethod.invoke(map) as HashMap<String, Any?>
|
||||
}
|
||||
|
||||
private fun callBridgeMethod(hashMap: HashMap<String, Any?>): Map<String, Any?>? =
|
||||
try {
|
||||
val (method, args) = getBridgeCallData(hashMap) ?: return null
|
||||
val ret = method(args).toNativeObject()
|
||||
mapOf("result" to ret)
|
||||
} catch (e: Throwable) {
|
||||
mapOf("error" to e.toString())
|
||||
}
|
||||
private fun callBridgeMethod(hashMap: HashMap<String, Any?>): Map<String, Any?>? {
|
||||
try {
|
||||
val pair = getBridgeCallData(hashMap) ?: return null
|
||||
val (method, args) = pair
|
||||
val ret = method(args).toNativeObject()
|
||||
return mapOf("result" to ret)
|
||||
} catch (e: Throwable) {
|
||||
return mapOf("error" to e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBridgeCallData(
|
||||
hashMap: HashMap<String, Any?>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue