Skip to content

Commit

Permalink
chore: Remove Language annotation usage. Fix deprecations (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszkwiecinski authored Jul 10, 2021
1 parent 0a5d9b1 commit 20961e8
Show file tree
Hide file tree
Showing 21 changed files with 133 additions and 151 deletions.
48 changes: 48 additions & 0 deletions Advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Advanced usage

### Global configuration
Additional default configuration can be applied by adding to the **root project**'s `build.gradle`.
All submodules will use this config as default

``` groovy
plugins {
id("com.starter.config") version("x.y.z)
}
commonConfig {
javaVersion JavaVersion.VERSION_1_8
javaFilesAllowed = true
androidPlugin {
compileSdkVersion 29
minSdkVersion 23
targetSdkVersion 29
}
qualityPlugin {
formatOnCompile = false
}
versioningPlugin {
enabled = true
}
}
```

- `javaVersion` - defines which java version source code is compatible with
- `javaFilesAllowed` - defines if the project can contain java files, fails the build otherwise.
- `androidPlugin`:
- contains values passed to _Android Gradle Plugin_
- `qualityPlugin`:
- `formatOnCompile` - defines if ktlint should format source code on every compilation
- `versioningPlugin`:
- `enabled` - enables/disables [Versioning Plugin](..#versioning-plugin)

### Generating baselines
It is possible to generate baseline for every quality tool available in the project.
- `Android Lint`
Type `rm **/lint-*.xml ; ./gradlew projectLint -PrefreshBaseline --continue` into console
- `Detekt`
Create baseline using [provided configuration](https://github.com/arturbosch/detekt/blob/master/docs/pages/baseline.md)
- `Checkstyle`
Execute `./gradlew generateCheckstyleBaseline` task.
- `ktlint`
Unfortunately it is not possible to generate `ktlint` baseline.
Proper code style may be achieved by using `./gradlew formatKotlin` task.
118 changes: 39 additions & 79 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ___
## Motivation

Maintaining multiple multi-module Android project often requires **copying project configuration across different projects**.
Even when project reaches more advanced stage it is still required to put non minimal effort to maintain its configuration.
Even when project reaches more advanced stage it is still required to put non-minimal effort to maintain its configuration.
Starting a new project, from the scratch, **takes more than a day** to configure every tool you usually want to use.
Sometimes people create template project or another way of keeping your project configuration in a good shape is using `buildSrc` plugins.
Less code written, ease of sharing between projects but still some part of the code needed to be copied.
Expand All @@ -23,16 +23,12 @@ This project goes further and addresses that issue by **exposing set of plugins*
Repository consists of several plugins that makes initial project configuration effortless and easily extensible.
Each module consists of configuration code most commonly used in Android project configuration.

### Getting started

#### Add buildscript dependency

### Plugins Configuration
### Module plugins
#### Kotlin Library Plugin
Plugin configures automated [code style tasks](#quality-plugin), hooks for [common tasks](#day-to-day-use),
Plugin configures [code style tasks](#quality-plugin), hooks for [common tasks](#day-to-day-use),
sets coverage reports generation or manages [versioning](#versioning-plugin) of the artifact

Apply plugin to project level `build.gradle`
Apply plugin to **project** level `build.gradle`

``` groovy
plugins {
Expand All @@ -47,12 +43,21 @@ projectConfig {

- `javaFilesAllowed` - defines if the project can contain java files, fails the build otherwise

#### Multiplatform Library Plugin
For kotlin multiplatform libraries apply plugin to **project** level `build.gradle`

``` groovy
plugins {
id("com.starter.library.multiplatform") version("x.y.z")
}
```

#### Android Application/Library Plugin
In addition to customizations made to [Kotlin Library Plugin](#kotlin-library-plugin) Android plugins
tweak default Android Gradle Plugin setup by disabling _BuildConfig_ file generation
tweaks default Android Gradle Plugin setup by disabling _BuildConfig_ file generation
or recognizing `src/main/kotlin` (and similar) path as a valid source set.

Android Library plugin requires adding to project level `build.gradle`:
Android Library plugin requires adding to **project** level `build.gradle`:

``` groovy
plugins {
Expand Down Expand Up @@ -85,97 +90,52 @@ for example setting `fullDebug` as default variant would make `testFullDebugUnit
`["freeRelease", "fullRelease"]` would make add `testFreeReleaseUnitTest` to `projectTest` and `testFreeReleaseLint` to `projectLint`.
- `coverageExclusions` - defines jacoco coverage exclusions for specific module

#### Quality Plugin
##### Day-to-day use
After applying _Library_/_Application_ plugin following tasks become available:
- `./gradlew projectTest`
Runs tests for all modules using either predefined tasks (i.e. `test` for kotlin modules or `testDebugUnitTest` for android libraries) or use customized values.
- `./gradlew projectLint`
Runs Android lint checks against all modules (if custom lint checks are applied then for Kotlin modules too)
- `./gradlew projectCodeStyle`
Verifies if code style matches modern standards using tools such as [`ktlint`](https://github.com/pinterest/ktlint), [`Detekt`](https://github.com/arturbosch/detekt) or [`Checkstyle`](https://checkstyle.org/) with predefined config.
- `./gradlew projectCoverage`
Automatically generates test coverage reports for all modules using [`Jacoco`](https://github.com/jacoco/jacoco)

Quality plugin is applied automatically by a _Module plugin_, but there is a possibility to use it as a standalone plugin.
Apply plugin to project level `build.gradle`
Those tasks allows you to run tests efficiently for all modules by typing just a single task.

### Standalone plugins
#### Quality Plugin
To only configure codestyle tools apply plugin to **project** level `build.gradle`
```
plugins {
id("com.starter.quality") version("x.y.z")
}
```
which applies and configures code style tasks for the project automatically.
To execute run: `./gradlew projectCodeStyle` to check codestyl or `./gradlew issueLinksReport` to find and check state of all issuetracker links linked in code comments.

##### Generating baselines

When integrating code style checks into large projects it is almost forbidden to introduce large sets of changes.
It is possible to generate baseline for every quality tool available in the project.
- `Android Lint`
Type `rm **/lint-*.xml ; ./gradlew projectLint -PrefreshBaseline --continue` into console
- `Detekt`
Create baseline using [provided configuration](https://github.com/arturbosch/detekt/blob/master/docs/pages/baseline.md)
- `Checkstyle`
Execute `./gradlew generateCheckstyleBaseline` task.
- `ktlint`
Unfortunately it is not possible to generate `ktlint` baseline.
Proper code style may be achieved by using `./gradlew formatKotlin` task.

Tasks available:
- `./gradlew projectCodeStyle` - checks codestyle using all tools
- `./gradlew issueLinksReport` - finds and check state of all issuetracker links linked in code comments

Quality Plugin gets applied automatically when using any of module _Application_/_Library_ plugins above.

#### Versioning Plugin

Applied automatically.
Uses tag-based versioning backed by the [allegro/axion-release-plugin](https://github.com/allegro/axion-release-plugin) (view a [full documentation](https://github.com/allegro/axion-release-plugin))

To enable it as a standalone plugin, apply plugin to root project `build.gradle`
```
apply plugin: 'com.starter.versioning'
```
Can be disabled using [Global Configuration](#global-configuration)
Versioning plugin gets applied automatically when using any of module _Application_/_Library_ plugins above and can be disabled using [Global Configuration](Advanced.md#global-configuration)

Regular flow relies on calling
- `./gradlew cV` or `./gradlew currentVersion`
- `./gradlew markNextVersion -Prelease.version=1.0.0`
- `./gradlew release` (which pushes proper tags to remote server)

#### Global configuration

Additional default configuration can be applied by adding to **root project** `build.gradle`.
All submodules will use this config as default

``` groovy
plugins {
id("com.starter.config") version("x.y.z)
}
commonConfig {
javaVersion JavaVersion.VERSION_1_8
javaFilesAllowed = true
androidPlugin {
compileSdkVersion 29
minSdkVersion 23
targetSdkVersion 29
}
qualityPlugin {
formatOnCompile = false
}
versioningPlugin {
enabled = true
}
}
```

- `javaVersion` - defines which java version source code is compatible with
- `javaFilesAllowed` - defines if the project can contain java files, fails the build otherwise.
- `androidPlugin`:
- contains values passed to _Android Gradle Plugin_
- `qualityPlugin`:
- `formatOnCompile` - defines if ktlint should format source code on every compilation
- `versioningPlugin`:
- `enabled` - enables/disables [Versioning Plugin](#versioning-plugin)

### Day-to-day use
After applying library/application plugin there are appropriate tasks added:
- `./gradlew projectTest`
Runs tests for all modules using either predefined tasks (i.e. `test` for kotlin modules or `testDebugUnitTest` for android libraries) or use customized values.
- `./gradlew projectLint`
Runs Android lint checks against all modules (if custom lint checks are applied then for Kotlin modules too)
- `./gradlew projectCodeStyle`
Verifies if code style matches modern standards using tools such as [`ktlint`](https://github.com/pinterest/ktlint), [`Detekt`](https://github.com/arturbosch/detekt) or [`Checkstyle`](https://checkstyle.org/) with predefined config.
- `./gradlew projectCoverage`
Automatically generates test coverage reports for all modules using [`Jacoco`](https://github.com/jacoco/jacoco)

Those tasks allows you to run tests efficiently for all modules by typing just a single task.
That solves an issue when for example `test` task unnecessarily executes tests for all build variants and more strict `testDebug` skips executing tests in kotlin only modules.
### Advanced usage
See [Advanced usage](Advanced.md)

## Sample project
Sample [Github Browser](https://github.com/mateuszkwiecinski/github_browser) project - a customized, `buildSrc` based plugin application.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.project.starter.modules.internal

import com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.TestedExtension
import com.android.build.gradle.api.BaseVariant
Expand All @@ -16,8 +15,6 @@ import com.project.starter.quality.internal.configureAndroidCoverage
import org.gradle.api.DomainObjectSet
import org.gradle.api.Project

private const val LAST_STABLE_AGP_VERSION = 4

internal fun BaseExtension.configureAndroidPlugin(rootConfig: RootConfigExtension) {
defaultConfig.apply {
compileSdkVersion(rootConfig.android.compileSdkVersion)
Expand All @@ -26,11 +23,6 @@ internal fun BaseExtension.configureAndroidPlugin(rootConfig: RootConfigExtensio
setTestInstrumentationRunner("androidx.test.runner.AndroidJUnitRunner")
}

if (ANDROID_GRADLE_PLUGIN_VERSION.split(".").firstOrNull()?.toIntOrNull() ?: 0 <= LAST_STABLE_AGP_VERSION) {
@Suppress("deprecation")
dexOptions.preDexLibraries = true
}

addKotlinSourceSets()

compileOptions.apply {
Expand All @@ -42,13 +34,10 @@ internal fun BaseExtension.configureAndroidPlugin(rootConfig: RootConfigExtensio
internal fun Project.configureAndroidProject(variants: DomainObjectSet<out BaseVariant>, projectConfig: AndroidExtension) {
configureAndroidCoverage(variants, projectConfig.coverageExclusions)
val findBuildVariants = {
if (projectConfig.defaultVariants.isEmpty()) {
val default = variants.firstOrNull { it.buildType.name == "debug" }
?: variants.first()
projectConfig.defaultVariants.ifEmpty {
val default = variants.firstOrNull { it.buildType.name == "debug" } ?: variants.first()

listOf(default.name.capitalize())
} else {
projectConfig.defaultVariants
}
}
registerProjectLintTask { projectLint ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ internal fun Project.configureAndroidCoverage(variants: DomainObjectSet<out Base
report.description = "Generates Jacoco coverage reports for the ${variant.name} variant."

report.reports {
it.html.isEnabled = true
it.xml.isEnabled = true
it.html.required.set(true)
it.xml.required.set(true)
}

val sourceDirs = variant.sourceSets.flatMap { it.javaDirectories }
val classesDir = variant.javaCompileProvider.get().destinationDir
val classesDir = variant.javaCompileProvider.get().destinationDirectory.get().asFile
val executionData = jacocoTestTaskExtension.destinationFile

val coverageExcludes = excludes + projectExclusions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.project.starter.modules.tasks

import com.project.starter.WithGradleProjectTest
import com.project.starter.javaClass
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
Expand All @@ -20,7 +19,7 @@ internal class ConfigurationCacheTest : WithGradleProjectTest() {

resolve("build.gradle").writeText("")
androidModuleRoot = resolve("module1") {
@Language("groovy")
// language=groovy
val script =
"""
plugins {
Expand All @@ -46,7 +45,7 @@ internal class ConfigurationCacheTest : WithGradleProjectTest() {
}
}
kotlinModuleRoot = resolve("module2") {
@Language("groovy")
// language=groovy
val script =
"""
plugins {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.project.starter.WithGradleProjectTest
import com.project.starter.javaClass
import org.assertj.core.api.Assertions.assertThat
import org.gradle.testkit.runner.TaskOutcome
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.File
Expand All @@ -20,7 +19,7 @@ internal class GenerateCheckstyleBaselineTaskTest : WithGradleProjectTest() {

resolve("build.gradle").writeText("")
moduleRoot = resolve("javaModule") {
@Language("groovy")
// language=groovy
val script =
"""
plugins {
Expand Down Expand Up @@ -64,7 +63,7 @@ internal class GenerateCheckstyleBaselineTaskTest : WithGradleProjectTest() {
@Test
fun `generating baseline makes build to pass on old code, but fail on new one`() {
moduleRoot.resolve("src/test/java/OldCode.java") {
@Language("java")
// language=java
val javaClass =
"""
public class OldCode {
Expand All @@ -84,7 +83,7 @@ internal class GenerateCheckstyleBaselineTaskTest : WithGradleProjectTest() {
assertThat(checkStyleOldCode.task(":javaModule:checkstyle")?.outcome).isEqualTo(TaskOutcome.SUCCESS)

moduleRoot.resolve("src/test/java/NewCode.java") {
@Language("java")
// language=java
val javaClass =
"""
public class NewCode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.project.starter.WithGradleProjectTest
import com.project.starter.commit
import com.project.starter.setupGit
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
Expand Down Expand Up @@ -32,7 +31,7 @@ internal class AndroidVersioningPluginTest : WithGradleProjectTest() {
)
}
resolve("build.gradle") {
@Language("gradle")
// language=groovy
val buildscript =
"""
plugins {
Expand Down
Loading

0 comments on commit 20961e8

Please sign in to comment.