diff --git a/.github/workflows/dummy_bundle.yml b/.github/workflows/dummy_bundle_and_apk.yml similarity index 51% rename from .github/workflows/dummy_bundle.yml rename to .github/workflows/dummy_bundle_and_apk.yml index bd946537c..00736d16c 100644 --- a/.github/workflows/dummy_bundle.yml +++ b/.github/workflows/dummy_bundle_and_apk.yml @@ -1,13 +1,13 @@ -name: Generate dummy bundle +name: Generate dummy bundle and APK -# The workflow will trigger when the `dummy_bundle` tag is pushed. +# This workflow will trigger when the 'dummy_bundle_and_apk' is pushed. on: push: tags: - - 'dummy_bundle' # dummy_bundle Tag + - 'dummy_bundle_and_apk' # dummy_bundle_and_apk Tag. jobs: - publish_dummy_bundle: + publish_dummy_bundle_and_apk: runs-on: ubuntu-22.04 steps: @@ -24,23 +24,33 @@ jobs: KEYSTORE: ${{ secrets.keystore }} run: | echo "$KEYSTORE" | base64 -d > kiwix-android.keystore + + - name: Retrieve date from git revision + id: git_head_revision_date + run: | + DATE=$(git log -1 --format=%cd --date=format:%Y-%m-%d) + echo "KIWIX_ANDROID_RELEASE_DATE=$DATE" >> $GITHUB_ENV + shell: bash - - name: Generate dummy Bundle + - name: Generate dummy Bundle and APKs env: KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} + KIWIX_ANDROID_RELEASE_DATE: ${{ env.KIWIX_ANDROID_RELEASE_DATE }} run: | - ./gradlew bundlePlayStore --scan + ./gradlew bundlePlayStore assembleRelease --scan - - name: Get Bundle name and path - id: bundle-path + - name: Get Bundle and APKs name and path + id: get-bundle-and-apk-paths run: | BUNDLE_PATH="app/build/outputs/bundle/playStore/kiwix-playStore.aab" BUNDLE_NAME="PlayStoreDummyBundle.aab" echo "bundle_path=$BUNDLE_PATH" >> $GITHUB_ENV echo "bundle_name=$BUNDLE_NAME" >> $GITHUB_ENV + APK_DIR="app/build/outputs/apk/release/" + echo "apk_dir=$APK_DIR" >> $GITHUB_ENV - name: Upload Bundle as an artifact uses: actions/upload-artifact@v4 @@ -48,3 +58,9 @@ jobs: name: ${{ env.bundle_name }} path: ${{ env.bundle_path }} + - name: Upload All Release APKs as artifacts + uses: actions/upload-artifact@v4 + with: + name: ReleaseApks + path: ${{ env.apk_dir }}*.apk + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c0c2e8304..342e9b7dd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,13 @@ jobs: - name: Set tag variable run: echo "TAG=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV + - name: Retrieve date from git revision + id: git_head_revision_date + run: | + DATE=$(git log -1 --format=%cd --date=format:%Y-%m-%d) + echo "KIWIX_ANDROID_RELEASE_DATE=$DATE" >> $GITHUB_ENV + shell: bash + - name: Retrieve secrets to files env: KEYSTORE: ${{ secrets.keystore }} @@ -37,6 +44,7 @@ jobs: KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} UNIVERSAL_RELEASE_APK: app/build/outputs/apk/standalone/*universal*.apk ARCHIVE_NAME: kiwix-${{ github.event.release.tag_name }}.apk + KIWIX_ANDROID_RELEASE_DATE: ${{ env.KIWIX_ANDROID_RELEASE_DATE }} run: | ./gradlew assembleStandalone cp ${UNIVERSAL_RELEASE_APK} ${ARCHIVE_NAME} @@ -64,6 +72,7 @@ jobs: KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} PLAYSTORE_JSON: ${{ secrets.PLAYSTORE_JSON }} + KIWIX_ANDROID_RELEASE_DATE: ${{ env.KIWIX_ANDROID_RELEASE_DATE }} run: | echo "$PLAYSTORE_JSON" > playstore.json ./gradlew publishPlayStoreBundle --scan diff --git a/.github/workflows/testing_release.yml b/.github/workflows/testing_release.yml index 393370a4a..d9a8362cb 100644 --- a/.github/workflows/testing_release.yml +++ b/.github/workflows/testing_release.yml @@ -1,6 +1,7 @@ name: Publish App to Play Store -# Trigger the workflow on a schedule (every Monday at 12:00 UTC) +# This workflow is triggered on a schedule or when specific tags are pushed. +# It runs every Monday at 12:00 UTC and also when the 'internal_testing' tag is pushed. on: schedule: - cron: '0 12 * * 1' # Runs every Monday at 12:00 @@ -29,10 +30,30 @@ jobs: echo "$KEYSTORE" | base64 -d > kiwix-android.keystore echo "$PLAYSTORE_JSON" > playstore.json + - name: Retrieve date from git revision + id: git_head_revision_date + run: | + DATE=$(git log -1 --format=%cd --date=format:%Y-%m-%d) + echo "KIWIX_ANDROID_RELEASE_DATE=$DATE" >> $GITHUB_ENV + shell: bash + - name: Publish bundle in internal testing on Google Play env: KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} + KIWIX_ANDROID_RELEASE_DATE: ${{ env.KIWIX_ANDROID_RELEASE_DATE }} run: | - ./gradlew publishPlayStoreBundle --scan + OUTPUT=$(./gradlew publishPlayStoreBundle --scan 2>&1) + echo "$OUTPUT" > gradle_output.log + if echo "$OUTPUT" | grep -q "BUILD SUCCESSFUL"; then + echo "$OUTPUT" + exit 0 + fi + + if echo "$OUTPUT" | grep -q "Try another version code."; then + echo "Upload skipped because very same version. $OUTPUT" + exit 0 + fi + echo "$OUTPUT" + exit 1 diff --git a/README.md b/README.md index de89d170c..c88da6ac7 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,13 @@ want to build the `app` module in the `debug` configuration. If you are interested in our custom apps, they have their own repo [kiwix-android-custom](https://github.com/kiwix/kiwix-android-custom). +## Release + +We have an [automatic version code generation](https://github.com/kiwix/kiwix-android/blob/main/buildSrc/src/main/kotlin/VersionCodeGenerator.kt) system based on the current date. However, you +can override this by setting the environment variable `KIWIX_ANDROID_RELEASE_DATE` to a specific +date in the `YYYY-MM-DD` format. This will use the provided date for the version code calculation +instead of the current date. + ## Libraries Used - [Libkiwix](https://github.com/kiwix/java-libkiwix) - Kotlin/Java binding for the core Kiwix diff --git a/buildSrc/src/main/kotlin/VersionCodeGenerator.kt b/buildSrc/src/main/kotlin/VersionCodeGenerator.kt index 269b31198..a61cf3e1e 100644 --- a/buildSrc/src/main/kotlin/VersionCodeGenerator.kt +++ b/buildSrc/src/main/kotlin/VersionCodeGenerator.kt @@ -1,6 +1,3 @@ -import java.time.LocalDate -import java.time.temporal.ChronoUnit - /* * Kiwix Android * Copyright (c) 2024 Kiwix @@ -19,20 +16,41 @@ import java.time.temporal.ChronoUnit * */ +import java.time.LocalDate +import java.time.temporal.ChronoUnit + +/** + * The date when the automatic version code generation started. + */ +const val LAST_DATE = "2024-07-17" + +/** + * Base version code. This is the version code of the last release uploaded to the Play Store. + * We use this as the starting point for generating new version codes automatically. + */ +const val BASE_VERSION_CODE = 231101 + fun String.getVersionCode(): Int { - // the date when the automatic version code generation started - val lastDate = LocalDate.of(2024, 7, 17) - - // Calculate the number of days between the lastDate and today's date. + // Get the current date. If the "KIWIX_ANDROID_RELEASE_DATE" environment + // variable is set(in YYYY-MM-DD format). + // It uses the specified date to generate the APK version code. + // Otherwise, it generates the version code based on the current date. + // See https://github.com/kiwix/kiwix-android/issues/4120 for more details. + val currentDate = if (!System.getenv("KIWIX_ANDROID_RELEASE_DATE").isNullOrEmpty()) { + LocalDate.parse(System.getenv("KIWIX_ANDROID_RELEASE_DATE")).also { + println("Environment variable found. Using date: $it for version code generation.") + } + } else { + LocalDate.now().also { + println("No environment variable found. Using current date: $it for version code generation.") + } + } + // Calculate the number of days between the LAST_DATE and today's date. // This gives us the total number of days since the last version code was set. - val daysDifference = ChronoUnit.DAYS.between(lastDate, LocalDate.now()).toInt() - - // Base version code. This is the version code of the last release uploaded to the Play Store. - // We use this as the starting point for generating new version codes automatically. - val baseVersionCode = 231101 + val daysDifference = ChronoUnit.DAYS.between(LocalDate.parse(LAST_DATE), currentDate).toInt() // Generate and return the new version code. - // The new version code is calculated by adding the number of days since lastDate + // The new version code is calculated by adding the number of days since LAST_DATE // to the base version code. This creates a unique version code for each day. - return baseVersionCode + daysDifference + return BASE_VERSION_CODE + daysDifference }