Managing Android App Versioning and Changelogs with Fastlane: Part 6

Managing Android App Versioning and Changelogs with Fastlane

Automate release metadata, connect versions to Git history, and make Android releases traceable and repeatable.

In this part We'll look at Android versioning as a release-engineering problem, automate version code management, define version names deliberately, generate changelogs from Git history, and connect release metadata to the Fastlane deployment workflow.

In Part 5, we automated Android screenshot generation with Screengrab.

Now we are going one level deeper into the release process.

Every Android release carries metadata with it.

At minimum, we need to answer three questions:

  • Which release is this?
  • What changed?
  • Which source code produced this release?

If these answers depend on someone manually editing Gradle files, writing release notes and remembering what changed since the previous release, the release process is fragile.

Fastlane gives us a way to turn much of this release knowledge into repeatable automation.

Git Release Version Version Code Changelog Build Google Play

Step 1: Understand Android Release Versioning

Android releases commonly involve two different version values: versionCode and versionName.

versionCode

The versionCode is an internal, machine-oriented release identifier. For releases distributed through Google Play, each new release needs a higher version code than the previous release.

versionCode 101
versionCode 102
versionCode 103

versionName

The versionName is the human-readable release identifier presented to users.

1.0.0
1.1.0
1.1.1
2.0.0
Don't treat them as the same thing

The version code answers "which build is newer?". The version name answers "which release are we talking about?". A production release process should manage both deliberately.

Step 2: Automate Version Code Management

Version codes are excellent candidates for automation because they follow a simple machine-oriented rule: each release must have a unique, increasing value.

Fastlane provides the increment_version_code action for this purpose.

platform :android do

  lane :prepare_version do

    increment_version_code

  end

end

This removes the need for a developer to manually edit the version code every time a release is prepared.

But where should the version code come from?

That depends on your release architecture. A local workflow might increment it in the project. A CI/CD pipeline may derive it from the build number, Git metadata or another centrally controlled release counter.

Step 3: Define the Version Name Deliberately

Version names are different.

They communicate product releases to humans, so blindly incrementing them is usually not the best release strategy.

Instead, many teams use a deliberate versioning strategy such as:

1.4.0
1.4.1
1.5.0
2.0.0

If your project follows Semantic Versioning, the version name can also communicate the nature of the release:

  • Major — potentially breaking changes.
  • Minor — new backward-compatible functionality.
  • Patch — backward-compatible fixes.

The important point is that the release version should represent a product decision, not simply whatever number happens to be generated by a script.

A better production model

Let the release process decide which version is being shipped, while automation takes care of applying that version consistently across the build and deployment process.

Step 4: Connect Releases to Git Tags

If we want our releases to be traceable, Git should become part of the versioning story.

For example, we might create tags such as:

v1.0.0
v1.1.0
v1.1.1
v2.0.0

Now a release version can be associated with an exact point in the source code history.

Release traceability

A strong release pipeline should allow you to move backward from a production artifact to its version, Git commit and source code.

Step 5: Generate Changelogs from Git History

A version tells us which release we are shipping.

The changelog tells users what changed.

Fastlane provides the changelog_from_git_commits action, which can generate changelog text from Git history.

changelog = changelog_from_git_commits(
  path: "."
)

puts changelog

If your Git history contains meaningful commit messages such as:

feat: add dark mode
fix: resolve login crash
perf: improve image loading
docs: update onboarding guide

Fastlane can turn that history into release-note input.

Garbage in, garbage out

Automated changelogs do not magically create good release notes. If commit messages are vague, the generated changelog will be vague too.

Step 6: Generate Changes Since the Previous Release

Generating the entire Git history is rarely useful.

For a release, we usually care about the changes introduced after the previous release tag.

changelog = changelog_from_git_commits(
  path: ".",
  between: ["v1.0.0", "v1.1.0"]
)

This gives the release process a clear boundary:

v1.0.0 Commits v1.1.0

The changelog now represents the changes between two known release points, rather than an arbitrary collection of commits.

Step 7: Combine Versioning and Changelog Generation

Now we can bring these pieces together into a release-preparation lane.

platform :android do

  desc "Prepare Android release"

  lane :prepare_release do

    increment_version_code

    changelog = changelog_from_git_commits(
      path: "."
    )

    puts "Release Changelog:"
    puts changelog

  end

end

Notice that we have deliberately separated the responsibilities.

  • The version code is machine-managed.
  • The version name represents the product release.
  • The Git history provides the source for release notes.
  • The release lane orchestrates the process.

Step 8: Connect Release Metadata to the Build

The next step is connecting our metadata to the actual Android artifact.

A simplified release lane might look like this:

platform :android do

  desc "Build Android release"

  lane :release do

    increment_version_code

    changelog = changelog_from_git_commits(
      path: "."
    )

    gradle(
      task: "bundle",
      build_type: "Release"
    )

    puts changelog

  end

end

We now have a single workflow that understands both the source history and the artifact being produced.

This is where automation becomes valuable

We are no longer automating isolated commands. We are encoding the relationship between source code, release metadata and the build artifact.

Step 9: Connect the Changelog to Google Play

Once the changelog has been generated, it can be passed into the Google Play deployment workflow.

platform :android do

  desc "Build and deploy Android release"

  lane :release do

    increment_version_code

    changelog = changelog_from_git_commits(
      path: "."
    )

    gradle(
      task: "bundle",
      build_type: "Release"
    )

    upload_to_play_store(
      changelog: changelog
    )

  end

end

The exact deployment configuration depends on your Google Play setup, product flavors and CI/CD architecture.

But conceptually, the pipeline has now become:

Git
Release Metadata
Changelog
Gradle Build
Google Play
Security reminder

Google Play credentials should never be committed to the repository. In CI/CD, use encrypted secrets or your platform's secure credential mechanism.

Step 10: Make the Release Traceable

This is the part that separates a basic automation script from a mature release workflow.

Ideally, we should be able to answer:

  • Which Git commit produced this release?
  • Which version name was released?
  • Which version code was uploaded?
  • Which changelog was generated?
  • Which artifact was built?

This creates a chain of traceability:

Git Commit
Git Tag / Release Version
Version Code
Android Artifact
Google Play Release

When something goes wrong in production, this traceability becomes extremely valuable for debugging, rollback decisions and release audits.

Release Versioning Best Practices

  • Keep versioning predictable. Decide how major, minor and patch releases are represented.
  • Automate version codes. Avoid relying on developers to remember to increment them manually.
  • Use Git tags. Tags create explicit boundaries between releases.
  • Write meaningful commit messages. Automated changelogs depend on useful source history.
  • Keep release metadata traceable. Every artifact should be connected to its source and release version.
  • Separate product decisions from automation. Automation should execute the release strategy, not invent one.

The Complete Release Flow

We can now visualize the complete release process:

Developer / Release Trigger
Git Tag / Version
Fastlane
Version Code
Generate Changelog
Gradle Build
Google Play

What Have We Built?

Across the previous parts, we have gradually moved from individual Fastlane commands toward a release system.

Before:

Developer manually updates versions, prepares release notes, builds the application and uploads the release.

After:

Fastlane can orchestrate version management, changelog generation, building and deployment as a repeatable release workflow.

The bigger engineering lesson

Release automation is not primarily about reducing the number of commands a developer types. It is about creating a reliable system where release decisions, source code, artifacts and deployment metadata remain connected.

Wrapping Up

Versioning and changelog management may look like small release tasks.

But once an Android application starts releasing frequently, these small tasks become part of the delivery system.

With Fastlane, we can automate version-code management, generate changelogs from Git history, connect release metadata to builds and eventually push the complete release through Google Play.

More importantly, we have established a foundation for the next step: moving this workflow away from a developer's laptop and into CI/CD.

Coming Next — Part 7 In the next part, we'll take everything we have built so far and connect Fastlane to a real CI/CD pipeline — turning our local release automation into an automated mobile delivery system.
Fastlane for Android — Part 6
Release versioning, changelogs and traceable mobile delivery.

Comments

Featured Articles

🗂️ Heap Dumping Explained - LeakCanary's Bold Move

Building a Production-Ready Kotlin Multiplatform Platform Kit: Lessons from My BlrKotlin x InMobi Talk

🦈 Shark Heap Analysis - LeakCanary's Detective at Work

Android Device Security: Sandboxing, Rooting, and Attestation Explained

JIT vs AOT Compilation | Android Runtime