gradle: set sonarRunner settings for projects applying specific plugin - android

We use a company-wide gradle configuration which is applied to all our gradle projects.
Projects using this config might apply different types of plugins (specificially the plugins java or android & android-library). In order to get the sonarRunner plugin to automatically check the android projects, additional properties have to be applied which are not available for java projects.
Now to the question: How can additional sonarRunner (or other) properties be applied only to projects applying a specific (in this case "android" or "android-library") plugin?
What I have tried so far, but does not work as the AndroidPlugin property is not know in the preparation phase:
plugins.withType(AndroidPlugin) {
sonarRunner {
sonarProperties {
property "sonar.profile", "Android"
...
}
}
}

Sounds like the code is missing an import for the AndroidPlugin class. Alternatively, plugins.withId("android") can be used for current gradle versions or afterEvaluate { if (plugins.hasPlugin("android")) { ... } } for gradle 1.12 and earlier.

Related

android.featureVariants get error: Properties not found when migrate from base-feature to dynamic-feature in Gradle

i'm using game engine (Cocos creator) and now I need migrate to Billing v4. When doing, I need support on old device that I need upgrade Gradle Plugin to version 4, then gradle need to migrate from base-feature to dynamic-feature to work, but have some problem need to resolve.
The original Gradle script:
android.featureVariants.all { variant ->
// delete previous files first
delete "${buildDir}/intermediates/merged_assets/"
variant.mergeAssets.doLast {
def sourceDir = "${buildDir}/../../../../.."
copy {
from "${sourceDir}"
include "assets/**"
include "src/**"
include "jsb-adapter/**"
into outputDir
}
copy {
from "${sourceDir}/main.js"
from "${sourceDir}/project.json"
into outputDir
}
}
}
How can I fix the error android.featureVariants properties not found
The build.gradle had migrated from base feature to dymanic feature by
Remove: apply plugin: 'com.android.feature' and change to apply plugin: 'com.android.dynamic-feature' and something at this guide: https://developer.android.com/topic/google-play-instant/feature-module-migration

How can I get list of gradle plugins that a project will use

I would like to get the list of plugins in the Gradle's plugins block. "Project.plugins" will not achieve what I'm looking for. By experimentation, I've discovered that "Project.plugins" is the set of plugins that have already been applied in the project. What I want is the set of plugins declarative defined in the gradle.build script whether the plugin has yet to be applied or not. For example, I have a build.gradle script with a "plugins" block. The first plugin I've added to block is "my.custom.plugin". When it gets applied, for diagnosis purposes it print the list of plugins in "Project.plugins". The printed list I get back contains the following plugins: HelpTasksPlugin, BuildInitPlugin and WrapperPlugin. Here's what the build.gradle script looks like:
plugins{
id("my.custom.plugin")
id("com.android.application")
}
I was hoping that the plugin "com.android.application" would have been in that list. Since it wasn't, that's why I say that "Project.plugins" is the list of applied plugins. "My.custom.plugin" was also not in that list and I guessing that's because the plugin is in the process of being applied, but not yet completed being applied.
What I was hoping to do in "my.custom.plugin" was to see that if the project contains the "com.android.application" plugin, I would do some special processing like configuring android's AppExtension. So my question is: is there a way for me to get the id's of all the plugins in the "plugins" block, whether the plugin has yet to be applied or not? So why not apply the "com.android.application" plugin before applying "my.custom.plugin"? Well the short of that is that I've also discovered that applying "com.android.application" without any "android" AppExtension in the build.gradle fails because it wants to know compileSdkVersion, but it won't know that until "my.custom.plugin is applied which defines that value.
I believe what you actually want to do in your plugin is to create a beforeEvaluate { } hook, which will execute after plugins have been applied, but before Gradle resolves all references to things, giving you a chance to change any settings or setup before tasks execute.
class MyCustomPlugin implements Plugin<Project> {
void apply(Project project) {
project.beforeEvaluate {
if (project.getPluginManager().hasPlugin("com.android.application")) {
throw new GradleException("com.android.application already applied");
} else {
// Do your plugin setup here
project.getPluginManager().apply("com.android.application");
}
}
}
}

Apply Kotlin multiplatform plugin via gradle legacy plugin application

I'm doing some in-depth hands-on with Kotlin Multiplatform Mobile and I'm forced to apply Gradle plugins with the legacy way of applying plugins.
I'm using Kotlin DSL for Gradle and I didn't manage to include the kotlin-multiplatform plugin.
Essentially, there are two ways to include a gradle plugin in your project:
via Gradle Plugins DSL (a modern way)
via legacy plugin application (deprecated but more flexible).
I've basically created a very blank gradle project (gradle init), not related to any IDE or any other dependencies, which both are common for KMM projects - to isolate the issue as much as possible.
The build.gradle.kts below works just fine, when run via ./gradlew clean build (via Plugins DSL)
plugins {
id("org.jetbrains.kotlin.multiplatform") version "1.4.10"
}
kotlin {
jvm()
}
repositories {
jcenter()
}
However, this won't work (via legacy plugin application):
buildscript {
repositories {
maven {
url = uri("https://plugins.gradle.org/m2/")
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
}
}
apply(plugin = "org.jetbrains.kotlin.multiplatform")
kotlin {
jvm()
}
repositories {
jcenter()
}
It fails with this error:
* What went wrong:
Script compilation errors:
Line 12: kotlin {
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public fun DependencyHandler.kotlin(module: String, version: String? = ...): Any defined in org.gradle.kotlin.dsl
public fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec defined in org.gradle.kotlin.dsl
Line 13: jvm()
^ Unresolved reference: jvm
2 errors
It can't resolve the kotlin {} block which is essentially the entry point in KMM projects.
Interestingly, using Groovy instead of Kotlin for Gradle - works in both cases.
But I would like to use Kotlin DSL for Gradle and apply the plugins via the legacy way, since this way I can apply plugins dynamically, i.e. under certain conditions.
In general, you can use apply false in the plugins DSL and call apply conditionally. Apply alone will NEVER work with Kotlin DSL, it only works with dynamic Groovy. Kotlin can work like Groovy if you also use the plugins DSL + apply false in it.
Example:
plugins {
kotlin("multiplatform") apply false // Applied conditionally later
}
For more detailed discussion of the problem check this.

SonarQube not finding Kotlin Junit5 tests

I'm trying to set up a sample android studio project in Github which integrates also its CI connected to SonarQube.
I'm having problems with sonarQube due to it says there is no test coverage applied. However there is, in kotlin and with Juni5, but there is no way to set sonar.tests for recognizing it.
this it the sonar-project.properties
test are run fine either locally and in the CI when a branch of the project is build.
Also I've added this
Gradle has been written with Kotlin-DSL.
if you are using gradle there is no need to define the sources and the tests in the sonar-project.properties. The gradle sonarqube task will pick them up automatically based on your sourcesets.
What i think you are missing is a tool to generate the coverage, sonarqube will not generate coverage data for you. SonarQube utilizes in Java eg. JaCoCo so you also need to apply a plugin for that.
so your build gradle (behold this is groovy dsl, but i will provide a link to one in kotlin) will look something like the following code snippet. This will generate everything automatically
plugins {
id 'java'
id 'jacoco'
id 'eclipse' // optional (to generate Eclipse project files)
id 'idea' // optional (to generate IntelliJ IDEA project files)
id "org.sonarqube" version "2.8"
}
repositories {
jcenter()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.0')
}
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
sonarqube {
properties {
/*
UPDATE SECTION START
Please fill in your data
*/
property "sonar.projectName", "SonarCloud Github Actions with gradle"
property "sonar.projectKey", "aepfli_SonarCloud-GitHubActions-Gradle-example"
property "sonar.organization", "aepfli"
/*
UPDATE SECTION END
*/
property "sonar.host.url", "https://sonarcloud.io"
}
}
jacocoTestReport {
reports {
xml.enabled = true
}
}
Alternatively if you are looking for an example in kotlin DSL, i can recommend this one from JUnit Pioneer.
I am still not sure how good the support for kotlin is with JaCoCo. if there is a different tool like JaCoCo in the Kotlin world, you can also try to generate and XML report and provide this xml report via property sonar.coverage.jacoco.xmlReportPaths base on Sonarqube doc

gradle withJavadocJar() and withSourcesJar() for android library

Is there a way to leverage the new functions withSourcesJar() and withJavadocJar() for Android library projects? Currently when I try to use it I get:
> SourceSet with name 'main' not found.
With the latest Gradle version 6.0.1, there seems to be no way to use these new methods in Android library projects. Here’s why I believe that’s the case:
The two methods withJavadocJar() and withSourcesJar() on the java extension have the default main source set hardcoded, see here and here.
There are two methods with the same names (withJavadocJar() and withSourcesJar()) which can be used in feature variant declarations. However, it seems that Android Gradle builds don’t use feature variants, i.e., these methods can’t be used either.
The documentation states, that these come from the JavaPluginExtension - but not from Android DSL. So they can only be used in conjunction with apply plugin: "java" or apply plugin: "java-library", but not with apply plugin: "com.android.application", apply plugin: "com.android.library" and alike. The name of these tasks also suggest that it's common Java (*.jar) and not Android (*.aar). On Android, this would only make sense for a *.jar library, which uses pure Java features, but no Android features at all (which is limited in functionality).
In short, apply plugin: "java-library" would permit accessing these.
With Gradle 7.2 I "recreated" withJavadocJar and withSourcesJar using Gradle Kotlin DSL:
val sourceFiles = android.sourceSets.getByName("main").java.getSourceFiles()
tasks.register<Javadoc>("withJavadoc") {
isFailOnError = false
dependsOn(tasks.named("compileDebugSources"), tasks.named("compileReleaseSources"))
// add Android runtime classpath
android.bootClasspath.forEach { classpath += project.fileTree(it) }
// add classpath for all dependencies
android.libraryVariants.forEach { variant ->
variant.javaCompileProvider.get().classpath.files.forEach { file ->
classpath += project.fileTree(file)
}
}
source = sourceFiles
}
tasks.register<Jar>("withJavadocJar") {
archiveClassifier.set("javadoc")
dependsOn(tasks.named("withJavadoc"))
val destination = tasks.named<Javadoc>("withJavadoc").get().destinationDir
from(destination)
}
tasks.register<Jar>("withSourcesJar") {
archiveClassifier.set("sources")
from(sourceFiles)
}
Put this into your gradle.build.kts file and then run ./gradlew withJavadocJar and ./gradlew withSourcesJar (or use the tasks to create artifacts for publishing).
android.sourceSets.getByName("main").java.getSourceFiles() is the Android specific part to retrieve the "main" source files.

Categories

Resources