Skip to content

Commit

Permalink
Added Develocity plugin for build scans and remote build cache (#4311)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mr3zee authored Sep 23, 2024
1 parent 4e42dd5 commit 69e2cab
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ gradle-user-home

.fleet
.kotlin

scan-journal.log
27 changes: 27 additions & 0 deletions docs/develocity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Develocity usage guide

> [!NOTE]
> Build scans and remote build cache are for JetBrains developers only.
>
> To disable publishing attempts, add `ktor.develocity.skipBuildScans=true` property
to your `~/.gradle/gradle.properties` file

Develocity is configured for this project.
That means that you can use both [build scans](https://docs.gradle.org/current/userguide/build_scans.html)
and remote [build cache](https://docs.gradle.org/current/userguide/build_cache.html)
features.

To use build scans, first you need to log in here: https://ge.jetbrains.com.
You can do that directly in Gradle:

```Bash
./gradlew :provisionDevelocityAccessKey
```

Sing in with your Google work account, and that is it.
Now your scans will automatically be published after each build, and
Gradle will read the remote build caches so that your local build may be faster.

This also allows you to check various metrics about your scans (https://ge.jetbrains.com).

Build scan logs are collected locally in the `scan-journal.log` file.
17 changes: 17 additions & 0 deletions gradle-settings-conventions/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

plugins {
`kotlin-dsl`
}

repositories {
mavenCentral()
gradlePluginPortal()
}

dependencies {
implementation("com.gradle:develocity-gradle-plugin:3.17")
implementation("com.gradle:common-custom-user-data-gradle-plugin:2.0.1")
}
5 changes: 5 additions & 0 deletions gradle-settings-conventions/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

rootProject.name = "gradle-conventions-settings"
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import java.util.*

plugins {
id("com.gradle.develocity")
id("com.gradle.common-custom-user-data-gradle-plugin")
}

develocity {
val startParameter = gradle.startParameter
val scanJournal = File(settingsDir, "scan-journal.log")

server = DEVELOCITY_SERVER

buildScan {
uploadInBackground = !isCIRun

// obfuscate NIC since we don't want to expose user real IP (will be relevant without VPN)
obfuscation {
ipAddresses { addresses -> addresses.map { _ -> "0.0.0.0" } }
}

capture {
fileFingerprints = true
}

buildScanPublished {
scanJournal.appendText("${Date()}$buildScanUri$startParameter\n")
}

val skipBuildScans = settings.providers.gradleProperty("ktor.develocity.skipBuildScans")
.getOrElse("false")
.toBooleanStrict()

publishing.onlyIf { !skipBuildScans }
}
}

buildCache {
if (isCIRun) {
local {
isEnabled = false
}
}

remote(develocity.buildCache) {
isPush = isCIRun
isEnabled = true
}
}

enrichTeamCityData()
enrichGitData()
64 changes: 64 additions & 0 deletions gradle-settings-conventions/src/main/kotlin/customization.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import com.gradle.develocity.agent.gradle.DevelocityConfiguration
import org.gradle.api.initialization.Settings

fun Settings.enrichTeamCityData() {
val ge = extensions.getByType(DevelocityConfiguration::class.java)

gradle.projectsEvaluated {
if (isCIRun) {
val buildTypeId = "teamcity.buildType.id"
val buildId = "teamcity.build.id"

if (gradle.rootProject.hasProperty(buildId) && gradle.rootProject.hasProperty(buildTypeId)) {
val buildIdValue = gradle.rootProject.property(buildId).toString()
val teamCityBuildNumber = java.net.URLEncoder.encode(buildIdValue, "UTF-8")
val teamCityBuildTypeId = gradle.rootProject.property(buildTypeId)

ge.buildScan.link(
"Ktor TeamCity build",
"${TEAMCITY_URL}/buildConfiguration/${teamCityBuildTypeId}/${teamCityBuildNumber}"
)
}

if (gradle.rootProject.hasProperty(buildId)) {
ge.buildScan.value("CI build id", gradle.rootProject.property(buildId) as String)
}
}
}
}

fun Settings.enrichGitData() {
val ge = extensions.getByType(DevelocityConfiguration::class.java)

val skipGitTags = settings.providers.gradleProperty("ktor.develocity.skipGitTags")
.getOrElse("false")
.toBooleanStrict()

gradle.projectsEvaluated {
if (!isCIRun && !skipGitTags) {
// Git commit id
val commitId = execute("git rev-parse --verify HEAD")
if (commitId.isNotEmpty()) {
ge.buildScan.value("Git Commit ID", commitId)
ge.buildScan.link("GitHub Commit Link", "$GITHUB_REPO/tree/$commitId")
}

// Git branch name
val branchName = execute("git rev-parse --abbrev-ref HEAD")
if (branchName.isNotEmpty()) {
ge.buildScan.value("Git Branch Name", branchName)
ge.buildScan.link("GitHub Branch Link", "$GITHUB_REPO/tree/$branchName")
}

// Git dirty local state
val status = execute("git status --porcelain")
if (status.isNotEmpty()) {
ge.buildScan.value("Git Status", status)
}
}
}
}
12 changes: 12 additions & 0 deletions gradle-settings-conventions/src/main/kotlin/execute.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

import org.gradle.api.initialization.Settings

@Suppress("UnstableApiUsage")
fun Settings.execute(cmd: String): String {
return settings.providers.exec {
commandLine(cmd.split(" "))
}.standardOutput.asText.get().trim()
}
9 changes: 9 additions & 0 deletions gradle-settings-conventions/src/main/kotlin/params.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/

const val DEVELOCITY_SERVER = "https://ge.jetbrains.com"
const val GITHUB_REPO = "https://github.com/ktorio/ktor"
const val TEAMCITY_URL = "https://ktor.teamcity.com"

val isCIRun = System.getenv("TEAMCITY_VERSION") != null
8 changes: 8 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ kotlin.daemon.useFallbackStrategy=false
# dokka
# workaround for resolving platform dependencies, see https://github.com/Kotlin/dokka/issues/3153
org.jetbrains.dokka.classpath.useNativeDistributionAccessor=true

# Uncomment to skip attempts to publish Develocity build scans
# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes
#ktor.develocity.skipBuildScans=true

# Uncomment to skip adding git tags to Develocity build scan
# Add this property to ~/.gradle/gradle.properties to avoid polluting git with unwanted changes
#ktor.develocity.skipGitTags=true
22 changes: 6 additions & 16 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,21 @@
*/

pluginManagement {
includeBuild("gradle-settings-conventions")

repositories {
mavenCentral()
google()
gradlePluginPortal()
}
}

rootProject.name = "ktor"

val CACHE_USER = System.getenv("GRADLE_CACHE_USER")

if (CACHE_USER != null) {
val CACHE_PASSWORD = System.getenv("GRADLE_CACHE_PASSWORD")
buildCache {
remote(HttpBuildCache::class) {
isPush = true
setUrl("https://ktor-gradle-cache.teamcity.com/cache/")
credentials {
username = CACHE_USER
password = CACHE_PASSWORD
}
}
}
plugins {
id("conventions-develocity")
}

rootProject.name = "ktor"

val fullVersion = System.getProperty("java.version", "8.0.0")
val versionComponents = fullVersion
.split(".")
Expand Down

0 comments on commit 69e2cab

Please sign in to comment.