Revision control

Copy as Markdown

// Top-level build file where you can add configuration options common to all sub-projects/modules.
import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask
import org.gradle.internal.logging.text.StyledTextOutput.Style
import org.gradle.internal.logging.text.StyledTextOutputFactory
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import static org.gradle.api.tasks.testing.TestResult.ResultType
buildscript {
repositories {
if (project.hasProperty("googleRepo")) {
maven {
name "Google"
url project.property("googleRepo")
allowInsecureProtocol true // Local Nexus in CI uses HTTP
}
} else {
google()
}
if (project.hasProperty("centralRepo")) {
maven {
name "MavenCentral"
url project.property("centralRepo")
allowInsecureProtocol true // Local Nexus in CI uses HTTP
}
} else {
mavenCentral()
}
}
dependencies {
classpath ComponentsDependencies.tools_androidgradle
classpath ComponentsDependencies.tools_kotlingradle
}
// Variables in plugins {} aren't directly supported. Hack around it by setting an
// intermediate variable which can pull from FenixDependencies.kt and be used later.
ext {
detekt_plugin = Versions.detekt
python_envs_plugin = Versions.python_envs_plugin
ksp_plugin = Versions.ksp_plugin
}
}
plugins {
id("io.gitlab.arturbosch.detekt").version("$detekt_plugin")
id("com.google.devtools.ksp").version("$ksp_plugin")
}
allprojects {
repositories {
if (project.hasProperty("googleRepo")) {
maven {
name "Google"
url project.property("googleRepo")
allowInsecureProtocol true // Local Nexus in CI uses HTTP
}
} else {
google()
}
if (project.hasProperty("centralRepo")) {
maven {
name "MavenCentral"
url project.property("centralRepo")
allowInsecureProtocol true // Local Nexus in CI uses HTTP
}
} else {
mavenCentral()
}
maven {
name "Mozilla"
}
if (ExtraRepositories.mozillaStaging) {
maven {
name "Mozilla Staging"
}
}
}
}
subprojects {
apply plugin: 'jacoco'
// Enable Kotlin warnings as errors for all modules
tasks.withType(KotlinCompile).configureEach {
kotlinOptions.allWarningsAsErrors = true
}
project.configurations.configureEach {
// Dependencies can't depend on a different major version of Glean than A-C itself.
resolutionStrategy.eachDependency { details ->
if (details.requested.group == 'org.mozilla.telemetry'
&& details.requested.name.contains('glean') ) {
def requested = details.requested.version.tokenize(".")
def defined = Versions.mozilla_glean.tokenize(".")
// Check the major version
if (requested[0] != defined[0]) {
throw new AssertionError("Cannot resolve to a single Glean version. Requested: ${details.requested.version}, A-C uses: ${Versions.mozilla_glean}")
} else {
// Enforce that all (transitive) dependencies are using the defined Glean version
details.useVersion Versions.mozilla_glean
}
}
}
resolutionStrategy.capabilitiesResolution.withCapability("org.mozilla.telemetry:glean-native") {
def toBeSelected = candidates.find { it.id instanceof ModuleComponentIdentifier && it.id.module.contains('geckoview') }
if (toBeSelected != null) {
select(toBeSelected)
}
because 'use GeckoView Glean instead of standalone Glean'
}
}
// Allow local appservices substitution in each subproject.
def appServicesSrcDir = null
if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
appServicesSrcDir = gradle.getProperty('localProperties.autoPublish.application-services.dir')
} else if (gradle.hasProperty('localProperties.branchBuild.application-services.dir')) {
appServicesSrcDir = gradle.getProperty('localProperties.branchBuild.application-services.dir')
}
if (appServicesSrcDir) {
if (appServicesSrcDir.startsWith("/")) {
apply from: "${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
} else {
apply from: "${rootProject.projectDir}/${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
}
}
// Allow local Glean substitution in each subproject.
if (gradle.hasProperty('localProperties.autoPublish.glean.dir')) {
ext.gleanSrcDir = gradle."localProperties.autoPublish.glean.dir"
apply from: "${rootProject.projectDir}/${gleanSrcDir}/build-scripts/substitute-local-glean.gradle"
}
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
}
ext.topsrcdir = gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir"
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
}
afterEvaluate {
if (it.hasProperty('android')) {
jacoco {
toolVersion = Versions.jacoco
}
// Format test output
tasks.matching {it instanceof Test}.configureEach() {
systemProperty "robolectric.logging", "stdout"
systemProperty "logging.test-mode", "true"
systemProperty "javax.net.ssl.trustStoreType", "JKS"
testLogging.events = []
def out = services.get(StyledTextOutputFactory).create("an-ouput")
beforeSuite { descriptor ->
if (descriptor.getClassName() != null) {
out.style(Style.Header).println("\nSUITE: " + descriptor.getClassName())
}
}
beforeTest { descriptor ->
out.style(Style.Description).println(" TEST: " + descriptor.getName())
}
onOutput { descriptor, event ->
logger.lifecycle(" " + event.message.trim())
}
afterTest { descriptor, result ->
switch (result.getResultType()) {
case ResultType.SUCCESS:
out.style(Style.Success).println(" SUCCESS")
break
case ResultType.FAILURE:
out.style(Style.Failure).println(" FAILURE")
logger.lifecycle("", result.getException())
break
case ResultType.SKIPPED:
out.style(Style.Info).println(" SKIPPED")
break
}
logger.lifecycle("")
}
}
dependencies {
lintChecks project(':tooling-lint')
}
kotlin {
jvmToolchain(config.jvmTargetCompatibility)
}
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
packagingOptions {
resources {
excludes += ['META-INF/atomicfu.kotlin_module', 'META-INF/AL2.0', 'META-INF/LGPL2.1']
// Required dependencies using byte-buddy; remove after this is
excludes.add("META-INF/licenses/ASM")
pickFirsts += ['win32-x86-64/attach_hotspot_windows.dll', 'win32-x86/attach_hotspot_windows.dll']
}
}
androidResources {
ignoreAssetsPattern "manifest.template.json"
}
tasks.withType(KotlinCompile).configureEach {
kotlinOptions.freeCompilerArgs += ["-opt-in=kotlin.RequiresOptIn"]
}
}
if (project.hasProperty("coverage") && project.name != "support-test") {
android.buildTypes.all { buildType ->
tasks.withType(Test).configureEach() {
jacoco {
includeNoLocationClasses = true
excludes = ['jdk.internal.*']
}
finalizedBy { "jacoco${buildType.name.capitalize()}TestReport" }
}
tasks.register("jacoco${buildType.name.capitalize()}TestReport", JacocoReport) {
reports {
xml.required = true
html.required = true
}
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
'**/*Test*.*', 'android/**/*.*', '**/*$[0-9].*']
def kotlinDebugTree = fileTree(dir: "$project.layout.buildDirectory/tmp/kotlin-classes/${buildType.name}", excludes: fileFilter)
def javaDebugTree = fileTree(dir: "$project.layout.buildDirectory/intermediates/classes/${buildType.name}", excludes: fileFilter)
def mainSrc = "$project.projectDir/src/main/java"
sourceDirectories.setFrom(files([mainSrc]))
classDirectories.setFrom(files([kotlinDebugTree, javaDebugTree]))
getExecutionData().setFrom(fileTree(project.layout.buildDirectory).include([
"jacoco/test${buildType.name.capitalize()}UnitTest.exec"
]))
}
}
android {
buildTypes {
debug {
testCoverageEnabled true
}
}
}
}
}
}
}
tasks.register("clean", Delete) {
delete rootProject.layout.buildDirectory
}
detekt {
input = files("$projectDir/components", "$projectDir/buildSrc", "$projectDir/samples")
config = files("$projectDir/config/detekt.yml")
baseline = file("$projectDir/config/detekt-baseline.xml")
reports {
html {
enabled = true
destination = file("$projectDir/build/reports/detekt.html")
}
xml {
enabled = false
}
txt {
enabled = false
}
}
}
tasks.withType(Detekt).configureEach() {
// Custom detekt rules should be build before
dependsOn(":tooling-detekt:assemble")
autoCorrect = true
exclude "**/build.gradle.kts"
exclude "**/src/androidTest/**"
exclude "**/src/iosTest/**"
exclude "**/src/test/**"
exclude "**/test/src/**"
exclude "**/build/**"
exclude "**/resources/**"
exclude "**/tmp/**"
exclude "**/tooling/fetch/tests/**"
exclude "**/tooling/fetch-tests/**"
exclude "**/src/main/assets/extensions/**"
exclude "**/docs/**"
}
// Apply same path exclusions as for the main task
tasks.withType(DetektCreateBaselineTask).configureEach() {
exclude "**/src/androidTest/**"
exclude "**/src/test/**"
exclude "**/test/src/**"
exclude "**/build/**"
exclude "**/resources/**"
exclude "**/tmp/**"
exclude "**/tooling/fetch/tests/**"
exclude "**/tooling/fetch-tests/**"
}
configurations {
ktlint
}
dependencies {
ktlint("com.pinterest:ktlint:${Versions.ktlint}") {
attributes {
attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
}
}
detektPlugins project(":tooling-detekt")
}
tasks.register("ktlint", JavaExec) {
group = "verification"
description = "Check Kotlin code style."
classpath = configurations.ktlint
mainClass.set("com.pinterest.ktlint.Main")
args "components/**/*.kt" , "samples/**/*.kt", "!**/build/**/*.kt", "buildSrc/**/*.kt", "--baseline=ktlint-baseline.xml"
}
tasks.register("ktlintFormat", JavaExec) {
group = "formatting"
description = "Fix Kotlin code style deviations."
classpath = configurations.ktlint
mainClass.set("com.pinterest.ktlint.Main")
args "-F", "components/**/*.kt" , "samples/**/*.kt", "!**/build/**/*.kt", "buildSrc/**/*.kt", "--baseline=ktlint-baseline.xml"
jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}
tasks.register("listRepositories") {
doLast {
println "Repositories:"
project.repositories.each { println "Name: " + it.name + "; url: " + it.url }
}
}
tasks.register("githubBuildDetails", GithubDetailsTask) {
text = """### Test result files
- [Test Coverage]({reportsUrl}/jacoco/jacocoReleaseTestReport/html/index.html)
- [Unit Tests]({reportsUrl}/tests/testReleaseUnitTest/index.html)
- [Android Lint]({reportsUrl}/lint-results-release.html)"""
}
tasks.register("githubLintDetektDetails", GithubDetailsTask) {
text = "### [Detekt Results Android-Components]({reportsUrl}/detekt.html)"
}
tasks.register("githubLintAndroidDetails", GithubDetailsTask) {
text = "### [Android Lint Results Android-Components]({reportsUrl}/lint-results-debug.html)"
}
tasks.register("testToolsDir", Exec) {
group = "verification"
description = "Run tests in the tools/ directory."
workingDir = "tools"
commandLine = ["python3", "test_list_compatible_dependency_versions.py"]
}