<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jonathan Cardoso Machado</title>
    <description>The latest articles on DEV Community by Jonathan Cardoso Machado (@jonathancardoso).</description>
    <link>https://dev.to/jonathancardoso</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F89989%2F5f3bad8e-34a9-4cb2-8308-a9df7ff975c7.jpeg</url>
      <title>DEV Community: Jonathan Cardoso Machado</title>
      <link>https://dev.to/jonathancardoso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonathancardoso"/>
    <language>en</language>
    <item>
      <title>Automated Deployment of React Native Apps Using Fastlane - Part 1 - Play Store</title>
      <dc:creator>Jonathan Cardoso Machado</dc:creator>
      <pubDate>Tue, 08 Sep 2020 15:17:19 +0000</pubDate>
      <link>https://dev.to/jonathancardoso/automated-deployment-of-react-native-apps-using-fastlane-part-1-play-store-3n0g</link>
      <guid>https://dev.to/jonathancardoso/automated-deployment-of-react-native-apps-using-fastlane-part-1-play-store-3n0g</guid>
      <description>&lt;p&gt;In this article, we will learn how to deploy React Native apps to the Android Play Store using &lt;a href="https://fastlane.tools/"&gt;fastlane&lt;/a&gt;. This is the first part of a series about automated deployment of React Native apps using fastlane.&lt;/p&gt;

&lt;p&gt;Everyone that has been releasing apps manually knows how tiresome and time consuming the process is, the main idea behind this series is to, by the end of it, have full knowledge about how to automate these tasks, letting a CI/CD provider run them. Freeing developers' time and machine processing power.&lt;/p&gt;

&lt;p&gt;The first two parts will be focused on the Android Play Store, and then later we will see how to the same for the IOS App Store.&lt;/p&gt;

&lt;p&gt;Our main goal is to use specific release tracks on Play Store to give us a fast and reliable environment to test and iterate on our app, be it on the closed alpha track or the open beta track, before sending the release to production and making it available on the Play Store.&lt;/p&gt;

&lt;p&gt;Each of the three release tracks we are going to use is going to match one of the branches in our repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alpha Track → develop Branch&lt;/li&gt;
&lt;li&gt;Beta Track → staging Branch&lt;/li&gt;
&lt;li&gt;Production Track → master branch&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; while this guide is focused on React Native apps, the same steps can be taken to add fastlane to any Android App.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;To follow this guide it's needed to have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git CLI and basic git knowledge&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; and &lt;a href="https://bundler.io/"&gt;Bundler&lt;/a&gt; installed&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/studio"&gt;Android Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/"&gt;Code Editor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ruby basics are nice to have but not required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing the Project
&lt;/h2&gt;

&lt;p&gt;The first step we must take is to initialize our React Native project, the React Native docs have a really great &lt;a href="https://reactnative.dev/docs/environment-setup"&gt;Environment Setup&lt;/a&gt; section, so follow the instructions there, using the &lt;code&gt;React Native CLI Quickstart&lt;/code&gt; guide.&lt;/p&gt;

&lt;p&gt;Basically, you will need to install the dependencies and run &lt;code&gt;react-native init&lt;/code&gt;, in our case we are going to name our project &lt;code&gt;fastlane_react_native_deployment&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npx react-native init fastlane_react_native_deployment &lt;span class="nt"&gt;--version&lt;/span&gt; react-native@0.63.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4_-QlViX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oluc8s5uavpdbxa6htqk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4_-QlViX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oluc8s5uavpdbxa6htqk.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
react-native init output



&lt;p&gt;After the project is created, we must &lt;code&gt;cd&lt;/code&gt; into the created folder and initialize a local git repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;fastlane_react_native_deployment &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's commit everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"initial code"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating our Play Store Developer Account
&lt;/h2&gt;

&lt;p&gt;Next, we are going to sign up for a developer account on Play Store, this requires a one-time payment of $25 registration fee, in case you have not done so already.&lt;/p&gt;

&lt;p&gt;After you have created your account, go to the &lt;a href="https://play.google.com/apps/publish"&gt;play store console dashboard&lt;/a&gt; and click &lt;code&gt;CREATE APPLICATION&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjKio0zP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01j8ya34xp82nju53dlj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjKio0zP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01j8ya34xp82nju53dlj.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Play Store apps listing screen



&lt;p&gt;Choose the language of your app and give it a name:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fINE2JhT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/owayoy4sgvjcfuve0yoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fINE2JhT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/owayoy4sgvjcfuve0yoe.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
We will be using "Fastlane RN Deployment" as the application name



&lt;p&gt;Right now you are not required to fill in the details of your app in the &lt;code&gt;Store Listing&lt;/code&gt; section, but feel free to do so if you want to.&lt;/p&gt;

&lt;p&gt;The other step we need to do in the Play Store Console is to create a service account with API Access to our app, to do so go back to the &lt;code&gt;All applications&lt;/code&gt; listing, then in the sidebar click on &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;API Access&lt;/code&gt;, if you have never configured this on your Play Store account, you will see a screen like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iqYq0_xM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfs4xlttm4hn4e4yal1d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iqYq0_xM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfs4xlttm4hn4e4yal1d.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;CREATE NEW PROJECT&lt;/code&gt; and a new project on Google Developer Console will be automatically created and linked to your Play Store account.&lt;/p&gt;

&lt;p&gt;The screen will be updated with some new information:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XPid0m29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fxcn9nz4wrjmpdsrsw30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XPid0m29--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fxcn9nz4wrjmpdsrsw30.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Service Accounts&lt;/code&gt; section, click on &lt;code&gt;CREATE SERVICE ACCOUNT&lt;/code&gt; and a modal will appear, follow the instructions there.&lt;/p&gt;

&lt;p&gt;You can give the service account any meaningful name you want, for this tutorial we are going to use &lt;code&gt;fastlane&lt;/code&gt;. The important steps to take are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OWHD6CPb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/euuew7sdtwdpedl99g87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OWHD6CPb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/euuew7sdtwdpedl99g87.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Add the `Service Account User` role to the service account



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x2h8aYGi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vx5usd4usw78u809461o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x2h8aYGi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vx5usd4usw78u809461o.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Download the account JSON key file and keep it stored somewhere safe.



&lt;p&gt;After you complete these steps, head back to the Play Store Console page and click &lt;code&gt;Done&lt;/code&gt;, the page will reload and the newly created service account will appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wb-MwHB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y3qdom10zdeesdiz4cgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wb-MwHB_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y3qdom10zdeesdiz4cgo.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the service account click &lt;code&gt;GRANT ACCESS&lt;/code&gt;, a new modal will appear to add it as a user with access to your Play Store account, here you can choose between the &lt;code&gt;Release Manager&lt;/code&gt; and the &lt;code&gt;Project Lead&lt;/code&gt; roles.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Project Lead&lt;/code&gt; has access to all tracks but the &lt;code&gt;production&lt;/code&gt; one, while the &lt;code&gt;Release Manager&lt;/code&gt; role has access to everything. We are going to use the &lt;code&gt;Release Manager&lt;/code&gt; role. Click &lt;code&gt;ADD USER&lt;/code&gt; to finish the service account setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating our Key Store File
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: if you are following this for an app that is already published, you probably already have a key store file, so you can skip their creation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we are required to upload manually a version of our app to the Play Store, this is needed for it to identify our app package name. The first time we do that we must also create a signing key for our uploads. The process is detailed thoughtfully here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.android.com/studio/publish/app-signing"&gt;https://developer.android.com/studio/publish/app-signing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make it easier we are going to use Android Studio. Open Android Studio, then click on &lt;code&gt;Open an existing Android Studio project&lt;/code&gt; and select the&lt;code&gt;./android&lt;/code&gt; folder in our React Native project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZFI2PAYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0hflz05woeq0kw301icr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZFI2PAYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0hflz05woeq0kw301icr.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Android Studio splash screen



&lt;p&gt;Then go to &lt;code&gt;Build&lt;/code&gt; → &lt;code&gt;Generate Signed Bundle / APK&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ha2EzATw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hxms07fljh780chx8f8h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ha2EzATw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hxms07fljh780chx8f8h.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the next window select &lt;code&gt;Android App Bundle&lt;/code&gt; to use the new build format, which is smaller and faster to build than an &lt;code&gt;apk&lt;/code&gt;, then click &lt;code&gt;Next&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y6WzZ1JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4hetrococu0fcxjtwydr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y6WzZ1JL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4hetrococu0fcxjtwydr.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally, you will be required to create a new key store or to choose an existing one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Em2kzMDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/auqffn82792napnlvzvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Em2kzMDy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/auqffn82792napnlvzvc.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Generate Signed Bundle or APK dialog



&lt;p&gt;As we don't have an existing key store, let's click on &lt;code&gt;CREATE NEW...&lt;/code&gt; and a new dialog will appear:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wL8h04G8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oietopw43i9y4ag5i0vn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wL8h04G8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/oietopw43i9y4ag5i0vn.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
New key store dialog



&lt;p&gt;The &lt;code&gt;Key store path&lt;/code&gt; should be a location inside the &lt;code&gt;./android/&lt;/code&gt; folder in our project, for this tutorial we are going to use &lt;code&gt;android/keystore.jks&lt;/code&gt;. This file is going to be committed to the repository, the file itself is AES-encrypted and the keys can only be obtained if we have both passwords.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think on the key store as a Safe which contains multiple smaller boxes, and each of these boxes has their own separated secret. If you want to access the content of a box, which in our case is our upload key, you must know both the safe and box secrets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first &lt;code&gt;Password&lt;/code&gt; field is the password for the key store itself and the second one is for the key with the specified &lt;code&gt;Alias&lt;/code&gt;, which is going to be our upload key.&lt;/p&gt;

&lt;p&gt;Make sure to remember the passwords and the alias you use here, this information will be needed later. We are going to use &lt;code&gt;app-1&lt;/code&gt; as the key &lt;code&gt;Alias&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The fields on the &lt;code&gt;Certificate&lt;/code&gt; section are the info that will be used to create the key store file, you can fill then with your own/company info.&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Ok&lt;/code&gt; after you fill in the info, and it should create the key store file, the previous modal will be filled with the new info. For now, you can close this dialog and Android Studio itself, as we are done creating the key store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using our Key Store File
&lt;/h2&gt;

&lt;p&gt;Now we need to configure our project to use the signing key when building, first, let's create the .properties file to store our credentials, create the file &lt;code&gt;android/keystore.properties&lt;/code&gt; with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;storePassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;::store_password::&lt;/span&gt;
&lt;span class="py"&gt;keyPassword&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;::key_password::&lt;/span&gt;
&lt;span class="py"&gt;keyAlias&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;app-1&lt;/span&gt;
&lt;span class="py"&gt;storeFile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;keystore.jks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;storePassword&lt;/code&gt; is the password you used for the key store.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;keyPassword&lt;/code&gt; is the password you used for the key itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;keyAlias&lt;/code&gt; is the name of the key which in our case was &lt;code&gt;app-1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;storeFile&lt;/code&gt; will point to the location of our key store file, per previous steps, it's called &lt;code&gt;keystore.jks&lt;/code&gt; and is located inside the &lt;code&gt;android/&lt;/code&gt; folder, alongside the &lt;code&gt;keystore.properties&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;As we said previously, this file should not be committed to the repository, since it contains sensitive information. So make sure to also include it into your &lt;code&gt;.gitignore&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The plan now is to load that file inside our build, or if there are some environment variables with the values we need (hint: when running on CI), use them instead.&lt;/p&gt;

&lt;p&gt;Let's do that, open &lt;code&gt;android/app/build.gradle&lt;/code&gt; and add the following highlighted code above the &lt;code&gt;android {&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;enableHermes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"enableHermes"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;areUploadKeystoreEnvsSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_STORE_FILE"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_STORE_PASSWORD"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_KEY_ALIAS"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
                                &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYAPPP_RELEASE_KEY_PASSWORD"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;

&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"keystore.properties"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keystorePropertiesFileExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Properties&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!(&lt;/span&gt;&lt;span class="n"&gt;keystorePropertiesFileExists&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;areUploadKeystoreEnvsSet&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidUserDataException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'''&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="nc"&gt;You&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;keystore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;properties&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;rn&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;environments&lt;/span&gt; &lt;span class="nl"&gt;variables:&lt;/span&gt;
  &lt;span class="no"&gt;MYRNAPP_RELEASE_STORE_FILE&lt;/span&gt;
  &lt;span class="no"&gt;MYRNAPP_RELEASE_STORE_PASSWORD&lt;/span&gt;
  &lt;span class="no"&gt;MYRNAPP_RELEASE_KEY_ALIAS&lt;/span&gt;
  &lt;span class="no"&gt;MYRNAPP_RELEASE_KEY_PASSWORD&lt;/span&gt;
&lt;span class="sc"&gt;'''&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;keystorePropertiesFileExists&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;load&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FileInputStream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keystorePropertiesFile&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will load our properties file inside the &lt;code&gt;keystoreProperties&lt;/code&gt; variable. If the &lt;code&gt;android/keystore.properties&lt;/code&gt; file does not exists and the environment variables are not set, an error will be thrown.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may have noted that the environment variables have a common prefix, &lt;code&gt;MYRNAPP_RELEASE_&lt;/code&gt;, you can change this to anything that would make more sense for your project.&lt;br&gt;&lt;br&gt;
The idea of having a prefix is to avoid collisions when you are setting these environment variables for multiple apps on the settings of your CI/CD provider.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Inside the same file, &lt;code&gt;android/app/build.gradle&lt;/code&gt;, look for the &lt;code&gt;signingConfigs&lt;/code&gt; block. It should be around line 165 and look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="n"&gt;signingConfigs&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;storeFile&lt;/span&gt; &lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;keystore&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;storePassword&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
            &lt;span class="n"&gt;keyAlias&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;androiddebugkey&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
            &lt;span class="n"&gt;keyPassword&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Right now it only has a config for the &lt;code&gt;debug&lt;/code&gt; version, we need to add a new block there for the &lt;code&gt;release&lt;/code&gt; version, which is the one submitted to the store.&lt;/p&gt;

&lt;p&gt;Add the following inside the &lt;code&gt;signingConfigs&lt;/code&gt; block, right below the &lt;code&gt;debug&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;areUploadKeystoreEnvsSet&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;storeFile&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_STORE_FILE"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
                &lt;span class="n"&gt;storePassword&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_STORE_PASSWORD"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;keyAlias&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_KEY_ALIAS"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="n"&gt;keyPassword&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MYRNAPP_RELEASE_KEY_PASSWORD"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;storeFile&lt;/span&gt; &lt;span class="n"&gt;rootProject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;storeFile&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
                &lt;span class="n"&gt;storePassword&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;storePassword&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;keyAlias&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;keyAlias&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
                &lt;span class="n"&gt;keyPassword&lt;/span&gt; &lt;span class="n"&gt;keystoreProperties&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;keyPassword&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will check if the environment variables were set, if they were, it will try to load the settings using their values, if they were not (the else clause) it will load the values from the properties file.&lt;/p&gt;

&lt;p&gt;With the release's signing config created we need to use it. In the same file search for the release build type, it should be right below the &lt;code&gt;signingConfig&lt;/code&gt; block, inside a &lt;code&gt;buildTypes&lt;/code&gt; block. It looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="n"&gt;release&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Caution! In production, you need to generate your own keystore file.&lt;/span&gt;
            &lt;span class="c1"&gt;// see https://reactnative.dev/docs/signed-apk-android.&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;
            &lt;span class="n"&gt;minifyEnabled&lt;/span&gt; &lt;span class="n"&gt;enableProguardInReleaseBuilds&lt;/span&gt;
            &lt;span class="n"&gt;proguardFiles&lt;/span&gt; &lt;span class="nf"&gt;getDefaultProguardFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"proguard-android.txt"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"proguard-rules.pro"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We need to change the &lt;code&gt;signingConfig&lt;/code&gt; field in the &lt;code&gt;release&lt;/code&gt; block to use &lt;code&gt;signingConfigs.release&lt;/code&gt; instead of the debug one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight java"&gt;&lt;code&gt;            &lt;span class="c1"&gt;// ...&lt;/span&gt;
            &lt;span class="n"&gt;signingConfig&lt;/span&gt; &lt;span class="n"&gt;signingConfigs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;release&lt;/span&gt;
            &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The next step is to generate our AAB (&lt;a href="https://developer.android.com/guide/app-bundle"&gt;Android App Bundle&lt;/a&gt;) binary. This is as easy as running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;android
./gradlew bundleRelease
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After the command execution the built &lt;code&gt;app-release.aab&lt;/code&gt; file will be available at &lt;code&gt;android/app/release/app-release.aab&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This file should not be committed to the repository, so add the following to &lt;code&gt;.gitignore&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;android/app/*/*.aab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's commit everything we have done so far:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"android release signing"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Uploading our First App Bundle to Play Store
&lt;/h2&gt;

&lt;p&gt;Now it's time to create the Alpha closed track in the Play Store Console. Go back to the Play Store Console applications listing and click on &lt;code&gt;App releases&lt;/code&gt; in the sidebar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F9mPlzY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k6v4j4ntzlyh51nnc7v4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F9mPlzY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k6v4j4ntzlyh51nnc7v4.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to &lt;code&gt;Closed track&lt;/code&gt;, and click &lt;code&gt;MANAGE&lt;/code&gt; on the &lt;code&gt;Alpha&lt;/code&gt; track, in the next screen click &lt;code&gt;CREATE RELEASE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7pFg7wTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yormn7xcwgkn0d3oo4ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7pFg7wTV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yormn7xcwgkn0d3oo4ck.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;CONTINUE&lt;/code&gt; to let Google manage and protect the app signing key. Then in the next section, we will need to upload the &lt;code&gt;app-release.aab&lt;/code&gt; file we just built.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VBNX4Gn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cknzyfhfl0k0tgmiyzap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VBNX4Gn7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cknzyfhfl0k0tgmiyzap.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the upload is done processing, verify if the &lt;code&gt;Release name&lt;/code&gt; is correct, add a changelog entry if needed, and click &lt;code&gt;Save&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You are probably going to see a warning that will not let you start the roll-out of the alpha release, related to the fact that there are no internal testers on the Alpha track. You can take this opportunity to include the testers, go back to the &lt;code&gt;App releases&lt;/code&gt; page and click on &lt;code&gt;MANAGE&lt;/code&gt; in the Alpha track.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oc0j3BOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5grtkon3re6zkwyzz5pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oc0j3BOL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5grtkon3re6zkwyzz5pv.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;Manage testers&lt;/code&gt; section and include any e-mails you need. After this is complete, press &lt;code&gt;EDIT RELEASE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Everything should be filled with the same data than before, press &lt;code&gt;REVIEW&lt;/code&gt;, and the &lt;code&gt;START ROLLOUT TO ALPHA&lt;/code&gt; button should be available, click on it to finish the first alpha release.&lt;/p&gt;

&lt;p&gt;If you are doing this for a new app, the only important task remaining is to make sure the following checkmarks are green, if the app is already available in the Play Store, this step is not necessary as it was done the first time the app was uploaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R422KBqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v3anz0b3sjupk15sq8r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R422KBqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v3anz0b3sjupk15sq8r9.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Click on each section and follow the instructions.



&lt;p&gt;We are finally done with the Play Store Console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initializing Fastlane
&lt;/h2&gt;

&lt;p&gt;Now we are going to set up &lt;a href="https://fastlane.tools/"&gt;fastlane&lt;/a&gt;, the tool we will use to do the heavy lifting for us when deploying to the play store.&lt;/p&gt;

&lt;p&gt;The first step is to initialize the Ruby &lt;a href="https://bundler.io/"&gt;bundler&lt;/a&gt; on our android folder and to add fastlane as a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ./android
bundle init
bundle &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--path&lt;/span&gt; vendor/bundle
bundle add fastlane
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: If for some reason the last command results in an error, it's probably because you don't have development tools installed on your OS. For &lt;code&gt;macOS&lt;/code&gt; this means running &lt;code&gt;xcode-select --install&lt;/code&gt;. On Windows the Ruby installer will take care of installing the required packages. And on most *nix variants it's needed to install the &lt;code&gt;-dev&lt;/code&gt; variant of the ruby package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add &lt;code&gt;android/vendor&lt;/code&gt; and &lt;code&gt;android/.bundle&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt;, as we don't want to commit this folder to the repository.&lt;/p&gt;

&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;fastlane init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--paGTnggp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y9p8kr36hzwxwi68lu6d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--paGTnggp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y9p8kr36hzwxwi68lu6d.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
fastlane init output



&lt;p&gt;You will be asked for some information related to your app. The first information is the package name, this is the app identifier you are using. For Android, this means the value of the field &lt;code&gt;android.defaultConfig.applicationId&lt;/code&gt; in the &lt;code&gt;android/app/build.gradle&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The second information is the path to the service account JSON we saved previously.&lt;/p&gt;

&lt;p&gt;Finally, the third question will ask us if we want to download the existing metadata from the Play Store and setup metadata management, we will answer &lt;code&gt;y&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;After this step, there will be a new folder called &lt;code&gt;fastlane&lt;/code&gt; inside the &lt;code&gt;android&lt;/code&gt; folder, open this folder and you will find the fastlane files. The most important one here is the &lt;code&gt;Fastfile&lt;/code&gt;, which contains our lanes: some common tasks we can run from the CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Android Versioning
&lt;/h2&gt;

&lt;p&gt;One of the main aspects of having an automated deployment process for mobile applications is to automatically increment their build numbers for each subsequent build. This is, in fact, a requirement to upload new bundles to the Play Store: you cannot upload a new version that has the same, or smaller, build number than the latest one uploaded. If we try to do so an error will be thrown:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[!] Google Api Error:&lt;/strong&gt; apkNotificationMessageKeyUpgradeVersionConflict: APK specifies a version code that has already been used. - APK specifies a version code that has already been used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Currently, fastlane does not provide an action to increment the Android version as it does for IOS, fortunately, there are other ways to do that, and one of them is using a fastlane plugin. One was specifically written for this tutorial: &lt;a href="https://github.com/JCMais/fastlane-plugin-android_version_manager"&gt;android_version_manager&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's add that plugin to our project, go to the &lt;code&gt;android/fastlane&lt;/code&gt; folder inside the react native project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;android/fastlane
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;fastlane add_plugin android_version_manager
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Fastlane will ask &lt;code&gt;Should fastlane modify the Gemfile at path '&amp;lt;some-path-to&amp;gt;/android/Gemfile' for you?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Answer yes.&lt;/p&gt;

&lt;p&gt;Now we can use the plugin to handle versioning for us. Open &lt;code&gt;android/fastlane/Fastfile&lt;/code&gt; in your favorite text editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This file contains the fastlane.tools configuration&lt;/span&gt;
&lt;span class="c1"&gt;# You can find the documentation at https://docs.fastlane.tools&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# For a list of all available actions, check out&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#     https://docs.fastlane.tools/actions&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# For a list of all available plugins, check out&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#     https://docs.fastlane.tools/plugins/available-plugins&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;

&lt;span class="c1"&gt;# Uncomment the line if you want fastlane to automatically update itself&lt;/span&gt;
&lt;span class="c1"&gt;# update_fastlane&lt;/span&gt;

&lt;span class="n"&gt;default_platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:android&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="ss"&gt;:android&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Runs all the tests"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:test&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Submit a new Beta Build to Crashlytics Beta"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:beta&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="s2"&gt;"clean assembleRelease"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;crashlytics&lt;/span&gt;

    &lt;span class="c1"&gt;# sh "your_script.sh"&lt;/span&gt;
    &lt;span class="c1"&gt;# You can also use other beta testing services here&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Deploy a new version to the Google Play"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:deploy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="s2"&gt;"clean assembleRelease"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;upload_to_play_store&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Fastfile&lt;/code&gt; is essentially a Ruby file, with some extra DSL mixed in. It contains multiple lanes, which are steps we can run to help us automate multiple tasks.&lt;/p&gt;

&lt;p&gt;For now, don't pay to much attention to the existing lanes, just note that at the root we have a platform block called &lt;code&gt;:android&lt;/code&gt; with individual lanes inside.&lt;/p&gt;

&lt;p&gt;We are going to create two new lanes inside this block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Number
&lt;/h3&gt;

&lt;p&gt;The first lane we will create is called &lt;code&gt;ibn&lt;/code&gt;. This lane will be responsible for &lt;strong&gt;i&lt;/strong&gt;ncrementing the &lt;strong&gt;b&lt;/strong&gt;uild &lt;strong&gt;n&lt;/strong&gt;umber.&lt;/p&gt;

&lt;p&gt;The Android &lt;code&gt;builder number&lt;/code&gt; we are referring to here is commonly known as &lt;code&gt;internal version number&lt;/code&gt;, and is the value of the &lt;code&gt;versionCode&lt;/code&gt; field in the file &lt;code&gt;android/app/build.gradle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how our &lt;code&gt;ibn&lt;/code&gt; lane looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Increment build number and push to repository - Build number in this case is the android version code"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:ibn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;should_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;commit_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:commit_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"android: bump build number (version code) [skip ci]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;should_push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;ensure_git_status_clean&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;

  &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;:app_project_dir&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'app'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version_code&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;android_increment_version_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;new_version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_CODE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version code to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
    &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
    &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is an overview of what we just did.&lt;/p&gt;

&lt;p&gt;First, we have the &lt;code&gt;lane :name do |options| ... end&lt;/code&gt; block, which creates the lane itself. We can have some description of the lane by using the &lt;code&gt;desc&lt;/code&gt; call above the lane definition.&lt;/p&gt;

&lt;p&gt;The first few lines of our lane are creating three local variables. We will use them to store the values of some options passed when calling our lane.&lt;/p&gt;

&lt;p&gt;For example, the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="c1"&gt;# ...&lt;/span&gt;
  &lt;span class="n"&gt;should_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Is going to store in the variable named &lt;code&gt;should_commit&lt;/code&gt; the value passed on the CLI for the &lt;code&gt;should_commit&lt;/code&gt; option, in case no value was passed, we are going to assume &lt;code&gt;true&lt;/code&gt; as the default value (the second argument passed to &lt;code&gt;fetch&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Next, we are making sure that when we run our lane, there are no non-committed changes to our git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;ensure_git_status_clean&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This step is necessary in case we are going to automatically commit the build number bump to our repository (&lt;code&gt;should_commit&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;), as we don't want to commit unrelated files.&lt;/p&gt;

&lt;p&gt;Right after that we are creating another local variable called &lt;code&gt;params&lt;/code&gt;, which is initialized to a hash with a single key, &lt;code&gt;:app_project_dir&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;:app_project_dir&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'app'&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This variable is going to be used later when we call the plugin method to increment the build number, it's needed because we want to pass an extra param to this method depending on if we called our lane with a certain option or not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version_code&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we passed the option &lt;code&gt;build_number&lt;/code&gt; when calling our lane from the command-line, their value is going to be added as a new item to our &lt;code&gt;params&lt;/code&gt; hash, with the key &lt;code&gt;:version_code&lt;/code&gt;. The only difference being that we cast it to integer first by calling &lt;code&gt;to_i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can now call the action from the &lt;code&gt;android_version_manager&lt;/code&gt; plugin, passing the &lt;code&gt;params&lt;/code&gt; hash as the sole argument. This action, as their name implies, is responsible for incrementing the version code in the &lt;code&gt;android/app/build.gradle&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;android_increment_version_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The source code for this action can be found on GitHub: &lt;a href="https://github.com/JCMais/fastlane-plugin-android_version_manager/blob/master/lib/fastlane/plugin/android_version_manager/actions/android_increment_version_code_action.rb"&gt;./lib/fastlane/plugin/android_version_manager/actions/android_increment_version_code_action.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After calling the action, we are able to retrieve the new version code and display it on the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;new_version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_CODE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version code to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Actions.lane_context&lt;/code&gt; is a special hash used by fastlane that contains values shared from actions that were run previously, in our case we are retrieving the value for the key &lt;code&gt;Actions::SharedValues::ANDROID_VERSION_CODE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the field that the &lt;code&gt;android_increment_version_code&lt;/code&gt; action uses to store the new version code. How do we know that?&lt;/p&gt;

&lt;p&gt;By looking at the documentation of the action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;fastlane&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="n"&gt;android_increment_version_code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which is going to print something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kJ2vit_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9nbq643dld145t4k75kl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kJ2vit_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9nbq643dld145t4k75kl.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
android_increment_version_code documentation



&lt;p&gt;The keys we can use are available on the &lt;code&gt;android_increment_version_code Output Variables&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;The same output also shows a description of the action and each option it accepts.&lt;/p&gt;

&lt;p&gt;Remember that the &lt;code&gt;params&lt;/code&gt; hash we are passing has a &lt;code&gt;:app_project_dir&lt;/code&gt; key and could also contain another key &lt;code&gt;:version_code&lt;/code&gt;? As we can see above, these are options accepted by the action.&lt;/p&gt;

&lt;p&gt;Finally, at the end of our lane, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
    &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
    &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;should_commit&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, which it's going to be by default (remember the &lt;code&gt;options.fetch&lt;/code&gt; a few lines above), we are going to add, and commit, the &lt;code&gt;android/app/build.gradle&lt;/code&gt; file to our repository, and if &lt;code&gt;should_push&lt;/code&gt; is also true, we are going to push these changes to the remote git repository immediately after.&lt;/p&gt;

&lt;p&gt;The commit message is going to be the value of the &lt;code&gt;commit_message&lt;/code&gt; variable, which comes from the &lt;code&gt;commit_message&lt;/code&gt; command-line argument we pass to our lane.&lt;/p&gt;

&lt;p&gt;Now let's call our lane, first make sure you are in the android directory of the React Native project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;android&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;fastlane&lt;/span&gt; &lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="n"&gt;ibn&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;&lt;span class="ss"&gt;:false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note how arguments are passed to the lane using the &lt;code&gt;[key]:[value]&lt;/code&gt; format.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The output should look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MkEppxDW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b0dnngfua1p00yzvy78g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MkEppxDW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/b0dnngfua1p00yzvy78g.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the command output above we can see that version code (build number) was incremented from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;2&lt;/code&gt;. Which means our lane worked. 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Version Number
&lt;/h3&gt;

&lt;p&gt;The second lane we need is called &lt;code&gt;ivn&lt;/code&gt;. This lane will be responsible for &lt;strong&gt;i&lt;/strong&gt;ncrementing the &lt;strong&gt;v&lt;/strong&gt;ersion &lt;strong&gt;n&lt;/strong&gt;umber.&lt;/p&gt;

&lt;p&gt;The Android &lt;code&gt;version number&lt;/code&gt; we are referring to here is commonly known as &lt;code&gt;version name&lt;/code&gt;, and is the value of the &lt;code&gt;versionName&lt;/code&gt; field in the file &lt;code&gt;android/app/build.gradle&lt;/code&gt;. This is the value visible for users when downloading the app.&lt;/p&gt;

&lt;p&gt;We are going to use a Semver like versioning, &lt;code&gt;major.minor.patch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is how our &lt;code&gt;ivn&lt;/code&gt; lane looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Increment version number and push to repository - Version number in this case is the android version name"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:ivn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;should_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;commit_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:commit_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"android: bump version number (version name) [skip ci]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;should_push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# Ensure that your git status is not dirty&lt;/span&gt;
  &lt;span class="n"&gt;ensure_git_status_clean&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;

  &lt;span class="n"&gt;increment_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:increment_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;new_version_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;app_project_dir: &lt;/span&gt;&lt;span class="s1"&gt;'app'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;increment_type: &lt;/span&gt;&lt;span class="n"&gt;increment_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;new_version_params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_version_params&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;android_increment_version_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;new_version_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_NAME&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version name to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
    &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
    &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This lane follows the same idea as the previous one. But it accepts a few more options. The most important ones being &lt;code&gt;increment_type&lt;/code&gt; and &lt;code&gt;version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can pass either of them. &lt;code&gt;version&lt;/code&gt; allows us to specify the new version number directly, while &lt;code&gt;increment_type&lt;/code&gt; gives us the option to just say the increment type, which can be one of: &lt;code&gt;patch&lt;/code&gt;, &lt;code&gt;minor&lt;/code&gt;, and &lt;code&gt;major&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;increment_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:increment_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;new_version_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we don't pass anything, the default will be a &lt;code&gt;patch&lt;/code&gt; increment of the current version.&lt;/p&gt;

&lt;p&gt;After we handle the lane options, we call the &lt;code&gt;android_increment_version_name&lt;/code&gt; action, provided by the &lt;code&gt;android_version_manager&lt;/code&gt; plugin we have been using.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;android_increment_version_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;new_version_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_NAME&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version name to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The source code for this action can also be found on GitHub: &lt;a href="https://github.com/JCMais/fastlane-plugin-android_version_manager/blob/master/lib/fastlane/plugin/android_version_manager/actions/android_increment_version_name_action.rb"&gt;./lib/fastlane/plugin/android_version_manager/actions/android_increment_version_name_action.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then the same git handling we did in the previous lane is also being done here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
    &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
    &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's call our lane, again make sure you are in the android directory of the React Native project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;cd&lt;/span&gt; &lt;span class="n"&gt;android&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="n"&gt;fastlane&lt;/span&gt; &lt;span class="n"&gt;android&lt;/span&gt; &lt;span class="n"&gt;ivn&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;&lt;span class="ss"&gt;:false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The output should look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jwm0Vhq8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qese7c9gnd27088vdhpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jwm0Vhq8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qese7c9gnd27088vdhpz.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The version was correctly bumped from &lt;code&gt;1&lt;/code&gt; to &lt;code&gt;1.0.1&lt;/code&gt;. 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Alpha Version to the Play Store using Fastlane
&lt;/h2&gt;

&lt;p&gt;Now that we have the lanes responsible for bumping the build and version numbers, it's time to create our lane responsible for uploading a new alpha version to the Play Store.&lt;/p&gt;

&lt;p&gt;Here is our &lt;code&gt;alpha&lt;/code&gt; lane:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Build and push a new alpha build to the Play Store"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:alpha&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;build_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;build_task: &lt;/span&gt;&lt;span class="s2"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;build_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# defaults to completed&lt;/span&gt;
    &lt;span class="ss"&gt;release_status: &lt;/span&gt;&lt;span class="s2"&gt;"draft"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The code for this lane is much simpler than the ones we have written so far.&lt;/p&gt;

&lt;p&gt;Right at the start we are changing to another lane, called &lt;code&gt;build&lt;/code&gt;, and passing some options to it.&lt;/p&gt;

&lt;p&gt;We can call other lanes directly, they are just functions.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;build&lt;/code&gt; lane is responsible for building our AAB file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Build a version of the app"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;build_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"assemble"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;build_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Release"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;gradle_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="n"&gt;build_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;build_type: &lt;/span&gt;&lt;span class="n"&gt;build_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gradle_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It accepts two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build_task&lt;/code&gt;: which can be either &lt;code&gt;assemble&lt;/code&gt; or &lt;code&gt;bundle&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build_type&lt;/code&gt;: the variant we are building&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then passes those to the &lt;a href="https://docs.fastlane.tools/actions/gradle/"&gt;&lt;code&gt;gradle&lt;/code&gt;&lt;/a&gt; action.&lt;/p&gt;

&lt;p&gt;After the &lt;code&gt;build&lt;/code&gt; lane finishes, the execution context goes back to our &lt;code&gt;alpha&lt;/code&gt; lane:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# defaults to completed&lt;/span&gt;
    &lt;span class="ss"&gt;release_status: &lt;/span&gt;&lt;span class="s2"&gt;"draft"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We then call the &lt;a href="https://docs.fastlane.tools/actions/supply/"&gt;&lt;code&gt;supply&lt;/code&gt;&lt;/a&gt; action passing two option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;track&lt;/code&gt; with the value &lt;code&gt;alpha&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;release_status&lt;/code&gt; with the value &lt;code&gt;draft&lt;/code&gt;
This is needed as we are not releasing directly to the Play Store - But to one of our closed tracks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's run our lane and see what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;fastlane android alpha
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UWmpMb-o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1rewrsm70u991ruvnt16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UWmpMb-o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1rewrsm70u991ruvnt16.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above output, we can see that Fastlane calls into our &lt;code&gt;build&lt;/code&gt; lane and after that goes back to the &lt;code&gt;alpha&lt;/code&gt; lane, which then calls the &lt;code&gt;supply&lt;/code&gt; action.&lt;/p&gt;

&lt;p&gt;After fastlane uploads the new alpha release it should output something similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jFqFH1HH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uh5g4lqdhlah7bvkw20e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jFqFH1HH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uh5g4lqdhlah7bvkw20e.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: If you receive an error like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Google Api Error: badRequest: Only releases with status draft may be created on draft app. - Only releases with status draft may be created on draft app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It means you have not released the initial alpha version directly in the Play Store Console, like mentioned in the previous steps.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;If you go to the Play Store Console &lt;code&gt;App releases&lt;/code&gt; screen, you should see that the latest version is the one we uploaded:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GBC5OKqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/571lomjoe2jxufdzhci7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GBC5OKqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/571lomjoe2jxufdzhci7.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome! Time to work on our &lt;code&gt;beta&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; lanes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Lanes for the Beta and Production Tracks
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;beta&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; lanes are even simpler. As we are always going to release first to &lt;code&gt;alpha&lt;/code&gt;, the only thing we need to do is to promote from one track to the other.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Alpha → Beta → Production&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"promote the current alpha build to the beta track"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:beta&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;version_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google_play_track_version_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version_codes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

  &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;track_promote_to: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;version_code: &lt;/span&gt;&lt;span class="n"&gt;version_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"promote the current beta build to the production track"&lt;/span&gt;
&lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:production&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;version_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google_play_track_version_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version_codes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

  &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;track_promote_to: &lt;/span&gt;&lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;version_code: &lt;/span&gt;&lt;span class="n"&gt;version_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are using the action &lt;code&gt;google_play_track_version_codes&lt;/code&gt; to retrieve the active version codes of the current track we are promoting from.&lt;/p&gt;

&lt;p&gt;We then use the first version code found as the one to be promoted to the next track. This is needed to use the same changelog from the specified version code.&lt;/p&gt;

&lt;p&gt;Before we run our new lanes, we must remove the default &lt;code&gt;beta&lt;/code&gt; lane that fastlane created initially. It should be right at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Submit a new Beta Build to Crashlytics Beta"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:beta&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="s2"&gt;"clean assembleRelease"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;crashlytics&lt;/span&gt;

    &lt;span class="c1"&gt;# sh "your_script.sh"&lt;/span&gt;
    &lt;span class="c1"&gt;# You can also use other beta testing services here&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In fact, we can remove all lanes we are not using. The final &lt;code&gt;Fastfile&lt;/code&gt; looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;default_platform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:android&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="ss"&gt;:android&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Build a version of the app"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:build&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;build_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"assemble"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;build_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:build_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Release"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;gradle_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;task: &lt;/span&gt;&lt;span class="n"&gt;build_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;build_type: &lt;/span&gt;&lt;span class="n"&gt;build_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;gradle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gradle_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Build and push a new alpha build to the Play Store"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:alpha&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;build_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;build_task: &lt;/span&gt;&lt;span class="s2"&gt;"bundle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;build_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"promote the current alpha build to the beta track"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:beta&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;version_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google_play_track_version_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version_codes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

    &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"alpha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;track_promote_to: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;version_code: &lt;/span&gt;&lt;span class="n"&gt;version_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"promote the current beta build to the production track"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:production&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;version_codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;google_play_track_version_codes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version_codes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

    &lt;span class="n"&gt;supply_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;track: &lt;/span&gt;&lt;span class="s2"&gt;"beta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;track_promote_to: &lt;/span&gt;&lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;version_code: &lt;/span&gt;&lt;span class="n"&gt;version_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;supply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;supply_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Increment build number and push to repository - Build number in this case is the android version code"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:ibn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;should_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commit_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:commit_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"android: bump build number (version code) [skip ci]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;should_push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;ensure_git_status_clean&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;

    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;:app_project_dir&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'app'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version_code&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:build_number&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;android_increment_version_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_version_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_CODE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version code to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_code&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
      &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
      &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Increment version number and push to repository - Version number in this case is the android version name"&lt;/span&gt;
  &lt;span class="n"&gt;lane&lt;/span&gt; &lt;span class="ss"&gt;:ivn&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;should_commit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_commit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;commit_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:commit_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"android: bump version number (version name) [skip ci]"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;should_push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:should_push&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Ensure that your git status is not dirty&lt;/span&gt;
    &lt;span class="n"&gt;ensure_git_status_clean&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;

    &lt;span class="n"&gt;increment_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:increment_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"patch"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_version_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;app_project_dir: &lt;/span&gt;&lt;span class="s1"&gt;'app'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;increment_type: &lt;/span&gt;&lt;span class="n"&gt;increment_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;new_version_params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:version_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_version_params&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;android_increment_version_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_version_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lane_context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Actions&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SharedValues&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ANDROID_VERSION_NAME&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;important&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Incremented android version name to &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;new_version_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_commit&lt;/span&gt;
      &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"android/app/build.gradle"&lt;/span&gt;
      &lt;span class="n"&gt;git_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;git_commit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;message: &lt;/span&gt;&lt;span class="n"&gt;commit_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# Push the new commit and tag back to your git remote&lt;/span&gt;
      &lt;span class="n"&gt;push_to_git_remote&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;should_push&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now run our lanes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;fastlane android beta
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8keaLTNh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6cu0cwbnl0wy19tjyhtu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8keaLTNh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6cu0cwbnl0wy19tjyhtu.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
Alpha version was promoted to the Beta track



&lt;p&gt;Commit everything we have done so far to the git repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"add fastlane and lanes to publish the app to play store"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you don't have created one yet, now is the time to create the GitHub repository for your app. After you have done that, and added the remote to your local repository, push the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push -u origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Improvements
&lt;/h2&gt;

&lt;p&gt;There are a few points that can be improved here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promoted Builds vs Different Builds for Each Track
&lt;/h3&gt;

&lt;p&gt;We are promoting from one track to the next one, but this is not going to work for everyone. Example: Each track should consume a different API, and the API is set via &lt;code&gt;.env&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;You can change each lane to rebuild the app the way that would make more sense for your use case. Remember, the Fastfile is just a Ruby file, you can do whatever you want to customize the build process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rollouts
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;supply&lt;/code&gt; action allows you to do staged rollouts. With a staged rollout, the version update reaches only a percentage of the users, which can be increased over time.&lt;/p&gt;

&lt;p&gt;See more details about this on the &lt;a href="https://docs.fastlane.tools/actions/supply/"&gt;documentation for the &lt;code&gt;supply&lt;/code&gt; action&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Internal Track vs Alpha Track
&lt;/h3&gt;

&lt;p&gt;While we are using the Alpha track here, the code can be easily changed to use the Internal test track instead.&lt;/p&gt;

&lt;p&gt;The main advantage of doing that is that Internal test releases are processed faster than the others, the disadvantage is that it's limited to only 100 testers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;That is it! We can now upload our app to the Play Store by running a single command using fastlane.&lt;/p&gt;

&lt;p&gt;In the next part, we will see how to use multiple CI providers to do that automatically on each change being pushed to the &lt;code&gt;develop&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;master&lt;/code&gt; branches.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>reactnative</category>
      <category>fastlane</category>
      <category>android</category>
    </item>
  </channel>
</rss>
