Skip to content

Commit 169cee4

Browse files
committed
fix: harden shell runtime, stabilize app flows, and sync native docs/CI
1 parent ee519c2 commit 169cee4

32 files changed

+1165
-517
lines changed

.github/workflows/build.yml

Lines changed: 14 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -7,53 +7,18 @@ on:
77
branches: [main]
88

99
jobs:
10-
build-web:
11-
name: Build React
12-
runs-on: ubuntu-latest
13-
steps:
14-
- name: Checkout code
15-
uses: actions/checkout@v4
16-
17-
- name: Setup Node.js
18-
uses: actions/setup-node@v4
19-
with:
20-
node-version: '20'
21-
cache: 'npm'
22-
cache-dependency-path: web/package-lock.json
23-
24-
- name: Install dependencies
25-
working-directory: ./web
26-
run: npm ci
27-
28-
- name: Build React
29-
working-directory: ./web
30-
run: npm run build
31-
32-
- name: Upload web assets
33-
uses: actions/upload-artifact@v4
34-
with:
35-
name: web-assets
36-
path: app/src/main/assets/www
37-
retention-days: 1
38-
3910
build-android:
40-
name: Build Android
41-
needs: build-web
11+
name: Lint, Test, and Build Debug APK
4212
runs-on: ubuntu-latest
4313
permissions:
4414
contents: read
15+
4516
steps:
4617
- name: Checkout code
47-
uses: actions/checkout@v4
48-
49-
- name: Download web assets
50-
uses: actions/download-artifact@v4
51-
with:
52-
name: web-assets
53-
path: app/src/main/assets/www
18+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
5419

5520
- name: Setup JDK 17
56-
uses: actions/setup-java@v4
21+
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9
5722
with:
5823
java-version: '17'
5924
distribution: 'temurin'
@@ -62,51 +27,19 @@ jobs:
6227
- name: Grant execute permission for gradlew
6328
run: chmod +x gradlew
6429

65-
# 1. Debug Build
66-
- name: Build Debug APK
30+
- name: Run lint
31+
run: ./gradlew lintDebug --no-daemon
32+
33+
- name: Run unit tests
34+
run: ./gradlew testDebugUnitTest --no-daemon
35+
36+
- name: Build debug APK
6737
run: ./gradlew assembleDebug --no-daemon
6838

69-
- name: Upload Debug APK
70-
uses: actions/upload-artifact@v4
39+
- name: Upload debug APK
40+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
7141
with:
7242
name: AppControlX-debug
7343
path: app/build/outputs/apk/debug/*.apk
74-
retention-days: 7
75-
76-
# 2. Release Build (Logic to handle both Real Sign and Generated Sign)
77-
- name: Configure Keystore
78-
id: sign_config
79-
run: |
80-
if [ -n "${{ secrets.KEYSTORE_BASE64 }}" ]; then
81-
echo "Found secrets. Setting up Real Signing..."
82-
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > release.keystore
83-
echo "KEYSTORE_FILE=$(pwd)/release.keystore" >> $GITHUB_ENV
84-
echo "KEYSTORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV
85-
echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> $GITHUB_ENV
86-
echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> $GITHUB_ENV
87-
echo "build_type=real-signed" >> $GITHUB_OUTPUT
88-
else
89-
echo "No secrets found. Setting up Generated Signing..."
90-
keytool -genkey -v -keystore release.keystore -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000 -storepass android -keypass android -dname "CN=Android Debug,O=Android,C=US"
91-
echo "KEYSTORE_FILE=$(pwd)/release.keystore" >> $GITHUB_ENV
92-
echo "KEYSTORE_PASSWORD=android" >> $GITHUB_ENV
93-
echo "KEY_ALIAS=androiddebugkey" >> $GITHUB_ENV
94-
echo "KEY_PASSWORD=android" >> $GITHUB_ENV
95-
echo "build_type=generated-signed" >> $GITHUB_OUTPUT
96-
fi
97-
98-
- name: Build Release APK
99-
run: ./gradlew assembleRelease --no-daemon
100-
101-
- name: Rename Release APK
102-
run: |
103-
cd app/build/outputs/apk/release/
104-
# Find the release apk (it might include version number)
105-
find . -name "*release.apk" -exec mv {} AppControlX-release-${{ steps.sign_config.outputs.build_type }}.apk \;
106-
107-
- name: Upload Release APK
108-
uses: actions/upload-artifact@v4
109-
with:
110-
name: AppControlX-release-${{ steps.sign_config.outputs.build_type }}
111-
path: app/build/outputs/apk/release/*.apk
44+
if-no-files-found: error
11245
retention-days: 7

.github/workflows/release.yml

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,23 @@ on:
77

88
jobs:
99
build-and-release:
10-
name: Build and Release
10+
name: Build Signed Release and Publish
1111
runs-on: ubuntu-latest
1212
permissions:
1313
contents: write
1414

15+
env:
16+
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
17+
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
18+
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
19+
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
20+
1521
steps:
1622
- name: Checkout code
17-
uses: actions/checkout@v4
18-
19-
- name: Setup Node.js
20-
uses: actions/setup-node@v4
21-
with:
22-
node-version: '20'
23-
cache: 'npm'
24-
cache-dependency-path: web/package-lock.json
25-
26-
- name: Install web dependencies
27-
working-directory: ./web
28-
run: npm ci
29-
30-
- name: Build React
31-
working-directory: ./web
32-
run: npm run build
23+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
3324

3425
- name: Setup JDK 17
35-
uses: actions/setup-java@v4
26+
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9
3627
with:
3728
java-version: '17'
3829
distribution: 'temurin'
@@ -41,31 +32,50 @@ jobs:
4132
- name: Grant execute permission for gradlew
4233
run: chmod +x gradlew
4334

44-
- name: Decode Keystore
45-
if: env.KEYSTORE_BASE64 != ''
46-
env:
47-
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
35+
- name: Validate signing secrets
36+
shell: bash
4837
run: |
49-
echo "$KEYSTORE_BASE64" | base64 --decode > app/keystore.jks
38+
set -euo pipefail
39+
missing=()
40+
[ -n "$KEYSTORE_BASE64" ] || missing+=("KEYSTORE_BASE64")
41+
[ -n "$KEYSTORE_PASSWORD" ] || missing+=("KEYSTORE_PASSWORD")
42+
[ -n "$KEY_ALIAS" ] || missing+=("KEY_ALIAS")
43+
[ -n "$KEY_PASSWORD" ] || missing+=("KEY_PASSWORD")
44+
45+
if [ ${#missing[@]} -gt 0 ]; then
46+
echo "Release signing is required. Missing secrets: ${missing[*]}"
47+
exit 1
48+
fi
5049
51-
- name: Build Release APK
50+
- name: Decode keystore
51+
shell: bash
52+
run: |
53+
set -euo pipefail
54+
KEYSTORE_PATH="$RUNNER_TEMP/release.keystore"
55+
echo "$KEYSTORE_BASE64" | base64 --decode > "$KEYSTORE_PATH"
56+
echo "KEYSTORE_FILE=$KEYSTORE_PATH" >> "$GITHUB_ENV"
57+
58+
- name: Build signed release APK
5259
run: ./gradlew assembleRelease --no-daemon
5360
env:
54-
KEYSTORE_FILE: ${{ github.workspace }}/app/keystore.jks
55-
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
56-
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
57-
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
61+
KEYSTORE_FILE: ${{ env.KEYSTORE_FILE }}
62+
KEYSTORE_PASSWORD: ${{ env.KEYSTORE_PASSWORD }}
63+
KEY_ALIAS: ${{ env.KEY_ALIAS }}
64+
KEY_PASSWORD: ${{ env.KEY_PASSWORD }}
5865

59-
- name: Get version from tag
60-
id: version
61-
run: echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
66+
- name: Upload release artifact
67+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
68+
with:
69+
name: AppControlX-release
70+
path: app/build/outputs/apk/release/*.apk
71+
if-no-files-found: error
72+
retention-days: 30
6273

63-
- name: Create Release
64-
uses: softprops/action-gh-release@v1
74+
- name: Publish GitHub release
75+
uses: softprops/action-gh-release@26994186c0ac3ef5cae75ac16aa32e8153525f77
6576
with:
66-
name: AppControlX ${{ steps.version.outputs.version }}
67-
files: |
68-
app/build/outputs/apk/release/*.apk
77+
name: AppControlX ${{ github.ref_name }}
78+
files: app/build/outputs/apk/release/*.apk
6979
generate_release_notes: true
7080
draft: false
7181
prerelease: false

CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ This is a complete migration from WebView/React to full native Kotlin with Jetpa
5050
- **activity_main.xml** - Layout XML removed
5151

5252
### Technical Details
53-
- 100% offline, no network calls
53+
- Native feature execution is local/on-device; the app still declares `INTERNET` permission in manifest
5454
- All native methods preserved (ShellManager, AppScanner, etc.)
5555
- Material Design 3 components throughout
5656
- Edge-to-edge display support
@@ -114,7 +114,7 @@ This is a complete migration from WebView/React to full native Kotlin with Jetpa
114114
- **Cache Strategy** - 30s TTL for app list, persistent icon cache
115115

116116
### Technical Details
117-
- All optimizations are **100% offline** (no network calls)
117+
- Runtime optimizations are local to device execution paths (no backend dependency)
118118
- Web layer remains design + UI only
119119
- Backend remains 100% Kotlin native
120120
- All 23 native methods intact and functional
@@ -243,7 +243,9 @@ This is a complete rewrite of AppControlX with modern architecture and new featu
243243

244244
---
245245

246-
## Architecture (v3)
246+
## Legacy Architecture Context (v3.x)
247+
248+
Historical reference for the v3 release line before the v4 native migration:
247249

248250
```
249251
┌─────────────────────────────────────┐

0 commit comments

Comments
 (0)