Automating Build and Release Process with Fastlane: Part 3
Moving from individual Fastlane lanes to a predictable, production-oriented Android release workflow.
In Part 1, we looked at the bigger engineering problem: a mobile release process should be predictable, repeatable, secure, and capable of running in CI/CD.
In Part 2, we installed Fastlane, initialized it inside an Android project, created our first lanes, and established the relationship between Fastlane and Gradle.
Now we are going to build the middle layer.
Instead of thinking about individual commands such as
test, assemble, or bundle,
we'll start designing a release workflow with explicit responsibilities
and predictable execution.
This part intentionally focuses on workflow design and build orchestration. Google Play deployment details belong to Part 4, screenshot automation belongs to Part 5, release versioning and changelogs belong to Part 6, and CI/CD execution belongs to Part 7.
Step 1: Start With the Release Workflow, Not the Commands
One of the easiest mistakes when introducing Fastlane is to create a lane for every command without first deciding what the release process should actually look like.
A better approach is to start with the desired engineering workflow.
1. Is the code valid?
2. Can we build the intended variant?
3. Is the resulting artifact trustworthy?
4. Is it ready for the next delivery stage?
Once those responsibilities are clear, Fastlane becomes much easier to structure.
A simple architecture might look like this:
release
|
+-- validate
|
+-- build_release
|
+-- verify_artifact
|
+-- deliver
The important idea is that the release lane expresses intent. Individual lanes perform focused operations.
Step 2: Keep Lanes Small and Composable
A Fastfile can quickly become difficult to maintain if every lane contains a large collection of unrelated commands.
Instead, each lane should have a clear responsibility.
platform :android do
desc "Run Android validation"
lane :validate do
gradle(
task: "test"
)
end
desc "Build the production release"
lane :build_release do
gradle(
task: "bundle",
flavor: "production",
build_type: "Release"
)
end
end
Now we have two focused operations:
- validate — performs release validation.
- build_release — produces the intended release artifact.
A lane should represent a meaningful engineering operation, not simply provide another name for a terminal command.
Step 3: Make the Build Variant Explicit
Real Android applications rarely have only one build configuration.
You may have product flavors such as:
- development
- staging
- production
Combined with build types, this creates different variants.
developmentDebug
developmentRelease
stagingDebug
stagingRelease
productionDebug
productionRelease
A production release workflow should not rely on someone remembering which Gradle task to execute.
The variant should be encoded explicitly in the automation:
gradle(
task: "bundle",
flavor: "production",
build_type: "Release"
)
This is much safer than asking every developer to remember the exact combination of flavor and build type.
A release workflow should make incorrect builds difficult to produce. Explicit variants reduce the chance of accidentally shipping a debug build, the wrong flavor, or an artifact configured for the wrong environment.
Step 4: Treat Signing as a Build Concern
A production Android artifact must be signed.
But this does not mean Fastlane should become the place where the Android signing model is defined.
The cleaner architecture is:
Gradle remains responsible for applying the signing configuration during the Android build.
Sensitive values should come from the environment rather than being hardcoded into the project:
android {
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE_FILE"))
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
}
Keystore passwords, private signing material, service-account credentials, and other secrets should never be committed to Git. The workflow should reference secure configuration rather than contain the secret itself.
Step 5: Validate Before You Build
One of the most important properties of a release workflow is ordering.
We don't want the pipeline to produce a release artifact and discover afterwards that the code fails its basic validation.
A dedicated validation lane gives us a clear boundary:
lane :validate do
gradle(
task: "test"
)
end
This can later grow to include additional quality gates such as lint, static analysis, or variant-specific tests.
The exact checks depend on the application. The important architectural principle is that validation happens before delivery.
Step 6: Build the Release Artifact
Once validation succeeds, the workflow can produce the release artifact.
For a production flavor, the lane might look like this:
lane :build_release do
gradle(
task: "bundle",
flavor: "production",
build_type: "Release"
)
end
The result is an Android App Bundle generated by Gradle through the Fastlane orchestration layer.
This series ultimately targets a Google Play delivery workflow. The Play Store deployment mechanics themselves are covered separately in Part 4. Here we are concerned with producing the correct release artifact.
Step 7: Verify the Artifact Before Delivery
Building successfully is not necessarily the same as producing the artifact you intended to ship.
A production-oriented workflow should have an opportunity to inspect or validate the generated artifact before it moves to the next stage.
At minimum, you may want to verify:
- The expected artifact exists.
- The expected variant was built.
- The artifact is a release build.
- The artifact was produced using the expected signing configuration.
- The artifact can be handed to the next delivery stage.
This becomes especially valuable in larger organizations where the artifact may pass through multiple systems before reaching users.
A release pipeline should not simply answer "did Gradle finish?". It should answer "did we produce the artifact we intended to deliver?"
Step 8: Compose Everything Into a Release Lane
Now we can compose the smaller operations into a higher-level workflow.
Fastlane allows one lane to call another lane:
platform :android do
desc "Run release validation"
lane :validate do
gradle(
task: "test"
)
end
desc "Build production release"
lane :build_release do
gradle(
task: "bundle",
flavor: "production",
build_type: "Release"
)
end
desc "Prepare Android release"
lane :release do
validate
build_release
end
end
Now the developer has one meaningful command:
fastlane release
This is the point where Fastlane starts behaving less like a command runner and more like a release orchestration layer.
Step 9: Design for Failure
Reliable automation is not about assuming that everything succeeds.
It is about making failure predictable and understandable.
Consider this workflow:
Validation fails
Stop the workflow. Do not produce or deliver the release artifact.
Build fails
Stop the workflow. Investigate the build failure.
Artifact verification fails
Stop the workflow. Do not pass the artifact to delivery.
This creates a very important property: failure in an earlier stage prevents unsafe progression to a later stage.
In other words, the workflow itself encodes the release policy.
Step 10: Keep Delivery as a Separate Boundary
At this point we have a validated release artifact.
Should the same lane immediately publish it?
Not necessarily.
In a production environment, organizations often introduce additional controls between artifact creation and artifact distribution.
This separation becomes particularly important when you introduce testing tracks, approvals, release gates, and automated deployment.
We'll explore the Google Play side of this boundary in much more detail in Part 4.
The Responsibility Model
At this point, it is worth stepping back and defining what each tool is actually responsible for.
Gradle
Compiles, tests, packages and signs the Android application according to the project's build configuration.
Fastlane
Orchestrates the sequence of release operations and exposes meaningful workflows through lanes.
CI/CD
Provides the execution environment, triggers, credentials and automation around the release workflow.
Fastlane should coordinate the release process without becoming a second Android build system. Gradle remains the source of truth for how the application is built.
What We Have Built
We started with individual operations and composed them into a workflow with explicit responsibilities.
Before
Developer remembers which Gradle commands to run, which variant to build, when to test, and what artifact to deliver.
After
The release workflow defines the sequence and delegates the actual Android build work to Gradle.
Developer
|
v
Fastlane release
|
+---- Validate
|
+---- Build
|
+---- Verify
|
v
Release Artifact
|
v
Next Delivery Stage
Wrapping Up
In this part, we moved beyond simply learning Fastlane commands.
We designed a release workflow around explicit stages: validation, build, signing, artifact verification, and delivery.
More importantly, we established boundaries between the tools involved.
Fastlane orchestrates the release.
CI/CD executes the system.
That distinction becomes increasingly important as the release process grows more sophisticated.
We now have a release artifact and a workflow capable of producing it predictably.
The next question is: how do we move that artifact into Google Play in a controlled way?
LinkedIn: Connect with me on LinkedIn
Email: vikasacsoni9211@gmail.com
📚 Fastlane Android Series
- Fastlane for Android: Designing a Reliable Release Automation System — Part 1
- Setting Up Fastlane in an Android Project — Part 2
- From Fastlane Commands to a Production-Ready Android Release Workflow — Part 3 — You are here.
- Play Store Uploads with Fastlane Supply — Part 4
- Automating Android Screenshots with Fastlane Screengrab — Part 5
- Managing Android App Versioning and Changelogs with Fastlane — Part 6
- Integrating Fastlane with CI/CD Pipelines — Part 7
From Fastlane commands to a production-ready release workflow.
Comments
Post a Comment