Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convention sample for single build Gradle plugin and Maven extension is added #1315

Merged
merged 8 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ updates:
schedule:
interval: "daily"
time: "02:00"
- package-ecosystem: "gradle"
directory: "convention-develocity-shared"
registries:
- gradle-plugin-portal
schedule:
interval: "daily"
time: "02:00"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
129 changes: 129 additions & 0 deletions .github/workflows/convention-develocity-shared-verification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: Verify Convention Develocity Shared

on:
push:
branches: [ main ]
paths: [ 'convention-develocity-shared/**', '.github/workflows/convention-develocity-shared-verification.yml' ]
pull_request:
branches: [ main ]
paths: [ 'convention-develocity-shared/**', '.github/workflows/convention-develocity-shared-verification.yml' ]
workflow_dispatch:

jobs:
build:
name: Build Convention Develocity Shared
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
- name: Build with Gradle
working-directory: convention-develocity-shared
run: ./gradlew build publishToMavenLocal
- name: Upload convention
uses: actions/upload-artifact@v4
with:
name: convention-develocity-shared
path: ~/.m2/repository/com/myorg

verification_gradle:
name: Verify Example Build for Gradle ${{ matrix.versions.version }}
needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
versions:
- sample: '5'
version: '5.0'
- sample: '6'
version: '6.0.1'
- sample: '6.9_and_later'
version: '6.9.4'
- sample: '6.9_and_later'
version: '7.0.2'
- sample: '6.9_and_later'
version: '8.0.2'
- sample: '6.9_and_later'
version: '(Current)'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
- name: Download plugin
uses: actions/download-artifact@v4
with:
name: convention-develocity-shared
path: ~/.m2/repository/com/myorg
- name: Set Gradle version
if: ${{ matrix.versions.version != '(Current)' }}
working-directory: convention-develocity-shared/examples/gradle_${{ matrix.versions.sample }}
run: |
sed -i '/distributionSha256Sum.*/d' gradle/wrapper/gradle-wrapper.properties
./gradlew wrapper --gradle-version=${{ matrix.versions.version }} --no-scan
./gradlew wrapper --gradle-version=${{ matrix.versions.version }} --no-scan
- name: Verify example build
id: build
working-directory: convention-develocity-shared/examples/gradle_${{ matrix.versions.sample }}
run: ./gradlew build -Ddevelocity.url=https://ge.solutions-team.gradle.com
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }}
- name: Verify Build Scan published
if: ${{ !steps.build.outputs.build-scan-url }}
run: echo "::error ::No Build Scan published"; exit 1

verification_maven:
name: Verify Example Build for Maven ${{ matrix.versions.version }}
needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
versions:
- sample: '3'
version: '3.6.3'
- sample: '3'
version: '3.8.8'
- sample: '3'
version: '(Current)'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin'
cache: maven
- name: Set up Maven
uses: gradle/develocity-actions/[email protected]
- name: Download extension
uses: actions/download-artifact@v4
with:
name: convention-develocity-shared
path: ~/.m2/repository/com/myorg
- name: Set Maven version
if: ${{ matrix.versions.version != '(Current)' }}
working-directory: convention-develocity-shared/examples/maven_${{ matrix.versions.sample }}
run: ./mvnw wrapper:wrapper -Dmaven=${{ matrix.versions.version }} -Ddevelocity.scan.disabled
- name: Verify example build
id: build
working-directory: convention-develocity-shared/examples/maven_${{ matrix.versions.sample }}
run: ./mvnw clean verify -Ddevelocity.url=https://ge.solutions-team.gradle.com
env:
DEVELOCITY_ACCESS_KEY: ${{ secrets.DV_SOLUTIONS_ACCESS_KEY }}
- name: Verify Build Scan published
if: ${{ !steps.build.outputs.build-scan-url }}
run: echo "::error ::No Build Scan published"; exit 1
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The samples can be grouped into the following categories:
- Configuration snippets to capture additional data in build scans
- Configuration snippets to optimize build performance
- Template projects for Gradle and Maven when using Develocity
- Scripts and code to apply and reuse Develocity across multiple projects
- Scripts and code to apply and reuse Develocity across multiple projects and build tools

## Learn more

Expand Down
2 changes: 1 addition & 1 deletion convention-develocity-gradle-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ cd plugins/gradle-5-or-newer
./gradlew publishToMavenLocal
```

Once you have published the plugins, you can run the four example builds under `examples`:
Once you have published the plugins, you can run the example builds under `examples`:

```bash
cd examples/gradle_6_and_later
Expand Down
143 changes: 143 additions & 0 deletions convention-develocity-shared/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
## Convention Develocity Shared

This project demonstrates how a convention Gradle plugin and Maven extension can share the same Develocity build configuration across multiple projects.
It is intended to serve as a starting point for creating your own Gradle plugin and Maven extension that applies your specific Develocity configuration.
Note the inline comments in the build and source code for things to adjust specifically to your needs.

### Applying the extension to your build

#### Gradle

##### Using a dynamic version

For builds using Gradle 6.9 and later, it's recommended to apply the convention plugin using a [dynamic version](https://docs.gradle.org/current/userguide/dynamic_versions.html).
This approach ensures that the latest version of the plugin is automatically used, but only for the specified major version.
For example, the following will automatically use the latest `1.x` version of the plugin up to, but excluding, version `2.0`:

```groovy
plugins {
id 'com.myorg.convention-develocity-gradle-plugin' version '1.+'
}
```

This allows you to quickly roll out non-breaking changes to all consumers of the convention plugin.
Breaking changes in the plugin should be released under a new major version, e.g., `2.0`.
All consumers of the plugin will then need to update the specified major version, e.g., `2.+`.

> [!IMPORTANT]
> Using dynamic versions should only be done when releases and development versions are published to separate repositories.
> Not having this separation introduces the risk that consumers will use a development version of the plugin not yet ready to be used.
> In these scenarios, using a static version is preferred.

##### Using a static version

For projects using earlier versions of Gradle, the convention plugin must be applied using a static version.
For example:

```groovy
plugins {
id 'com.myorg.convention-develocity-gradle-plugin' version '1.0'
}
```

For each new release of the convention plugin, consuming builds will need to be explicitly updated.

#### Maven

##### Using a version range

It's recommended to apply the convention extension using a [version range](https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html).
This approach ensures that the latest version of the extension is automatically used, up to the specified maximum version.
For example, the following will automatically use the latest version of the extension up to, but excluding, version `2.0`:

```xml
<extensions>
<extension>
<groupId>com.myorg</groupId>
<artifactId>convention-develocity-maven-extension</artifactId>
<version>(,2.0)</version>
</extension>
</extensions>
```

This allows you to quickly roll out non-breaking changes to all consumers of the convention extension.
Breaking changes in the extension should be released under a new major version, e.g., `2.0`.
All consumers of the extension will then need to update the upper boundary of the version range to the next major version, e.g., `(,3.0)`.

> [!IMPORTANT]
> Using version ranges should only be done when releases and development versions are published to separate repositories.
> Not having this separation introduces the risk that consumers will use a development version of the extension not yet ready to be used.
> In these scenarios, using a static version is preferred.

##### Using a static version

In scenarios where a version range can't be used, e.g., when releases and development versions are published to the same repository, a static version should be used.
For example:

```xml
<extensions>
<extension>
<groupId>com.myorg</groupId>
<artifactId>convention-develocity-maven-extension</artifactId>
<version>1.0</version>
</extension>
</extensions>
```

For each new release of the convention extension, consuming builds will need to be explicitly updated.

### Content

This project is structured as follows:

* `convention-develocity-common` - Contains the common convention logic shared between build tools
* `convention-develocity-gradle-plugin` - Contains the convention Gradle plugin
* `convention-develocity-maven-extension` - Contains the convention Maven extension
* `examples` - Contains example builds that apply the convention Gradle plugin or Maven extension for different Gradle and Maven versions
* `gradle_5` - Applies the convention Gradle plugin on a Gradle 5 build
* `gradle_6` - Applies the convention Gradle plugin on a Gradle 6 build
* `gradle_6.9_and_later` - Applies the convention Gradle plugin on a Gradle 6.9 and later build
* `maven_3` - Applies the convention Maven extension on a Maven 3 build

### Running the example builds

Before running the example builds, publish all components to your local Maven repository.

```bash
./gradlew publishToMavenLocal
```

> [!NOTE]
> You would publish these components to your internal artifact provider, e.g., Artifactory or Nexus, for production usage.
> The shared convention plugin at `buildSrc/src/main/kotlin/com.myorg.publishing-conventions.gradle.kts` can be used to configure the publishing of all components.

#### Gradle

Once you have published the plugin, you can run the three example builds under `examples`:

```bash
cd examples/gradle_5
./gradlew build

cd examples/gradle_6
./gradlew build

cd examples/gradle_6_and_later
./gradlew build
```

#### Maven

Once you have installed the extension, you can run the example build under `examples`:

```bash
cd examples/maven_3
./mvnw clean verify
```

> [!IMPORTANT]
> The artifact provider must be configured as a [Mirror](https://maven.apache.org/guides/mini/guide-mirror-settings.html) to Maven Central in order to correctly resolve the extension.

#### Requirements

To run the example builds, use Java 8 or higher.
7 changes: 7 additions & 0 deletions convention-develocity-shared/buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
`kotlin-dsl`
}

repositories {
gradlePluginPortal()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import org.gradle.jvm.toolchain.JavaLanguageVersion

plugins {
id("java")
}

java {
withJavadocJar()
withSourcesJar()
toolchain {
languageVersion = JavaLanguageVersion.of(8)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id("maven-publish")
}

publishing {
repositories {
maven {
// CHANGE ME: change to point to your organization's artifact repository
url = uri("https://repo.myorg.com/maven")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
id("com.myorg.java-conventions")
id("com.myorg.publishing-conventions")
id("java-library")
}

publishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.myorg;

import com.myorg.configurable.BuildCacheConfigurable;
import com.myorg.configurable.BuildScanConfigurable;
import com.myorg.configurable.DevelocityConfigurable;

final class DevelocityConventions {

void configureDevelocity(DevelocityConfigurable develocity) {
// CHANGE ME: Apply your Develocity configuration here
develocity.setServer("https://develocity-samples.gradle.com");
configureBuildScan(develocity.getBuildScan());
configureBuildCache(develocity.getBuildCache());
}

private void configureBuildScan(BuildScanConfigurable buildScan) {
// CHANGE ME: Apply your Build Scan configuration here
buildScan.setUploadInBackground(!isCi());
}

private void configureBuildCache(BuildCacheConfigurable buildCache) {
// CHANGE ME: Apply your Build Cache configuration here
buildCache.getLocal().setEnabled(true);
buildCache.getLocal().setStoreEnabled(true);
buildCache.getRemote().setEnabled(true);
buildCache.getRemote().setStoreEnabled(isCi());
}

private static boolean isCi() {
// CHANGE ME: Apply your environment detection logic here
return System.getenv().containsKey("CI");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.myorg.configurable;

public interface BuildCacheConfigurable {

LocalBuildCacheConfigurable getLocal();

RemoteBuildCacheConfigurable getRemote();

}
Loading