I have a pipeline that ones running perfectly when my application wasn't flavored.
it was building, signing and releasing the application to the firebase distribution.
Now I have the application flavored and I want on each push to development to release the app whether on com.example_flavor1 or com.example_flavor2
the gradle task and the firebase app id should change according to the flavor but i'm not knowing how to do so, can you help please
Here's my pipeline
trigger:
- development
variables:
- group: 'Variables'
stages:
- stage: Build
displayName: Build & Archive
jobs:
- job: build
displayName: build
pool:
vmImage: $(vmImage)
steps:
- task: Gradle#2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleRelease --stacktrace'
- task: DownloadSecureFile#1
displayName: Retrieving the Keystore
inputs:
secureFile: 'keystore.keystore'
- task: AndroidSigning#3
displayName: Signing the Release 2
inputs:
apkFiles: '**/*.apk'
apksign: true
apksignerKeystoreFile: 'keystore.keystore'
apksignerKeystorePassword: '$(KeyStorePassword)'
apksignerKeystoreAlias: '$(KeyAlias)'
apksignerKeyPassword: '$(KeyPassword)'
apksignerArguments: --out $(Build.SourcesDirectory)/app/build/outputs/apk/release/app-$(MajorVersion).$(MinorVersion).$(Build.BuildID)-release.apk
zipalign: false
- task: CopyFiles#2
displayName: Archive APKs
inputs:
contents: '**/*.apk'
targetFolder: '$(build.artifactStagingDirectory)/apk'
- task: CopyFiles#2
displayName: Archive AABs
inputs:
contents: '**/*.aab'
targetFolder: '$(build.artifactStagingDirectory)/aab'
- task: PublishBuildArtifacts#1
displayName: Publish build artifacts
inputs:
pathToPublish: '$(build.artifactStagingDirectory)'
artifactName: '$(MajorVersion).$(MinorVersion).$(Build.BuildID)'
- stage: Publish
displayName: Publish
condition: succeeded()
jobs:
- deployment:
displayName: Firebase Tools install and deploy
pool:
vmImage: $(vmImage)
environment: Dev
strategy:
runOnce:
deploy:
steps:
- task: NodeTool#0
inputs:
versionSpec: '10.x'
displayName: 'Install Node.js'
- task: DownloadBuildArtifacts#0
inputs:
buildType: 'current'
artifactName: '$(MajorVersion).$(MinorVersion).$(Build.BuildID)'
downloadPath: '$(System.ArtifactsDirectory)'
- script: |
cd $(Pipeline.Workspace)
npm install -g firebase-tools
firebase appdistribution:distribute $(System.ArtifactsDirectory)/$(MajorVersion).$(MinorVersion).$(Build.BuildID)/apk/app/build/outputs/apk/release/app-$(MajorVersion).$(MinorVersion).$(Build.BuildID)-release.apk --project $(firebase-project-id) --app $(firebase-android-app-id) --token $(firebase-token) --testers "$(firebase-testers-emails)" --groups "$(firebase-testers-groups)" --release-notes "$(release-notes)" --debug
displayName: 'npm install and distribute'
You could implement parallel jobs in Azure Devops to support an arbitrary number of Gradle flavors an Android app. And use Templates to define reusable content, logic, and parameters. For example:
jobs:
- job: A
variables:
- group: "A"
steps:
- template: build.yml
- job: B
variables:
- group: "B"
steps:
- template: build.yml
Here is a simple example you may refer to:
https://github.com/seanKenkeremath/AzureDevopsAndroidFlavorsExample
Related
Hey guy's i set up a pipeline for Automation and need to add the sign part.But since Google does not allow APK files i need the AAB file.
What my pipeline setup is i want to generate an AAB file and sign it for all variants.This part works
- task: Gradle#2
displayName: 'Gradle Assemble bundle'
inputs:
gradleWrapperFile: 'gradlew'
tasks: ':app:bundleRelease'
publishJUnitResults: false
javaHomeOption: 'JDKVersion'
gradleOptions: '-Xmx3072m'
sonarQubeRunAnalysis: false
spotBugsAnalysis: false
- task: AndroidSigning#3
displayName: 'Gradle AndroidSigning aab'
inputs:
apkFiles: '**/*.aab'
apksignerKeystoreFile: 'My.keystore'
apksignerKeystorePassword: 'pass'
apksignerKeystoreAlias: 'alias'
apksignerKeyPassword: 'pass'
apksignerArguments: '--verbose --min-sdk-version 26'
- task: CopyFiles#2
displayName: 'Copy AAB Files'
inputs:
contents: '**/*.aab'
targetFolder: '$(build.artifactStagingDirectory)'
overWrite: true
CleanTargetFolder: true
- task: PublishBuildArtifacts#1
displayName: 'PublishBuildArtifacts Files'
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'AAB Files for Google Play'
publishLocation: 'Container'
This part works cause i get full artifacts for all variants in one shot.
Whats odd is that it creates the Directory by i have a folder intermediary_bundle and outputs-bundle
What file is good?
As for the APK file for internal testing
Is it possible to use a task gradle#2 to generate all debug variants?
cause i have tried app:bundleDebug or assembleDebug but when i specify the variant like assembleVariantDebug it works
Also i need to move the APK same as AAB files but that seems to not move them?
- task: CopyFiles#1
displayName: 'Copy APK Files'
inputs:
Contents: '**/*.apk'
TargetFolder: '$(build.artifactStagingDirectory)'
CleanTargetFolder: true
flattenFolders: true
- task: PublishBuildArtifacts#1
displayName: 'Publishing Artifacts APK'
inputs:
pathToPublish: '$(build.artifactStagingDirectory)'
artifactName: 'VariantBuildsAPK'
artifactType: 'container'
I have an Ionic Capacitor Android app that I need to set up an Azure DevOps yaml pipeline for.
Here's my yaml:
- task: JavaToolInstaller#0
inputs:
versionSpec: "11"
jdkArchitectureOption: "x64"
jdkSourceOption: "PreInstalled"
displayName: "Install JDK v11"
- task: NodeTool#0
inputs:
versionSpec: "16.x"
displayName: "Install Node.js v16.x"
- task: Npm#1
inputs:
workingDir: "$(projectDirectory)"
command: install
displayName: "NPM Install"
- task: Npm#1
inputs:
command: "custom"
workingDir: "$(projectDirectory)"
customCommand: "install -g #ionic/cli"
displayName: "NPM Install Ionic CLI"
- powershell: |
ionic cap build android --no-open
npx cap sync android
workingDirectory: $(projectDirectory)
displayName: "Android: Ionic Cap Build and Sync"
- task: Gradle#3
inputs:
workingDirectory: $(projectDirectory)/android
gradleWrapperFile: "$(projectDirectory)/android/gradlew"
publishJUnitResults: false
tasks: assembleRelease
displayName: "Android: Build APK"
- task: AndroidSigning#3
displayName: "Android: Sign .APK file(s)"
inputs:
apkFiles: "$(projectDirectory)/android/app/build/outputs/apk/$(buildConfiguration)/*.apk"
apksign: true
apksignerKeystoreFile: "$(ts-secure-file-name)"
apksignerKeystorePassword: "$(ts-keystore-password)"
apksignerKeystoreAlias: "$(ts-keystore-alias)"
apksignerKeyPassword: "$(ts-keystore-password)"
zipalign: true # zipalign is no longer needed ? ref: https://stackoverflow.com/a/64973262/1508398
With this, I get the error at Android Signing step saying
Unable to open
'D:\a\1\s\Source\node_modules\webdriver-js-extender\built\built\built\built\built\built\built\built\built\built\built\built\built\built\built\built\spec\comm
##[error]Error: The process 'C:\Android\android-sdk\build-tools\33.0.0\zipalign.exe' failed with
exit code 1
When I set the zipAlign:false, then the signing fails saying:
Exception in thread "main" com.android.apksig.apk.ApkFormatException:
Malformed APK: not a ZIP archive
I am really new to this. Any idea on what I am missing out here?
Basically I have this in my build.gradle:
Like this I can build an APK that can be installed on a device without any error but on Azure I have these lines commented.
In Azure Devops I don't use these values, this part is commented. But I need this part when I generate the APK otherwise it won't run on device.
Currently I use this pipeline to build & sign the apk:
- stage: Android
dependsOn: [ReleaseNotes]
jobs:
- job: AndroidJob
pool:
vmImage: 'ubuntu-latest'
displayName: Android
steps:
- task: FlutterInstall#0
displayName: "Install Flutter SDK"
inputs:
mode: 'auto'
channel: 'stable'
version: 'latest'
- task: FlutterBuild#0
displayName: 'Flutter Build App - Android'
inputs:
target: apk
iosCodesign: false
projectDirectory: $(projectDirectory)
- task: AndroidSigning#3
displayName: 'Signing and aligning APK file(s) **/*.apk'
inputs:
apkFiles: '**/*.apk'
apksign: true
apksignerKeystoreFile: upload-keystore.jks
apksignerKeystorePassword: $(upload-keystore-password)
apksignerKeystoreAlias: upload
apksignerKeyPassword: $(upload-keystore-password)
What could be the solution?
Thanks in advance.
Failed to apply plugin 'com.android.internal.application'.
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
Your current JDK is located in /Users/runner/hostedtoolcache/Java_Temurin-Hotspot_jdk/8.0.332-9/x64/Contents/Home/jre
You can try some of the following options:
- changing the IDE settings.
- changing the JAVA_HOME environment variable.
- changing org.gradle.java.home in gradle.properties.
According to the error message, your project has been set to require Java 11. However, the default Java version installed on the agent machine is Java 8.
In Azure Pipelines, when the default Java version installed on the agent machine is not consistent with that required by your project, you can use the Java Tool Installer task to install the required Java version. This task will install the specified Java version and set it to the JAVA_HOME environment variable on the agent machine.
Then in the subsequent tasks in the same job, the specified Java version will be used by default.
Yea, I was having the same issue on Azure Pipelines with mac-latest.
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/runner/work/1/s/android/app/build.gradle' line: 1
* What went wrong:
A problem occurred evaluating project ':app'.
> Failed to apply plugin 'com.android.internal.application'.
> Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
Your current JDK is located in /Users/runner/hostedtoolcache/Java_Temurin-Hotspot_jdk/8.0.352-8/x64/Contents/Home/jre
You can try some of the following options:
- changing the IDE settings.
- changing the JAVA_HOME environment variable.
- changing `org.gradle.java.home` in `gradle.properties`.
I used JavaToolInstaller to set JAVA_HOME to 11 and then had to update gradle.properties and set org.gradle.java.home to the value in JAVA_HOME. Hope this helps someone else.
pool:
vmImage: 'macOS-latest'
steps:
- task: NodeTool#0
inputs:
versionSpec: '16.17.1'
displayName: 'Install Node.js'
- task: JavaToolInstaller#0
inputs:
versionSpec: '11'
jdkArchitectureOption: 'x64'
jdkSourceOption: 'PreInstalled'
- script: |
npm install
cd android
echo "org.gradle.java.home=$JAVA_HOME" >> ./gradle.properties
displayName: 'Android Setup Script'
- task: Gradle#3
inputs:
workingDirectory: 'android/'
gradleWrapperFile: 'android/gradlew'
gradleOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.8'
jdkArchitectureOption: 'x64'
publishJUnitResults: false
sonarQubeRunAnalysis: false
tasks: 'assembleRelease'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId)'
- task: AndroidSigning#3
inputs:
apkFiles: '**/*.apk'
apksignerKeystoreFile: 'upload.keystore'
apksignerKeystorePassword: '$(AndroidKeyStorePassword)'
apksignerKeystoreAlias: '$(AndroidKeyAlias)'
apksignerKeyPassword: '$(AndroidKeyPassword)'
zipalign: false
trigger:
- CDCI
pool:
vmImage: 'macOS-latest'
steps:
- task: NodeTool#0
inputs:
versionSpec: '16.17.1'
displayName: 'Install Node.js'
# - task: JavaToolInstaller#0
# inputs:
# versionSpec: "8"
# jdkArchitectureOption: x64
# jdkSourceOption: 'PreInstalled'
- task: JavaToolInstaller#0
inputs:
versionSpec: "11"
jdkArchitectureOption: x64
jdkSourceOption: 'PreInstalled'
- script: |
npm install
cd android
echo "org.gradle.java.home=$JAVA_HOME" >> ./gradle.properties
displayName: 'Android Setup Script'
# - script: |
# java -version
# env:
# JAVA_HOME: $(JAVA_HOME_8_X64)
# PATH: $(JAVA_HOME_8_X64)/bin;$(PATH)
# - script: |
# echo "##vso[task.setvariable variable=JAVA_HOME]$(JAVA_HOME_11_X64)"
# echo "##vso[task.setvariable variable=PATH]$(JAVA_HOME_11_X64)\bin;$(PATH)"
# displayName: "Set java version"
# Gradle v1
# Build using a Gradle wrapper script.
- task: Gradle#3
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '11'
jdkArchitectureOption: 'x64'
publishJUnitResults: false
sonarQubeRunAnalysis: false
tasks: 'assembleRelease'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId)'
# Download secure file
# Download a secure file to the agent machine
- task: DownloadSecureFile#1
inputs:
secureFile: 'keystore.jks'
- task: AndroidSigning#3
inputs:
apkFiles: '**/*.apk'
apksignerKeystoreFile: 'keystore.jks'
apksignerKeystorePassword: '$(jarsignerKeystorePassword)'
apksignerKeystoreAlias: '$(keyAlias)'
apksignerKeyPassword: '$(jarsignerKeyPassword)'
zipalign: false
- task: CopyFiles#2
inputs:
contents: '**/*.apk'
targetFolder: '$(build.artifactStagingDirectory)'
- task: PublishBuildArtifacts#1
- task: CmdLine#2
inputs:
script: 'appcenter login --token c47e589dadcc75a75fc51e211d7144f245da9e8c'
- task: AppCenterDistribute#3
inputs:
serverEndpoint: 'AppCentreServiceConnection'
appSlug: 'tauqeer.majeed-auxilium.digital/AirPortr'
appFile: 'app/release/app-release.apk'
buildVersion: '1.1'
releaseNotesOption: 'file'
releaseNotesFile: 'release-notes.txt'
destinationType: 'groups'
distributionGroupId: '667d2623-9734-4b84-84ce-8deb0e919928'
I have a react native app building on Azure Devops ok,
now to create the distribution, it shows a grey arrow on the "jobs", and I cannot find the app distributed,
What is Result: False ?
here the yaml
trigger:
- master
pool:
vmImage: 'macOS-10.14'
variables:
- group: AndroidKeystore
steps:
- task: NodeTool#0
displayName: 'Install Node'
inputs:
versionSpec: '12.16.1'
- script: npm install
displayName: 'Install node dependencies'
- script: |
npm i jetifier
npx jetify
displayName: 'npx'
- script: |
rm -r android/app/src/main/res/drawable-*
rm -r android/app/src/main/res/raw
displayName: 'delete before'
- task: Gradle#2
inputs:
workingDirectory: 'android'
gradleWrapperFile: 'android/gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'assembleRelease'
- task: AndroidSigning#3
inputs:
apkFiles: '**/*.apk'
apksign: true
apksignerKeystoreFile: 'my-release-key.keystore'
apksignerKeystorePassword: '$(jarsignerKeystorePassword)'
apksignerKeystoreAlias: 'my-key-alias'
apksignerKeyPassword: '$(jarsignerKeyPassword)'
- script: mv android/app/build/outputs/apk/release/app-release.apk ReactNativePipeline$(Build.BuildNumber).apk
displayName: 'Rename apk'
- task: PublishBuildArtifacts#1
inputs:
pathtoPublish: ReactNativePipeline$(Build.BuildNumber).apk
artifactName: drop
publishLocation: 'container'
- task: AppCenterDistribute#3
displayName: "Create a release on App Center"
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
inputs:
serverEndpoint: 'VSAC'
appSlug: 'Wisr/WisrRN-Android2'
appFile: 'ReactNativePipeline$(Build.BuildNumber).apk'
releaseNotesOption: 'input'
releaseNotesInput: |
$(Build.SourceVersionMessage)
latest source: '$(Build.SourceVersion)'
An automated release from Azure DevOps
destinationType: 'groups'
distributionGroupId: 'testBench'
So how to make the build available on the specific group "testBench"
What is Result: False ?
This is the result of condition. From the task log, the Build.SourceBranch is refs/heads/androidPipe.
refs/heads/androidPipe eq refs/heads/master Result: false
In your Yaml sample, the condition settings:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
This means that when the Build.SourceBranch is master, it will run the AppCenterDistribute task. Or it will not run the task(Skip the task).
Here are two methods to solve this issue:
1.You could change the Condition:
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/androidPipe'))
2.You could use the master branch to run the pipeline. Then the task will execute.
By the way, if you don't need this condition, you can also delete it. In this case, no matter what branch it is, this task will run.
For more detailed information, you could refer to this doc about Condition.