feat: build Android APK on Linux CI (symlink, gradlew, setup-android action)
Some checks failed
Build / increment-version (push) Successful in 6s
Build / build-linux (push) Failing after 30s
Build / build-android (push) Failing after 3m1s
Build / build-windows (push) Has been cancelled
Build / create-release (push) Has been cancelled

This commit is contained in:
2026-04-07 15:40:07 +10:00
parent 0c40638a5c
commit 2e4a39b27e
4 changed files with 44 additions and 26 deletions

View File

@@ -162,7 +162,7 @@ jobs:
path: dist-electron/Paarrot-*.AppImage path: dist-electron/Paarrot-*.AppImage
build-android: build-android:
runs-on: windows runs-on: ubuntu-latest
needs: increment-version needs: increment-version
if: always() && (needs.increment-version.outputs.should_build == 'true' || needs.increment-version.result == 'skipped') if: always() && (needs.increment-version.outputs.should_build == 'true' || needs.increment-version.result == 'skipped')
@@ -174,12 +174,10 @@ jobs:
ref: ${{ github.ref_name }} ref: ${{ github.ref_name }}
- name: Checkout submodules manually - name: Checkout submodules manually
shell: powershell
run: git submodule update --init --recursive run: git submodule update --init --recursive
- name: Pull latest (after version bump) - name: Pull latest (after version bump)
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
shell: powershell
run: git pull origin master run: git pull origin master
- name: Setup Node.js - name: Setup Node.js
@@ -187,18 +185,23 @@ jobs:
with: with:
node-version: '20' node-version: '20'
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Install dependencies (root) - name: Install dependencies (root)
run: npm install --prefer-offline run: npm install --prefer-offline
- name: Clean previous cinny dist - name: Clean previous cinny dist
shell: powershell run: rm -rf cinny/dist
run: |
if (Test-Path cinny/dist) { Remove-Item -Recurse -Force cinny/dist }
- name: Apply overlay and build Android APK - name: Apply overlay and build Android APK
run: npm run android:apk run: npm run android:apk:linux
env:
ANDROID_HOME: ${{ secrets.ANDROID_HOME }}
- name: Upload APK - name: Upload APK
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

View File

@@ -11,8 +11,11 @@
"android:open": "cd cinny && npx cap open android", "android:open": "cd cinny && npx cap open android",
"android:run": "cd cinny && npx cap run android", "android:run": "cd cinny && npx cap run android",
"android:apk": "npm run android:prepare && cd cinny/android && gradlew.bat assembleDebug && cd ../.. && node scripts/restore-cinny.mjs", "android:apk": "npm run android:prepare && cd cinny/android && gradlew.bat assembleDebug && cd ../.. && node scripts/restore-cinny.mjs",
"android:apk:linux": "npm run android:prepare && cd cinny/android && ./gradlew assembleDebug && cd ../.. && node scripts/restore-cinny.mjs",
"android:apk:release": "npm run android:prepare && cd cinny/android && gradlew.bat assembleRelease && cd ../.. && node scripts/restore-cinny.mjs", "android:apk:release": "npm run android:prepare && cd cinny/android && gradlew.bat assembleRelease && cd ../.. && node scripts/restore-cinny.mjs",
"android:aab": "npm run android:prepare && cd cinny/android && gradlew.bat bundleRelease && cd ../.. && node scripts/restore-cinny.mjs" "android:apk:release:linux": "npm run android:prepare && cd cinny/android && ./gradlew assembleRelease && cd ../.. && node scripts/restore-cinny.mjs",
"android:aab": "npm run android:prepare && cd cinny/android && gradlew.bat bundleRelease && cd ../.. && node scripts/restore-cinny.mjs",
"android:aab:linux": "npm run android:prepare && cd cinny/android && ./gradlew bundleRelease && cd ../.. && node scripts/restore-cinny.mjs"
}, },
"keywords": [], "keywords": [],
"author": { "author": {

View File

@@ -7,7 +7,7 @@
* 3. Copies overlay/tsconfig.json into cinny/tsconfig.json * 3. Copies overlay/tsconfig.json into cinny/tsconfig.json
* 4. Merges overlay/package-additions.json dependencies into cinny/package.json * 4. Merges overlay/package-additions.json dependencies into cinny/package.json
* 5. Copies capacitor.config.json (root) into cinny/capacitor.config.json with webDir reset to "dist" * 5. Copies capacitor.config.json (root) into cinny/capacitor.config.json with webDir reset to "dist"
* 6. Creates a Windows directory junction cinny/android -> root android/ so Capacitor can find it * 6. Creates a cinny/android symlink/junction -> root android/ so Capacitor can find it
* 7. Writes android/local.properties from ANDROID_HOME env var (so it works on any machine) * 7. Writes android/local.properties from ANDROID_HOME env var (so it works on any machine)
* *
* Run before every Android build to keep the cinny submodule clean while layering * Run before every Android build to keep the cinny submodule clean while layering
@@ -97,28 +97,36 @@ const cinnyCapConfig = { ...rootCapConfig, webDir: 'dist' };
writeFileSync(join(CINNY, 'capacitor.config.json'), JSON.stringify(cinnyCapConfig, null, 2) + '\n', 'utf8'); writeFileSync(join(CINNY, 'capacitor.config.json'), JSON.stringify(cinnyCapConfig, null, 2) + '\n', 'utf8');
console.log(` wrote cinny/capacitor.config.json (webDir: "dist")`); console.log(` wrote cinny/capacitor.config.json (webDir: "dist")`);
// 6. Create a directory junction cinny/android -> root android/ so Capacitor CLI can find it // 6. Create cinny/android -> root android/ link so Capacitor CLI can find it
console.log('[apply-overlay] Setting up android/ junction...'); console.log('[apply-overlay] Setting up android/ link...');
const androidJunction = join(CINNY, 'android'); const androidJunction = join(CINNY, 'android');
const androidTarget = resolve(ROOT, 'android'); const androidTarget = resolve(ROOT, 'android');
if (!existsSync(androidJunction)) { if (!existsSync(androidJunction)) {
try { if (process.platform === 'win32') {
execSync(`cmd /c mklink /J "${androidJunction}" "${androidTarget}"`, { stdio: 'pipe' }); try {
console.log(` created junction: cinny/android -> ${androidTarget}`); execSync(`cmd /c mklink /J "${androidJunction}" "${androidTarget}"`, { stdio: 'pipe' });
} catch (err) { console.log(` created junction: cinny/android -> ${androidTarget}`);
console.warn(' mklink /J failed, falling back to directory copy...'); } catch (err) {
copyDirRecursive(androidTarget, androidJunction); console.warn(' mklink /J failed, falling back to directory copy...');
console.log(` copied android/ into cinny/android/`); copyDirRecursive(androidTarget, androidJunction);
console.log(` copied android/ into cinny/android/`);
}
} else {
const { symlinkSync } = await import('fs');
symlinkSync(androidTarget, androidJunction);
console.log(` created symlink: cinny/android -> ${androidTarget}`);
} }
} else { } else {
console.log(` android/ junction already exists, skipping`); console.log(` android/ link already exists, skipping`);
} }
// 7. Write android/local.properties with the current machine's Android SDK path // 7. Write android/local.properties with the current machine's Android SDK path
const androidHome = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT; const androidHome = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT;
if (androidHome) { if (androidHome) {
console.log('[apply-overlay] Writing android/local.properties...'); console.log('[apply-overlay] Writing android/local.properties...');
const sdkDir = androidHome.replace(/\\/g, '\\\\'); const sdkDir = process.platform === 'win32'
? androidHome.replace(/\\/g, '\\\\')
: androidHome;
writeFileSync(join(androidTarget, 'local.properties'), `sdk.dir=${sdkDir}\n`, 'utf8'); writeFileSync(join(androidTarget, 'local.properties'), `sdk.dir=${sdkDir}\n`, 'utf8');
console.log(` sdk.dir=${androidHome}`); console.log(` sdk.dir=${androidHome}`);
} else { } else {

View File

@@ -29,14 +29,18 @@ if (existsSync(capConfig)) {
console.log('[restore-cinny] Removed cinny/capacitor.config.json'); console.log('[restore-cinny] Removed cinny/capacitor.config.json');
} }
// 3. Remove the android junction (rmdir only removes the junction, not the real directory) // 3. Remove the android link (junction on Windows, symlink on Linux)
const androidJunction = join(CINNY, 'android'); const androidJunction = join(CINNY, 'android');
if (existsSync(androidJunction)) { if (existsSync(androidJunction)) {
try { try {
execSync(`cmd /c rmdir "${androidJunction}"`, { stdio: 'pipe' }); if (process.platform === 'win32') {
console.log('[restore-cinny] Removed cinny/android junction'); execSync(`cmd /c rmdir "${androidJunction}"`, { stdio: 'pipe' });
} else {
unlinkSync(androidJunction);
}
console.log('[restore-cinny] Removed cinny/android link');
} catch (err) { } catch (err) {
console.warn('[restore-cinny] Could not remove android junction:', err.message); console.warn('[restore-cinny] Could not remove android link:', err.message);
} }
} }