Fix syntax error in ai_core_manager.sh at line 184 #13
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Android APK Build Preparation | |
| on: | |
| push: | |
| branches: [ main, 'copilot/**' ] | |
| paths: | |
| - 'scripts/**' | |
| - 'docs/ANDROID_INTEGRATION.md' | |
| - 'android/**' | |
| - '.github/workflows/android-apk-build.yml' | |
| pull_request: | |
| branches: [ main ] | |
| paths: | |
| - 'scripts/**' | |
| - 'docs/ANDROID_INTEGRATION.md' | |
| - 'android/**' | |
| - '.github/workflows/android-apk-build.yml' | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| build_type: | |
| description: 'Build type (debug/release)' | |
| required: true | |
| default: 'debug' | |
| type: choice | |
| options: | |
| - debug | |
| - release | |
| action: | |
| description: 'Action to perform' | |
| required: true | |
| default: 'prepare' | |
| type: choice | |
| options: | |
| - prepare | |
| - build | |
| notify_completion: | |
| description: 'Send notification when complete' | |
| required: false | |
| default: true | |
| type: boolean | |
| env: | |
| JAVA_VERSION: '17' | |
| ANDROID_API_LEVEL: '34' | |
| ANDROID_BUILD_TOOLS_VERSION: '34.0.0' | |
| GRADLE_VERSION: '8.4' | |
| jobs: | |
| prepare-build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| outputs: | |
| preparation-status: ${{ steps.prepare.outputs.status }} | |
| build-ready: ${{ steps.prepare.outputs.build-ready }} | |
| environment-hash: ${{ steps.prepare.outputs.env-hash }} | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Java JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: ${{ env.JAVA_VERSION }} | |
| distribution: 'temurin' | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| with: | |
| api-level: ${{ env.ANDROID_API_LEVEL }} | |
| build-tools: ${{ env.ANDROID_BUILD_TOOLS_VERSION }} | |
| - name: Create Android Project Structure | |
| run: | | |
| echo "Creating Android project structure..." | |
| mkdir -p android/app/src/main/{java/com/spiralgang/filesystemds,res/{layout,values,drawable}} | |
| mkdir -p android/app/src/main/assets | |
| # Create build.gradle (Project level) | |
| cat > android/build.gradle << 'EOF' | |
| buildscript { | |
| ext.kotlin_version = "1.9.20" | |
| dependencies { | |
| classpath 'com.android.tools.build:gradle:8.1.2' | |
| classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | |
| } | |
| } | |
| allprojects { | |
| repositories { | |
| google() | |
| mavenCentral() | |
| } | |
| } | |
| task clean(type: Delete) { | |
| delete rootProject.buildDir | |
| } | |
| EOF | |
| # Create build.gradle (App level) | |
| cat > android/app/build.gradle << 'EOF' | |
| plugins { | |
| id 'com.android.application' | |
| id 'org.jetbrains.kotlin.android' | |
| } | |
| android { | |
| namespace 'com.spiralgang.filesystemds' | |
| compileSdk 34 | |
| defaultConfig { | |
| applicationId "com.spiralgang.filesystemds" | |
| minSdk 24 | |
| targetSdk 34 | |
| versionCode 1 | |
| versionName "1.0.0" | |
| testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | |
| } | |
| buildTypes { | |
| release { | |
| minifyEnabled false | |
| proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | |
| signingConfig signingConfigs.debug | |
| } | |
| debug { | |
| debuggable true | |
| applicationIdSuffix ".debug" | |
| } | |
| } | |
| compileOptions { | |
| sourceCompatibility JavaVersion.VERSION_17 | |
| targetCompatibility JavaVersion.VERSION_17 | |
| } | |
| kotlinOptions { | |
| jvmTarget = '17' | |
| } | |
| } | |
| dependencies { | |
| implementation 'androidx.core:core-ktx:1.12.0' | |
| implementation 'androidx.appcompat:appcompat:1.6.1' | |
| implementation 'com.google.android.material:material:1.10.0' | |
| implementation 'androidx.constraintlayout:constraintlayout:2.1.4' | |
| testImplementation 'junit:junit:4.13.2' | |
| androidTestImplementation 'androidx.test.ext:junit:1.1.5' | |
| androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' | |
| } | |
| EOF | |
| # Create gradle.properties | |
| cat > android/gradle.properties << 'EOF' | |
| org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 | |
| android.useAndroidX=true | |
| android.enableJetifier=true | |
| kotlin.code.style=official | |
| android.nonTransitiveRClass=true | |
| EOF | |
| # Create settings.gradle | |
| cat > android/settings.gradle << 'EOF' | |
| pluginManagement { | |
| repositories { | |
| google() | |
| mavenCentral() | |
| gradlePluginPortal() | |
| } | |
| } | |
| dependencyResolutionManagement { | |
| repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) | |
| repositories { | |
| google() | |
| mavenCentral() | |
| } | |
| } | |
| rootProject.name = "FileSystemds" | |
| include ':app' | |
| EOF | |
| - name: Create Android Manifest | |
| run: | | |
| cat > android/app/src/main/AndroidManifest.xml << 'EOF' | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:tools="http://schemas.android.com/tools"> | |
| <uses-permission android:name="android.permission.INTERNET" /> | |
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |
| <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | |
| <application | |
| android:allowBackup="true" | |
| android:dataExtractionRules="@xml/data_extraction_rules" | |
| android:fullBackupContent="@xml/backup_rules" | |
| android:icon="@mipmap/ic_launcher" | |
| android:label="@string/app_name" | |
| android:roundIcon="@mipmap/ic_launcher_round" | |
| android:supportsRtl="true" | |
| android:theme="@style/Theme.FileSystemds" | |
| tools:targetApi="31"> | |
| <activity | |
| android:name=".MainActivity" | |
| android:exported="true"> | |
| <intent-filter> | |
| <action android:name="android.intent.action.MAIN" /> | |
| <category android:name="android.intent.category.LAUNCHER" /> | |
| </intent-filter> | |
| </activity> | |
| </application> | |
| </manifest> | |
| EOF | |
| - name: Create Android Source Files | |
| run: | | |
| # Create MainActivity.kt | |
| cat > android/app/src/main/java/com/spiralgang/filesystemds/MainActivity.kt << 'EOF' | |
| package com.spiralgang.filesystemds | |
| import android.os.Bundle | |
| import android.widget.TextView | |
| import androidx.appcompat.app.AppCompatActivity | |
| class MainActivity : AppCompatActivity() { | |
| override fun onCreate(savedInstanceState: Bundle?) { | |
| super.onCreate(savedInstanceState) | |
| setContentView(R.layout.activity_main) | |
| val textView = findViewById<TextView>(R.id.textView) | |
| textView.text = "FileSystemds Mobile Platform\nVersion: ${BuildConfig.VERSION_NAME}" | |
| } | |
| } | |
| EOF | |
| # Create layout | |
| cat > android/app/src/main/res/layout/activity_main.xml << 'EOF' | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
| xmlns:app="http://schemas.android.com/tools" | |
| xmlns:tools="http://schemas.android.com/tools" | |
| android:layout_width="match_parent" | |
| android:layout_height="match_parent" | |
| tools:context=".MainActivity"> | |
| <TextView | |
| android:id="@+id/textView" | |
| android:layout_width="wrap_content" | |
| android:layout_height="wrap_content" | |
| android:text="FileSystemds Mobile Platform" | |
| android:textSize="18sp" | |
| android:textStyle="bold" | |
| android:gravity="center" | |
| app:layout_constraintBottom_toBottomOf="parent" | |
| app:layout_constraintEnd_toEndOf="parent" | |
| app:layout_constraintStart_toStartOf="parent" | |
| app:layout_constraintTop_toTopOf="parent" /> | |
| </androidx.constraintlayout.widget.ConstraintLayout> | |
| EOF | |
| # Create strings.xml | |
| cat > android/app/src/main/res/values/strings.xml << 'EOF' | |
| <resources> | |
| <string name="app_name">FileSystemds</string> | |
| </resources> | |
| EOF | |
| # Create themes.xml | |
| cat > android/app/src/main/res/values/themes.xml << 'EOF' | |
| <resources xmlns:tools="http://schemas.android.com/tools"> | |
| <style name="Theme.FileSystemds" parent="Theme.Material3.DayNight"> | |
| <item name="colorPrimary">@color/purple_500</item> | |
| <item name="colorPrimaryVariant">@color/purple_700</item> | |
| <item name="colorOnPrimary">@color/white</item> | |
| <item name="colorSecondary">@color/teal_200</item> | |
| <item name="colorSecondaryVariant">@color/teal_700</item> | |
| <item name="colorOnSecondary">@color/black</item> | |
| <item name="colorError">@color/red_600</item> | |
| <item name="colorOnError">@color/white</item> | |
| <item name="colorSurface">@color/white</item> | |
| <item name="colorOnSurface">@color/black</item> | |
| <item name="status_bar_color" tools:targetApi="l">?attr/colorPrimaryVariant</item> | |
| </style> | |
| </resources> | |
| EOF | |
| # Create colors.xml | |
| cat > android/app/src/main/res/values/colors.xml << 'EOF' | |
| <?xml version="1.0" encoding="utf-8"?> | |
| <resources> | |
| <color name="purple_200">#FFBB86FC</color> | |
| <color name="purple_500">#FF6200EE</color> | |
| <color name="purple_700">#FF3700B3</color> | |
| <color name="teal_200">#FF03DAC5</color> | |
| <color name="teal_700">#FF018786</color> | |
| <color name="black">#FF000000</color> | |
| <color name="white">#FFFFFFFF</color> | |
| <color name="red_600">#FFE53E3E</color> | |
| </resources> | |
| EOF | |
| # Copy platform scripts to assets | |
| mkdir -p android/app/src/main/assets/scripts | |
| cp scripts/*.sh android/app/src/main/assets/scripts/ || echo "No scripts to copy yet" | |
| - name: Setup Gradle Wrapper | |
| run: | | |
| cd android | |
| gradle wrapper --gradle-version ${{ env.GRADLE_VERSION }} | |
| chmod +x gradlew | |
| - name: Cache Gradle Dependencies | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| android/.gradle | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/*.gradle*', 'android/**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Prepare or Build APK | |
| id: prepare | |
| run: | | |
| cd android | |
| BUILD_TYPE="${{ github.event.inputs.build_type || 'debug' }}" | |
| ACTION="${{ github.event.inputs.action || 'prepare' }}" | |
| echo "Action: $ACTION" | |
| echo "Build Type: $BUILD_TYPE" | |
| # Always prepare the environment first | |
| echo "Preparing Android build environment..." | |
| # Validate Android project structure | |
| if [ ! -f "build.gradle" ] || [ ! -f "app/build.gradle" ]; then | |
| echo "❌ Android project structure validation failed" | |
| echo "status=failed" >> $GITHUB_OUTPUT | |
| echo "build-ready=false" >> $GITHUB_OUTPUT | |
| exit 1 | |
| fi | |
| # Check dependencies and setup | |
| echo "✓ Android project structure validated" | |
| echo "✓ Gradle wrapper configured" | |
| echo "✓ Dependencies cached" | |
| # Generate environment hash for tracking | |
| ENV_HASH=$(echo "$BUILD_TYPE-$(date +%Y%m%d)" | sha256sum | cut -d' ' -f1 | head -c 8) | |
| echo "env-hash=$ENV_HASH" >> $GITHUB_OUTPUT | |
| # Create preparation manifest | |
| cat > preparation_manifest.json << EOF | |
| { | |
| "preparation_id": "$ENV_HASH", | |
| "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", | |
| "commit_sha": "${{ github.sha }}", | |
| "build_type": "$BUILD_TYPE", | |
| "status": "prepared", | |
| "build_ready": true, | |
| "trigger_required": true, | |
| "environment_validated": true, | |
| "dependencies_cached": true | |
| } | |
| EOF | |
| if [ "$ACTION" = "build" ]; then | |
| echo "🏗️ Building APK as requested..." | |
| if [ "$BUILD_TYPE" = "release" ]; then | |
| ./gradlew assembleRelease | |
| APK_PATH="app/build/outputs/apk/release/app-release.apk" | |
| APK_NAME="filesystemds-mobile-$(date +%Y%m%d-%H%M%S)-release.apk" | |
| else | |
| ./gradlew assembleDebug | |
| APK_PATH="app/build/outputs/apk/debug/app-debug.apk" | |
| APK_NAME="filesystemds-mobile-$(date +%Y%m%d-%H%M%S)-debug.apk" | |
| fi | |
| # Check if APK was built successfully | |
| if [ -f "$APK_PATH" ]; then | |
| echo "✅ APK built successfully: $APK_PATH" | |
| # Rename APK with timestamp | |
| mv "$APK_PATH" "app/build/outputs/apk/$APK_NAME" | |
| # Set outputs for successful build | |
| echo "apk-path=android/app/build/outputs/apk/$APK_NAME" >> $GITHUB_OUTPUT | |
| echo "apk-name=$APK_NAME" >> $GITHUB_OUTPUT | |
| echo "status=build-complete" >> $GITHUB_OUTPUT | |
| echo "build-ready=true" >> $GITHUB_OUTPUT | |
| # Get APK info | |
| aapt dump badging "app/build/outputs/apk/$APK_NAME" || echo "Could not get APK info" | |
| else | |
| echo "❌ APK build failed" | |
| echo "status=build-failed" >> $GITHUB_OUTPUT | |
| echo "build-ready=false" >> $GITHUB_OUTPUT | |
| exit 1 | |
| fi | |
| else | |
| echo "📋 Environment prepared successfully!" | |
| echo "🚨 APK BUILD READY - Manual trigger required" | |
| echo "" | |
| echo "To build the APK, run:" | |
| echo " - Go to Actions tab" | |
| echo " - Select 'Android APK Build Preparation'" | |
| echo " - Click 'Run workflow'" | |
| echo " - Select action: 'build'" | |
| echo " - Select build type: '$BUILD_TYPE'" | |
| echo "" | |
| # Update manifest for preparation only | |
| sed -i 's/"status": "prepared"/"status": "ready-for-build"/' preparation_manifest.json | |
| echo "status=ready-for-build" >> $GITHUB_OUTPUT | |
| echo "build-ready=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Upload Preparation Manifest | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: preparation-manifest-${{ steps.prepare.outputs.env-hash }} | |
| path: android/preparation_manifest.json | |
| retention-days: 7 | |
| - name: Upload APK Artifact | |
| if: github.event.inputs.action == 'build' && steps.prepare.outputs.status == 'build-complete' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ steps.prepare.outputs.apk-name }} | |
| path: ${{ steps.prepare.outputs.apk-path }} | |
| retention-days: 30 | |
| - name: Create Release APK | |
| if: github.event_name == 'release' && github.event.inputs.action == 'build' && steps.prepare.outputs.status == 'build-complete' | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ github.event.release.upload_url }} | |
| asset_path: ${{ steps.prepare.outputs.apk-path }} | |
| asset_name: ${{ steps.prepare.outputs.apk-name }} | |
| asset_content_type: application/vnd.android.package-archive | |
| notify-completion: | |
| runs-on: ubuntu-latest | |
| needs: prepare-build | |
| if: always() && (github.event.inputs.notify_completion == 'true' || github.event.inputs.notify_completion == '') | |
| steps: | |
| - name: Notify Preparation/Build Status | |
| run: | | |
| STATUS="${{ needs.prepare-build.outputs.preparation-status }}" | |
| BUILD_READY="${{ needs.prepare-build.outputs.build-ready }}" | |
| ENV_HASH="${{ needs.prepare-build.outputs.environment-hash }}" | |
| ACTION="${{ github.event.inputs.action || 'prepare' }}" | |
| if [ "$ACTION" = "build" ]; then | |
| if [ "$STATUS" = "build-complete" ]; then | |
| echo "🎉 APK Build Completed Successfully!" | |
| echo "Status: Build Complete" | |
| echo "Environment: $ENV_HASH" | |
| echo "APK is ready for download from GitHub Actions artifacts." | |
| else | |
| echo "❌ APK Build Failed" | |
| echo "Status: $STATUS" | |
| echo "Please check the build logs for details." | |
| fi | |
| else | |
| if [ "$BUILD_READY" = "true" ]; then | |
| echo "📋 APK Build Environment Prepared Successfully!" | |
| echo "🚨 READY TO BUILD APK - MANUAL TRIGGER REQUIRED" | |
| echo "" | |
| echo "Status: $STATUS" | |
| echo "Environment Hash: $ENV_HASH" | |
| echo "Build Ready: $BUILD_READY" | |
| echo "" | |
| echo "Next Steps:" | |
| echo "1. Go to the Actions tab in GitHub" | |
| echo "2. Select 'Android APK Build Preparation'" | |
| echo "3. Click 'Run workflow'" | |
| echo "4. Select action: 'build'" | |
| echo "5. Choose your build type" | |
| echo "6. Click 'Run workflow' to build the APK" | |
| echo "" | |
| echo "The environment is fully prepared and validated." | |
| echo "All dependencies are cached and ready." | |
| echo "The APK build will complete in ~2-3 minutes once triggered." | |
| else | |
| echo "❌ APK Build Preparation Failed" | |
| echo "Status: $STATUS" | |
| echo "Please check the preparation logs for details." | |
| fi | |
| fi | |
| - name: Create Build Ready Comment | |
| if: github.event_name == 'pull_request' && needs.prepare-build.outputs.build-ready == 'true' && github.event.inputs.action != 'build' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const status = '${{ needs.prepare-build.outputs.preparation-status }}'; | |
| const envHash = '${{ needs.prepare-build.outputs.environment-hash }}'; | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: `## 📋 APK Build Environment Ready! | |
| **Status:** ${status} | |
| **Environment Hash:** \`${envHash}\` | |
| **Build Ready:** ✅ Yes | |
| ### 🚨 Manual APK Build Trigger Required | |
| The Android build environment has been prepared and validated. All dependencies are cached and the project structure is ready. | |
| **To build the APK:** | |
| 1. Go to [Actions tab](https://github.com/${{ github.repository }}/actions/workflows/android-apk-build.yml) | |
| 2. Click "Run workflow" | |
| 3. Select action: **build** | |
| 4. Choose build type: debug or release | |
| 5. Click "Run workflow" | |
| The APK build will complete in ~2-3 minutes once triggered. | |
| **Build Details:** | |
| - Commit: ${{ github.sha }} | |
| - Branch: ${{ github.ref_name }} | |
| - Preparation Time: $(date) | |
| Ready to build when you are! 🚀` | |
| }) | |
| - name: Create APK Download Comment | |
| if: github.event_name == 'pull_request' && needs.prepare-build.outputs.preparation-status == 'build-complete' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: `## 📱 APK Build Completed Successfully! | |
| **APK Name:** \`${{ needs.prepare-build.outputs.apk-name }}\` | |
| **Download Link:** [Download APK Artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) | |
| **Build Details:** | |
| - Build Type: ${{ github.event.inputs.build_type || 'debug' }} | |
| - Commit: ${{ github.sha }} | |
| - Branch: ${{ github.ref_name }} | |
| The APK has been built and is ready for testing!` | |
| }) |