App Versioning Gradle Plugin

repository·main·Indexed 42 days ago

https://github.com/reactivecircus/app-versioning

A Gradle plugin for Android applications that automates versionCode and versionName generation using Git tags and SemVer. It supports custom versioning logic via overrideVersionCode and overrideVersionName, CI environment variable integration, and build variant-specific configurations. Compatible with AGP 4.0 through 8.x.

Tokens
3.1K
Snippets
10
Records
18
Agent score
4%

What's inside App Versioning

  1. Default versioning behavior

    main

    By default, the plugin fetches the latest Git tag and parses it as a SemVer string.

    • versionCode: Computed using positional notation: MAJOR * 10000 + MINOR * 100 + PATCH. For example, tag 1.3.1 results in 10301.
    • versionName: The versionName defaults to the exact name of the latest Git tag.
  2. Understand App Versioning Gradle tasks

    main

    The plugin provides two Gradle tasks for every build variant:

    1. generateAppVersionInfoFor<BuildVariant>: Generates the versionCode and versionName for the specified variant. This task is automatically triggered during assemble<BuildVariant> or bundle<BuildVariant> and injects the values into the merged AndroidManifest.
    2. printAppVersionInfoFor<BuildVariant>: Prints the generated versionCode and versionName to the console for debugging purposes.
  3. Retrieve generated version code and version name from build outputs

    main

    The plugin writes the generated version information to text files in the build output directory. You can read these files in a CI pipeline to use the values in subsequent steps (like uploading to the Play Store).

    File Paths:

    • app/build/outputs/app_versioning/<buildVariant>/version_code.txt
    • app/build/outputs/app_versioning/<buildVariant>/version_name.txt

    Usage Example (Shell):

    VERSION_CODE=$(cat app/build/outputs/app_versioning/<buildVariant>/version_code.txt)
    VERSION_NAME=$(cat app/build/outputs/app_versioning/<buildVariant>/version_name.txt)

    Note: If you need these values in a different VM than the one that performed the build, you must archive and carry over these .txt files. Re-running the generation task in a different VM might result in different values (e.g., if using Epoch timestamps).

  4. Install the App Versioning Gradle Plugin

    main

    To use the plugin, first ensure mavenCentral() is added to your plugin repositories in settings.gradle.kts or the root build.gradle.kts. Then, apply the plugin to your Android Application module.

    Note on Compatibility:

    • AGP 8.x: Use plugin version 1.6.0 (final).
    • AGP 7.x and below: Use plugin version 1.4.0 (final).
    • AGP 4.2: Use plugin version 0.10.0 (final).
    • AGP 4.0 and 4.1: Use plugin version 0.4.0 (final).
    // in settings.gradle.kts
    pluginManagement {
        repositories {
            mavenCentral()
        }
    }
    
    // or in root build.gradle.kts
    buildscript {
        repositories {
            mavenCentral()
        }
    }
    
    // Apply to your app module
    plugins {
        id("com.android.application")
        id("io.github.reactivecircus.app-versioning") version "x.y.z"
    }
  5. Setup app-versioning on CI (GitHub Actions)

    main

    Most CI providers perform a shallow clone by default, which excludes Git tags. To ensure app-versioning can resolve versions from tags, you must set fetch-depth: 0 in your checkout step.

    - uses: actions/checkout@v5
      with:
        fetch-depth: 0
  6. Configure the plugin for Release builds only

    main

    To prevent the plugin from generating version information for debug builds, set releaseBuildOnly to true. This is useful for reducing overhead in non-release environments.

    When releaseBuildOnly is true, the plugin only provides tasks for the release variant (e.g., generateAppVersionInfoForRelease).

    appVersioning {
        /**
         * Whether to only generate version name and version code for `release` builds.
         *
         * Default is `false`.
         */
        releaseBuildOnly.set(true)
    }
  7. Disable the app-versioning plugin

    main

    To disable the plugin and fall back to the versionCode and versionName defined in your defaultConfig block, set enabled to false in the appVersioning configuration block.

    appVersioning {
        /**
         * Whether to enable the plugin.
         *
         * Default is `true`.
         */
        enabled.set(false)
    }
  8. Filter Git tags using a glob pattern

    main

    By default, the plugin uses the latest tag in the current branch. You can restrict the plugin to use the latest tag matching a specific glob pattern using tagFilter.set(). This is useful if you have multiple apps using different tag metadata.

    Example (Kotlin)

    appVersioning {
        tagFilter.set("[0-9]*.[0-9]*.[0-9]*+app-b")
    }
  9. Configure tag fetching for local checkouts

    main

    If your local environment (e.g., a shallow clone) does not contain Git tags, you can instruct the plugin to fetch them from the remote repository by setting fetchTagsWhenNoneExistsLocally to true.

    appVersioning {
        /**
         * Whether to fetch git tags from remote when no git tag can be found locally.
         *
         * Default is `false`.
         */
        fetchTagsWhenNoneExistsLocally.set(true)
    }
  10. How app-versioning works with Android variants

    main

    The plugin automatically detects Android variants and registers tasks to generate version information. For each variant, it creates two primary tasks:

    1. Generate App Version Info: Calculates the version code and name from Git and writes them to files in build/outputs/app_versioning/{variantName}/.
    2. Print App Version Info: Prints the calculated version information to the console.

    The plugin then automatically wires the output of the generation task to the Android variant.outputs so that the versionCode and versionName are correctly set in the final APK/Bundle.

  11. Configure Git root and Bare repository paths

    main

    By default, the plugin assumes the root Gradle project is the Git root. If your .git directory is located elsewhere, use gitRootDirectory. If your .git is a symbolic link to a bare repository, use bareGitRepoDirectory (which overrides gitRootDirectory).

    appVersioning {
        /**
         * Git root directory used for fetching git tags.
         */
        gitRootDirectory.set(rootProject.file("../"))
    
        /**
         * Bare Git repository directory.
         */
        bareGitRepoDirectory.set(rootProject.file("../.repo/projects/app.git"))
    }
  12. Use the app-versioning plugin in an Android project

    main

    To use this plugin, apply it to an Android Application project. The plugin requires the com.android.application plugin to be applied. It automatically hooks into Android variants to set the versionCode and versionName based on the latest Git tag.

    plugins {
        id("com.android.application")
        id("io.github.reactivecircus.appversioning")
    }