1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 import org.yaml.snakeyaml.Yaml
8 apply from: file('./gradle/mozconfig.gradle')
11 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
14 if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
15 allowInsecureProtocol = true
22 classpath 'org.yaml:snakeyaml:2.2'
26 apply from: file('./gradle/mozconfig.gradle')
28 // Synchronized library configuration for all modules
29 // This "componentsVersion" number is defined in "version.txt" and should follow
30 // semantic versioning (MAJOR.MINOR.PATCH). See https://semver.org/
33 public final String componentsVersion
34 public final String componentsGroupId
35 public final Integer jvmTargetCompatibility
36 public final Integer compileSdkVersion
37 public final Integer minSdkVersion
38 public final Integer targetSdkVersion
41 String componentsVersion,
42 String componentsGroupId,
43 Integer jvmTargetCompatibility,
44 Integer compileSdkVersion,
45 Integer minSdkVersion,
46 Integer targetSdkVersion
48 this.componentsVersion = componentsVersion
49 this.componentsGroupId = componentsGroupId
50 this.jvmTargetCompatibility = jvmTargetCompatibility
51 this.compileSdkVersion = compileSdkVersion
52 this.minSdkVersion = minSdkVersion
53 this.targetSdkVersion = targetSdkVersion
57 def setupProject(name, path, description) {
58 settings.include(":$name")
60 def projectPath = "/mobile/android/android-components/${path}"
61 if (rootDir.toString().endsWith("android-components") ||
62 rootDir.toString().endsWith("focus-android") ||
63 rootDir.toString().endsWith("fenix")
65 projectPath = "../android-components/${path}"
68 project(":$name").projectDir = new File(rootDir, projectPath)
70 // project(...) gives us a skeleton project that we can't set ext.* on
71 gradle.beforeProject { project ->
72 // However, the "afterProject" listener iterates over every project and gives us the actual project
73 // So, once we filter for the project we care about, we can set whatever we want
74 if (project.name == name) {
75 project.ext.description = description
80 // Return a manifest version string that respects the Firefox version format,
81 // see: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/version#version_format
82 def getManifestVersionString(componentsVersion) {
83 // We assume that the `version.txt` file will always contain a version
84 // string with at least two parts separated with a dot. Below, we extract
85 // each part, and we make sure that there is no letter, e.g. `"0a2"` would
87 String[] parts = componentsVersion.split("\\.").collect {
88 part -> part.split("a|b")[0]
90 // Note the single `H` to avoid leading zeros, which are not allowed.
91 String dateAndTime = new Date().format("YYYYMMdd.Hmmss");
93 return "${parts[0]}.${parts[1]}.${dateAndTime}";
96 def buildConfigPath = '/mobile/android/android-components/.buildconfig.yml'
97 if (rootDir.toString().endsWith("android-components") ||
98 rootDir.toString().endsWith("focus-android") ||
99 rootDir.toString().endsWith("fenix")
101 buildConfigPath = '../android-components/.buildconfig.yml'
104 def yaml = new Yaml()
105 def buildconfig = yaml.load(new File(rootDir, buildConfigPath).newInputStream())
107 buildconfig.projects.each { project ->
108 // If we're building A-C, set up all projects, otherwise exclude samples e.g., if we're building Fenix or Focus.
109 // The samples are not relevant for the Fenix and Focus builds.
110 if (rootDir.toString().contains("android-components") || !project.key.startsWith("samples")) {
111 setupProject(project.key, project.value.path, project.value.description)
115 gradle.projectsLoaded { ->
116 def versionPath = '/mobile/android/version.txt'
117 def configPath = '/mobile/android/android-components/.config.yml'
119 if (rootDir.toString().endsWith("android-components") ||
120 rootDir.toString().endsWith("focus-android") ||
121 rootDir.toString().endsWith("fenix")
123 versionPath = '../version.txt'
124 configPath = '../android-components/.config.yml'
127 def componentsVersion = new File(rootDir, versionPath).text.stripTrailing()
128 def configData = yaml.load(new File(rootDir, configPath).newInputStream())
129 String version = componentsVersion
131 if (gradle.rootProject.hasProperty("nightlyVersion")) {
132 version = gradle.rootProject.nightlyVersion
133 } else if (gradle.rootProject.hasProperty("local")) {
134 // To support local auto-publication workflow, we use a version prefix we wouldn't normally encounter.
136 } else if (gradle.hasProperty("localProperties.branchBuild.android-components.version")) {
137 version = gradle.getProperty("localProperties.branchBuild.android-components.version")
140 // Wait until root project is "loaded" before we set "config"
141 // Note that since this is set on "rootProject.ext", it will be "in scope" during the evaluation of all projects'
142 // gradle files. This means that they can just access "config.<value>", and it'll function properly
143 gradle.rootProject.ext.config = new Config(
145 configData.componentsGroupId,
146 configData.jvmTargetCompatibility,
147 configData.compileSdkVersion,
148 configData.minSdkVersion,
149 configData.targetSdkVersion
152 gradle.rootProject.ext.buildConfig = buildconfig
154 // Define a reusable task for updating the version in manifest.json for modules that package
155 // a web extension. We automate this to make sure we never forget to update the version, either
156 // in local development or for releases. In both cases, we want to make sure the latest version
157 // of all extensions (including their latest changes) are installed on first start-up.
158 gradle.rootProject.allprojects {
159 ext.updateExtensionVersion = { task, extDir ->
162 include 'manifest.template.json'
163 rename { 'manifest.json' }
166 def values = ['version': getManifestVersionString(rootProject.ext.config.componentsVersion)]
167 inputs.properties(values)