From a4084bf1834c254a8a28a5bc2f8d7f3334e54203 Mon Sep 17 00:00:00 2001 From: Garfie Date: Mon, 13 Apr 2026 19:30:10 -0500 Subject: [PATCH] ci(android): publish signed debug APK on PRs with sticky link comment --- .github/workflows/ci.yml | 46 +++++++++++++++++++++++++++++++++++++++ .gitignore | 1 + app/build.gradle.kts | 9 ++++++++ app/debug.keystore | Bin 0 -> 2714 bytes 4 files changed, 56 insertions(+) create mode 100644 app/debug.keystore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 334867d..b918378 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,10 @@ jobs: name: Build Android App runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: - name: Checkout uses: actions/checkout@v5 @@ -98,6 +102,48 @@ jobs: - name: Build debug APK run: ./gradlew :app:assembleDebug + - name: Upload debug APK + id: upload_apk + if: always() && hashFiles('app/build/outputs/apk/debug/app-debug.apk') != '' + uses: actions/upload-artifact@v6 + with: + name: librechat-android-debug-${{ github.event.pull_request.number || github.sha }} + path: app/build/outputs/apk/debug/app-debug.apk + retention-days: 90 + if-no-files-found: error + + - name: Write APK summary + if: always() && steps.upload_apk.outputs.artifact-url != '' + env: + ARTIFACT_NAME: librechat-android-debug-${{ github.event.pull_request.number || github.sha }} + ARTIFACT_URL: ${{ steps.upload_apk.outputs.artifact-url }} + run: | + { + echo "## Android debug APK" + echo "" + echo "- **Artifact:** \`$ARTIFACT_NAME\`" + echo "- **Download:** [$ARTIFACT_NAME.zip]($ARTIFACT_URL)" + echo "- **Retention:** 90 days" + echo "" + echo "> Download requires a GitHub login. Installs over previous debug builds without uninstalling (stable signing key)." + } >> "$GITHUB_STEP_SUMMARY" + + - name: Post APK link to PR + if: always() && github.event_name == 'pull_request' && steps.upload_apk.outputs.artifact-url != '' + continue-on-error: true + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: android-debug-apk + message: | + ## Android debug APK + + **Artifact:** `librechat-android-debug-${{ github.event.pull_request.number }}` + **Download:** [librechat-android-debug-${{ github.event.pull_request.number }}.zip](${{ steps.upload_apk.outputs.artifact-url }}) + **Retention:** 90 days + **Commit:** `${{ github.event.pull_request.head.sha }}` + + > Download requires a GitHub login. Installs over previous debug builds without uninstalling (stable signing key). + ios: name: Build iOS App runs-on: macos-latest diff --git a/.gitignore b/.gitignore index b6306c6..7bc2dd1 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ local.properties # Keystore *.jks *.keystore +!app/debug.keystore # OS .DS_Store diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ec8ce3c..8dc349f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,6 +12,15 @@ android { applicationId = "com.garfiec.librechat" } + signingConfigs { + getByName("debug") { + storeFile = file("debug.keystore") + storePassword = "android" + keyAlias = "androiddebugkey" + keyPassword = "android" + } + } + buildFeatures { buildConfig = true } diff --git a/app/debug.keystore b/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..63859578fa7bdfe595093b04b776a89b161b2cf7 GIT binary patch literal 2714 zcma)8X*d)N*Pa=}7+XU#c0*a7>|>qCGRV$MNMfv^A=_BXmJA^(GPXx!naA$QPFWJ! z29YJZEXkHeQOcgzcYW{GbG^Ub_s6;JbME`x=jVML6p1AR1Y|&wSTIabsW_v!U3MS@ zm``F+0Fzi`PiaXMiLw1ZB*q#riLv68E<3FvCf0wu*jRv|d=ew(l+-}o{Ow?5N7i8;Kd3Dp*Ij+k^*%7!9~KBEfrm4TS61u`b^{e#wre%V(MqE3+68=plax9{ z@%_D$OYZPW?_=_FuU1|DGb^nD&_~-A3)4V@lQvR^Mbc4&I%B7=-&x`W|ChTxH!eS~ zd>yVyC_(B@AzZ_vV*2{XUB<(=Usmue#?l-}SN11{jpC6RgEg4iNx)uZpBdzr+tKMXz{AUJ~He8yUoMZ>g{(ef4Ebm&of=;Qfi zlX=@;Mf@5iaeWZj_-l2WZu7Z5!77*Ol7q)PSPI|F z@k5Sg(@V24p<>#Z>)_lQu&^R5<>Tf4uAJj%Bh4MUNGsq3 zKgRIJTD^Xhk<+?Fg!|wRp86{{>*(~$UpvJccCyU`Na)t4IRENbmb9Y zSi+1-disF#gx_y76bz21Ugz~s%*&-_GJa}V!fGLVG$nWK{q?SddcOFnO77Fvr(MTE zMGrlwWkAtIzg_GYErnul(w4*=ZbWH|QIKR7=`H^A0fME5gVMci$_lLXgy!0CyEF0* zW|v~N&x?{T({=pM>yu#2Cgg}@-TPbAeykCbdy}xaTjLV^?)KYp^_16uxoTWSYbMqy zK*`t28zCLvBq3f7=M(9zLRL4bUz3rQv1{LUb>|7~@c9ehB_jx{-cTIM?=X9tt+>3u zA%k(2DjTr&l;`DcuUB>HaU@^-JF|M>iTw87ayLC}D}|d%aq3r=v$ob8u|TaqWRdI= z$#Dd2`bF}=74I8iR%tJo4dnD!VPea5`42lna;)(Anv&yJ=$DF{MyR6uG@xrdRjAd zK+n>ykF*oWY3Ll9(!5%BAm=Q`zmnM2Ak9OswYTSFE6xdZi8%OHK=3~|dz&eP%|+=8 z?*;aQ9`EuJp%$04L2*ZcT5)q>s{xrw2Pmvh|)c7`%_3R~zfW6NLH#V9?Ng!gk1Hle& zC;WjY#Y31~iN4VhE#EX}S(LJa{)2XKtMm+$>2*ZfIALJ^5Os7iJ$0-NO6Z>ozUV zg>kaQ9W5@QODnv+%X&xRqU~=aLQ?u^ijoS#-_AQZ=TKtOW-DA?S~~KYTb^5g{oU}F9 zE4}ukNZs=7D8Ltfe(*z1)e(C8vv#x}o1h`$_V~wTNizA%#?G5dwZqsHLgtB6z8O8X z+f-~_%O|Oi`>KVcYQf1R94svZ(?3P|U)HQ&2mJ())BdQL~^}UdrT})=W z1`^)ltXk9?>2?N3cI0|%tR!#P`AoTAIEbqS8O^G{7nfUUs=03{apaG-O>69Zk7@2a zI~r6qE^L3dhTlB#<~9?O?dGMDBr97vq;Lr7+5y&er{~)VJlZAwoK%Z$;tz)6X-7Ng ze)sH>@BHCfI-8HoP%~byx6KTYg)&DepxA%^Yak#a04xG*+`KzDsANi>m)+aDVbGvT sTECDjfqw;S6)sQ}Pi_FiUF|>Cc?)TM7SFgcS?9$eS{ONT^na1^FH3CE^#A|> literal 0 HcmV?d00001