Create Xamarin.Forms Android App Bundle (aab) and release it to Google Play Store with DevOps YAML
trigger: | |
branches: | |
include: | |
# Your CI branch that the build should be triggered for | |
- vNext | |
stages: | |
- stage: Build | |
pool: | |
vmImage: 'windows-latest' | |
jobs: | |
- job: GenerateAab | |
variables: | |
# Your major and minor version numbers | |
appVersion: '1.2' | |
buildConfiguration: 'Release' | |
androidNdkPath: 'C:\Microsoft\AndroidNDK64\android-ndk-r16b' | |
steps: | |
# Code "stolen" from James, from his DevOps tasks -> https://github.com/jamesmontemagno/vsts-mobile-tasks | |
- task: PowerShell@2 | |
displayName: 'Updating Version Code and Name in Android Manifest' | |
inputs: | |
targetType: 'inline' | |
script: | | |
[string] $sourcePath = "$(System.DefaultWorkingDirectory)\Path\To\Your\Android\Project\Properties\AndroidManifest.xml" | |
[string] $appVersionName = "$(AppVersion).$(Build.BuildId)" | |
# I would suggest to use Build.BuildId variable for the version code but I've started using date and can't go back to lower numbers | |
[string] $appVersionCode = Get-Date -Format "yyMMddHH" | |
# Load the Android Manifest file | |
[xml] $androidManifestXml = Get-Content -Path $sourcePath | |
Write-Host "Original Manifest:" | |
Get-Content $sourcePath | Write-Host | |
# Get the version name | |
$VersionName= Select-Xml -xml $androidManifestXml -Xpath "/manifest/@android:versionName" -namespace @{android = "http://schemas.android.com/apk/res/android" } | |
$oldVersionName= $VersionName.Node.Value; | |
Write-Host " (i) Original Version Name: $oldVersionName" | |
$VersionName.Node.Value = $appVersionName | |
Write-Host " (i) New Package Name: $appVersionName" | |
# Get the version code | |
$VersionCode= Select-Xml -xml $androidManifestXml -Xpath "/manifest/@android:versionCode" -namespace @{android = "http://schemas.android.com/apk/res/android" } | |
$oldVersionCode = $VersionCode.Node.Value; | |
Write-Host " (i) Old Version Code: $oldVersionCode" | |
$VersionCode.Node.Value = $appVersionCode | |
Write-Host " (i) New App Name: $appVersionCode " | |
$androidManifestXml.Save($sourcePath) | |
Write-Host "Final Manifest:" | |
Get-Content $sourcePath | Write-Host | |
- task: NuGetToolInstaller@1 | |
displayName: 'Installing Nuget' | |
- task: NuGetCommand@2 | |
displayName: 'Restoring Nugets' | |
inputs: | |
restoreSolution: '**/*.sln' | |
- task: DownloadSecureFile@1 | |
displayName: 'Download keystore' | |
# This file's name will be used in the build task as a value for parameter AndroidSigningKeyStore | |
name: keystore | |
inputs: | |
# This file needs to be stored in the DevOps' Library | |
secureFile: 'NameOfYourKeystoreFile.keystore' | |
# KeystorePassword is a secure variable that has been set using GUI in the DevOps portal | |
- task: XamarinAndroid@1 | |
displayName: 'Build aab' | |
inputs: | |
projectFile: Path/To/Your/Android/Project/NameOfYourDroidHeadProject.csproj | |
outputDirectory: '$(Build.BinariesDirectory)' | |
configuration: '$(BuildConfiguration)' | |
clean: true | |
msbuildVersionOption: latest | |
msbuildArguments: ' /p:JavaSdkDirectory="$(JAVA_HOME)/" /t:SignAndroidPackage /p:AndroidNdkDirectory="$(androidNdkPath)" /p:AndroidKeyStore="True" /p:AndroidSigningKeyStore="$(keystore.secureFilePath)" /p:AndroidSigningKeyPass="$(KeystorePassword)" /p:AndroidSigningKeyAlias="YourKeystoreAlias" /p:AndroidSigningStorePass="$(KeystorePassword)"' | |
- task: PublishPipelineArtifact@1 | |
displayName: 'Publishing aab artifacts' | |
inputs: | |
targetPath: '$(Build.BinariesDirectory)' | |
artifact: AndroidAabPackage | |
publishLocation: 'pipeline' | |
- stage: Release | |
pool: | |
vmImage: 'macOS-latest' | |
dependsOn: Build | |
# The condition checks if the Build stage has succeeded and if it has been triggered from the vNext branch | |
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/vNext')) | |
jobs: | |
- job: GooglePlayBetaRelease | |
steps: | |
# Another file that needs to be stored in the DevOps' Library (see my previous post on how to generate it) | |
- task: DownloadSecureFile@1 | |
displayName: 'Download Google Play Console JSON key auth file' | |
name: serviceAccAuthJson | |
inputs: | |
secureFile: 'Google_Play_Store_Dev_Ops_Service_Acc_Auth.json' | |
- task: DownloadPipelineArtifact@2 | |
displayName: 'Downloading aab package' | |
inputs: | |
buildType: 'current' | |
artifactName: 'AndroidAabPackage' | |
itemPattern: '**/com.yourcompanyname.yourappname-Signed.aab' | |
targetPath: '$(Build.SourcesDirectory)\Artifacts' | |
- task: Bash@3 | |
displayName: 'Fastlane - Release aab to Beta' | |
inputs: | |
workingDirectory: '$(Build.SourcesDirectory)\Artifacts' | |
targetType: 'inline' | |
script: | | |
fastlane supply --aab com.yourcompanyname.yourappname-Signed.aab --json_key $(serviceAccAuthJson.secureFilePath) --track beta --rollout 1.0 --package_name com.yourcompanyname.yourappname --skip_upload_apk true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment