diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 0af8e45..680695e 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,74 +1,149 @@ - name: CI/CD Process on: workflow_call: workflow_dispatch: -concurrency: - group: ${{ github.workflow }}-${{ github.event.number || github.ref }} - cancel-in-progress: true - jobs: - build-android: - name: Compile Android - runs-on: ubuntu-latest + build-ios: + name: Build iOS + runs-on: macos-latest concurrency: - group: build-android-${{ github.workflow }}-${{ github.event.number || github.ref }} + group: ios-${{ github.workflow }}-${{ github.event.number || github.ref }} cancel-in-progress: true steps: - name: Checkout uses: actions/checkout@v6.0.2 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - name: Validate Gradle wrapper uses: gradle/actions/wrapper-validation@v6 with: allow-snapshots: false min-wrapper-count: 1 - - name: Set up JDK 17 - uses: actions/setup-java@v5 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' cache: 'gradle' + - name: Set up Ruby & Fastlane + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Build iOS via Fastlane + run: bundle exec fastlane ios build - - name: Run ktlint - run: ./gradlew ktlintCheck - - - name: Compile Android Kotlin - run: ./gradlew composeApp:compileDebugKotlinAndroid - - build-ios: - name: Compile iOS - runs-on: macos-latest + build-android: + name: Compile Android + runs-on: ubuntu-latest concurrency: - group: build-ios-${{ github.workflow }}-${{ github.event.number || github.ref }} + group: android-${{ github.workflow }}-${{ github.event.number || github.ref }} cancel-in-progress: true steps: - name: Checkout uses: actions/checkout@v6.0.2 - + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v5 + with: + allow-snapshots: false + min-wrapper-count: 1 - name: Set up JDK 17 uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '17' cache: 'gradle' - + - name: Set up Ruby w/Fastlane + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - name: Grant execute permission for gradlew run: chmod +x gradlew - - - name: Compile iOS Kotlin - run: ./gradlew composeApp:compileKotlinIosSimulatorArm64 + - name: Run lint through Fastlane + run: bundle exec fastlane android lint + - name: Decode Keystore + env: + ENCODED_STRING: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + run: | + echo $ENCODED_STRING | base64 -di > composeApp/keystore.jks + - name: Build Android Release (APK & AAB) via Fastlane + run: bundle exec fastlane android release + env: # for gradle + KEYSTORE_FILE: "keystore.jks" + KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} + KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} + KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} + - name: Upload Android APK artifact + uses: actions/upload-artifact@v4 + with: + name: echo-app-apk + path: composeApp/build/outputs/apk/release/*.apk + - name: Upload Android AAB artifact + uses: actions/upload-artifact@v4 + with: + name: echo-app-aab + path: composeApp/build/outputs/bundle/release/*.aab + + release: + name: GitHub Release + runs-on: ubuntu-latest + needs: + - build-ios + - build-android + concurrency: + # Only one release job at a time per branch, as only master releases. + group: release-${{ github.event.number || github.ref }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Download Android APK artifact + uses: actions/download-artifact@v4 + with: + name: android-release-apk + path: composeApp/build/outputs/apk/release/ + - name: Install Node + uses: actions/setup-node@v6.3.0 + with: + node-version: ${{ steps.node-version.outputs.version }} + - name: Semantic Release + env: + GITHUB_TOKEN: ${{ secrets.DEPLOYMENT_TOKEN }} + run: | + npm install + npx semantic-release + +###### remove comment when ready to deploy on play store +# deploy-play-store: +# name: Deploy to Play Store +# runs-on: ubuntu-latest +# needs: release +# if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' +# steps: +# - name: Checkout repository +# uses: actions/checkout@v4 +# - name: Download Android AAB artifact +# uses: actions/download-artifact@v4 +# with: +# name: android-release-aab +# path: composeApp/build/outputs/bundle/release/ +# - name: Set up Ruby & Fastlane for Play Store Deploy +# uses: ruby/setup-ruby@v1 +# with: +# bundler-cache: true +# - name: Deploy to Google Play Store via Fastlane +# #env: +# # PLAY_STORE_JSON_KEY_DATA: ${{ secrets.PLAY_STORE_JSON_KEY }} +# run: bundle exec fastlane android deploy success: runs-on: ubuntu-latest needs: - build-android - build-ios + - release + #- deploy-play-store if: >- always() && ( contains(join(needs.*.result, ','), 'failure') diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..cc868b6 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +4.0.1 \ No newline at end of file diff --git a/Gemfile b/Gemfile index 37a2349..a705a83 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org" -ruby '4.0.2' +ruby file: '.ruby-version' gem "fastlane" diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index eae6184..7d59f34 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -82,8 +82,20 @@ android { applicationId = "it.unibo.collektive.echo" minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() - versionCode = 1 - versionName = "1.0" + versionCode = System.getenv("VERSION_CODE")?.toIntOrNull() ?: 1 + versionName = System.getenv("VERSION_NAME") ?: "1.0" + } + + signingConfigs { + create("release") { + val keystoreFilePath = System.getenv("KEYSTORE_FILE") + if (keystoreFilePath != null) { + storeFile = file(keystoreFilePath) + storePassword = System.getenv("KEYSTORE_PASSWORD") + keyAlias = System.getenv("KEY_ALIAS") + keyPassword = System.getenv("KEY_PASSWORD") + } + } } packaging { @@ -95,6 +107,12 @@ android { buildTypes { release { isMinifyEnabled = false + val keystoreFilePath = System.getenv("KEYSTORE_FILE") + signingConfig = if (keystoreFilePath != null) { + signingConfigs.getByName("release") + } else { + signingConfigs.getByName("debug") + } } } diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8b782fb..113429f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -12,8 +12,14 @@ platform :android do project_dir: "./" ) end - + lane :release do + # Builds the APK used for the GitHub Release + gradle( + task: "composeApp:assembleRelease", + project_dir: "./" + ) + # Builds the Android App Bundle (AAB) used for the Play Store gradle( task: "composeApp:bundleRelease", project_dir: "./" @@ -21,47 +27,37 @@ platform :android do end lane :deploy do + # Uploads the generated AAB to Google Play Console + upload_to_play_store( + track: 'production', # ['internal', 'production', 'beta'] + aab: 'composeApp/build/outputs/bundle/release/composeApp-release.aab', + json_key_data: ENV['PLAY_STORE_JSON_KEY_DATA'] + ) end - end platform :ios do + lane :build do gradle( task: "composeApp:linkDebugFrameworkIosArm64", project_dir: "./" ) - end - lane :ios_release do - gradle( - task: "composeApp:linkReleaseFrameworkIosArm64", - project_dir: "./" - ) - build_app( - project: './iosApp/iosApp.xcodeproj', - scheme: "iosApp", - configuration: "Release", - destination: "generic/platform=iOS" - ) - - end - - lane :release do - gradle( - task: "composeApp:linkReleaseFrameworkIosArm64", - project_dir: "./" - ) - - build_app( - project: './iosApp/iosApp.xcodeproj', - scheme: 'iosApp', - configuration: 'Release', - destination: 'generic/platform=iOS', - allowProvisioningUpdates: true - ) - end + lane :release do + gradle( + task: "composeApp:linkReleaseFrameworkIosArm64", + project_dir: "./" + ) + build_app( + project: "./iosApp/iosApp.xcodeproj", + scheme: "iosApp", + configuration: "Release", + destination: "generic/platform=iOS", + allowProvisioningUpdates: true + ) + end end diff --git a/release.config.js b/release.config.js index ef02b14..6ae4eb4 100644 --- a/release.config.js +++ b/release.config.js @@ -2,10 +2,8 @@ var prepareCmd = ` echo version=\${nextRelease.version} > gradle.properties echo VERSION="\${nextRelease.version}" > .env echo PROJECT_NAME=$(grep -Po 'rootProject\\s*\\.\\s*name\\s*=\\s*"\\K[\\w-]+(?=")' settings.gradle.kts) >> .env -docker compose build ` var publishCmd = ` -docker compose push git add gradle.properties .env git commit -m "chore(release): update gradle.properties .env versions to \${nextRelease.version} [skip ci]" git push @@ -18,9 +16,9 @@ config.plugins.push( }], ["@semantic-release/github", { "assets": [ - { "path": "charts.tar.zst" }, + { "path": "composeApp/build/outputs/apk/release/*.apk", "label": "Android Release APK" } ] }], "@semantic-release/git", ) -module.exports = config \ No newline at end of file +module.exports = config