fix: updated icon launcher #39
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: 🚀 Build and Release Android | |
| on: | |
| push: | |
| branches: [ main ] | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| # ───────────────────────────────────────────── | |
| # Job 1 — Resolve the next semantic version | |
| # Runs semantic-release in dry-run mode so we | |
| # know the version before the build starts. | |
| # ───────────────────────────────────────────── | |
| resolve-version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.semver.outputs.version }} | |
| version_code: ${{ steps.semver.outputs.version_code }} | |
| will_release: ${{ steps.semver.outputs.will_release }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "lts/*" | |
| - name: Install semantic-release | |
| run: | | |
| npm install --save-dev semantic-release \ | |
| @semantic-release/changelog \ | |
| @semantic-release/git \ | |
| @semantic-release/github \ | |
| conventional-changelog-conventionalcommits | |
| - name: Write .releaserc.json (dry-run config) | |
| run: | | |
| cat > .releaserc.json << 'EOF' | |
| { | |
| "branches": ["main"], | |
| "plugins": [ | |
| ["@semantic-release/commit-analyzer", { "preset": "conventionalcommits" }], | |
| ["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }] | |
| ] | |
| } | |
| EOF | |
| - name: Determine next version (dry-run) | |
| id: semver | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # semantic-release exits 1 when no release is triggered — that's not an | |
| # error for us, so we capture the exit code manually instead of letting | |
| # bash -e kill the step. | |
| set +e | |
| OUTPUT=$(npx semantic-release --dry-run --no-ci 2>&1) | |
| SR_EXIT=$? | |
| set -e | |
| echo "$OUTPUT" | |
| echo "--- semantic-release exit code: $SR_EXIT ---" | |
| VERSION=$(echo "$OUTPUT" | grep -oP 'The next release version is \K[0-9]+\.[0-9]+\.[0-9]+' | head -1) | |
| # Exit code 2+ means a real error (bad config, auth failure, etc.) | |
| if [ $SR_EXIT -ge 2 ]; then | |
| echo "❌ semantic-release failed with exit code $SR_EXIT" | |
| exit $SR_EXIT | |
| fi | |
| if [ -z "$VERSION" ]; then | |
| echo "⚠️ No release triggered — using last tag or 1.0.0" | |
| VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "1.0.0") | |
| echo "will_release=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "will_release=true" >> $GITHUB_OUTPUT | |
| fi | |
| # versionCode: major*10000 + minor*100 + patch (e.g. 1.2.3 → 10203) | |
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | |
| MINOR=$(echo "$VERSION" | cut -d. -f2) | |
| PATCH=$(echo "$VERSION" | cut -d. -f3) | |
| VERSION_CODE=$(( MAJOR * 10000 + MINOR * 100 + PATCH )) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_code=$VERSION_CODE" >> $GITHUB_OUTPUT | |
| echo "✅ Version: $VERSION (code: $VERSION_CODE)" | |
| # ───────────────────────────────────────────── | |
| # Job 2 — Build & release | |
| # Uses the version resolved above. | |
| # ───────────────────────────────────────────── | |
| build-and-release: | |
| runs-on: ubuntu-latest | |
| needs: resolve-version | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| cache: gradle | |
| - name: Setup Android SDK | |
| uses: android-actions/setup-android@v3 | |
| - name: Cache Gradle dependencies | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Cache Android build | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.android/build-cache | |
| app/build | |
| key: ${{ runner.os }}-android-${{ hashFiles('**/build.gradle*', '**/gradle.properties', '**/settings.gradle*') }} | |
| restore-keys: | | |
| ${{ runner.os }}-android- | |
| - name: Cache Kotlin | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.kotlin/cache | |
| ~/.konan | |
| key: ${{ runner.os }}-kotlin-${{ hashFiles('**/*.kt', '**/*.kts') }} | |
| restore-keys: | | |
| ${{ runner.os }}-kotlin- | |
| - name: Make gradlew executable | |
| run: chmod +x ./gradlew | |
| - name: Decode Keystore | |
| run: | | |
| echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > $RUNNER_TEMP/release.keystore | |
| - name: Build Release APK + AAB (signed, versioned) | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| VERSION_CODE: ${{ needs.resolve-version.outputs.version_code }} | |
| KEYSTORE_PATH: ${{ runner.temp }}/release.keystore | |
| KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} | |
| KEY_ALIAS: ${{ secrets.KEY_ALIAS }} | |
| KEY_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} | |
| run: | | |
| echo "🏗️ Building v$VERSION (code $VERSION_CODE)" | |
| ./gradlew assembleRelease bundleRelease \ | |
| -PversionName="$VERSION" \ | |
| -PversionCode="$VERSION_CODE" \ | |
| -Pandroid.injected.signing.store.file=$RUNNER_TEMP/release.keystore \ | |
| -Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} \ | |
| -Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \ | |
| -Pandroid.injected.signing.key.password=${{ secrets.KEYSTORE_PASSWORD }} \ | |
| --build-cache | |
| - name: Rename and verify outputs | |
| id: outputs | |
| env: | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| run: | | |
| # Debug: show what was actually produced | |
| echo "📂 Build outputs:" | |
| find app/build/outputs -type f 2>/dev/null || echo " (nothing found)" | |
| APK_SRC="app/build/outputs/apk/release/app-release.apk" | |
| AAB_SRC="app/build/outputs/bundle/release/app-release.aab" | |
| [ ! -f "$APK_SRC" ] && APK_SRC=$(find app/build/outputs -name "*release*.apk" -type f | head -1) | |
| [ ! -f "$AAB_SRC" ] && AAB_SRC=$(find app/build/outputs -name "*release*.aab" -type f | head -1) | |
| if [ -z "$APK_SRC" ] || [ ! -f "$APK_SRC" ]; then | |
| echo "❌ APK release non trouvé" | |
| exit 1 | |
| fi | |
| if [ -z "$AAB_SRC" ] || [ ! -f "$AAB_SRC" ]; then | |
| echo "❌ AAB release non trouvé" | |
| exit 1 | |
| fi | |
| APK_OUT="app/build/outputs/apk/release/app-release-v${VERSION}.apk" | |
| AAB_OUT="app/build/outputs/bundle/release/app-release-v${VERSION}.aab" | |
| mv "$APK_SRC" "$APK_OUT" | |
| mv "$AAB_SRC" "$AAB_OUT" | |
| echo "APK_PATH=$APK_OUT" >> $GITHUB_OUTPUT | |
| echo "AAB_PATH=$AAB_OUT" >> $GITHUB_OUTPUT | |
| echo "✅ APK: $APK_OUT" | |
| echo "✅ AAB: $AAB_OUT" | |
| - name: Setup Node.js for semantic-release | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "lts/*" | |
| - name: Install semantic-release | |
| run: | | |
| npm install --save-dev semantic-release \ | |
| @semantic-release/changelog \ | |
| @semantic-release/git \ | |
| @semantic-release/github | |
| - name: Write .releaserc.json (real release with assets) | |
| env: | |
| APK_PATH: ${{ steps.outputs.outputs.APK_PATH }} | |
| AAB_PATH: ${{ steps.outputs.outputs.AAB_PATH }} | |
| VERSION: ${{ needs.resolve-version.outputs.version }} | |
| run: | | |
| cat << 'EOF' > .releaserc.json | |
| { | |
| "branches": ["main"], | |
| "plugins": [ | |
| ["@semantic-release/commit-analyzer", { "preset": "angular" }], | |
| ["@semantic-release/release-notes-generator", { "preset": "angular" }], | |
| "@semantic-release/changelog", | |
| ["@semantic-release/github", { | |
| "assets": [ | |
| { | |
| "path": "${{ env.APK_PATH }}", | |
| "name": "app-release-v${{ env.VERSION }}.apk", | |
| "label": "Android APK v${{ env.VERSION }} (universal)" | |
| }, | |
| { | |
| "path": "${{ env.AAB_PATH }}", | |
| "name": "app-release-v${{ env.VERSION }}.aab", | |
| "label": "Android App Bundle v${{ env.VERSION }} (Play Store)" | |
| } | |
| ] | |
| }], | |
| ["@semantic-release/git", { | |
| "assets": ["CHANGELOG.md"], | |
| "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" | |
| }] | |
| ] | |
| } | |
| EOF | |
| - name: Run semantic-release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: npx semantic-release | |
| - name: Publish AAB to Play Store | |
| uses: r0adkll/upload-google-play@v1 | |
| with: | |
| serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }} | |
| packageName: com.mirage.bob1 | |
| releaseFiles: ${{ steps.outputs.outputs.AAB_PATH }} | |
| track: internal | |
| status: completed | |
| - name: Upload APK artifact | |
| if: steps.outputs.outputs.APK_PATH != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bob1-apk | |
| path: ${{ steps.outputs.outputs.APK_PATH }} | |
| retention-days: 30 | |
| - name: Upload AAB artifact | |
| if: steps.outputs.outputs.AAB_PATH != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bob1-aab | |
| path: ${{ steps.outputs.outputs.AAB_PATH }} | |
| retention-days: 30 |