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

Modernize the maven build #1496

Merged
merged 18 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ jobs:
- name: spotlessCheck
run: ./gradlew spotlessCheck --build-cache
- name: assemble testClasses
run: ./gradlew assemble testClasses --build-cache -PSPOTLESS_EXCLUDE_MAVEN=true
# If this gets resolved, remove the EXCLUDE_MAVEN https://github.com/diffplug/spotless/issues/554
run: ./gradlew assemble testClasses --build-cache
build:
needs: sanityCheck
strategy:
Expand Down
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (

## [Unreleased]
### Added
* `ProcessRunner` has added some convenience methods so it can be used for maven testing. ([#1496](https://github.com/diffplug/spotless/pull/1496))
### Fixed
* The default list of type annotations used by `formatAnnotations` has had 8 more annotations from the Checker Framework added [#1494](https://github.com/diffplug/spotless/pull/1494)
### Changes
Expand Down
8 changes: 1 addition & 7 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,4 @@ VER_DURIAN=1.2.0
VER_JGIT=5.13.1.202206130422-r
VER_JUNIT=5.9.2
VER_ASSERTJ=3.24.2
VER_MOCKITO=4.11.0

# Used for Maven Plugin
VER_MAVEN_API=3.0
VER_ECLIPSE_AETHER=1.1.0
VER_MUSTACHE=0.9.10
VER_PLEXUS_RESOURCES=1.2.0
VER_MOCKITO=4.11.0
4 changes: 2 additions & 2 deletions lib-extra/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ dependencies {
// we'll hold the core lib to a high standard
spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes)

test {
useJUnitPlatform()
apply from: rootProject.file('gradle/special-tests.gradle')
tasks.named('test') {
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16)) {
// needed for EclipseCdtFormatterStepTest
jvmArgs '--add-opens=java.base/java.lang=ALL-UNNAMED'
Expand Down
5 changes: 1 addition & 4 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,7 @@ dependencies {
// we'll hold the core lib to a high standard
spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes)

tasks.withType(Test).configureEach {
useJUnitPlatform()
}

apply from: rootProject.file('gradle/special-tests.gradle')
jar {
for (glue in NEEDS_GLUE) {
from sourceSets.getByName(glue).output.classesDirs
Expand Down
41 changes: 36 additions & 5 deletions lib/src/main/java/com/diffplug/spotless/ProcessRunner.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 DiffPlug
* Copyright 2020-2023 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,18 +16,22 @@
package com.diffplug.spotless;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.BiConsumer;

import edu.umd.cs.findbugs.annotations.Nullable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

/**
Expand Down Expand Up @@ -55,13 +59,18 @@ public Result shell(String cmd) throws IOException, InterruptedException {

/** Executes the given shell command (using {@code cmd} on windows and {@code sh} on unix). */
public Result shellWinUnix(String cmdWin, String cmdUnix) throws IOException, InterruptedException {
return shellWinUnix(null, null, cmdWin, cmdUnix);
}

/** Executes the given shell command (using {@code cmd} on windows and {@code sh} on unix). */
public Result shellWinUnix(@Nullable File cwd, @Nullable Map<String, String> environment, String cmdWin, String cmdUnix) throws IOException, InterruptedException {
List<String> args;
if (FileSignature.machineIsWin()) {
args = Arrays.asList("cmd", "/c", cmdWin);
} else {
args = Arrays.asList("sh", "-c", cmdUnix);
}
return exec(args);
return exec(cwd, environment, null, args);
}

/** Creates a process with the given arguments. */
Expand All @@ -70,18 +79,32 @@ public Result exec(String... args) throws IOException, InterruptedException {
}

/** Creates a process with the given arguments, the given byte array is written to stdin immediately. */
public Result exec(byte[] stdin, String... args) throws IOException, InterruptedException {
public Result exec(@Nullable byte[] stdin, String... args) throws IOException, InterruptedException {
return exec(stdin, Arrays.asList(args));
}

/** Creates a process with the given arguments. */
public Result exec(List<String> args) throws IOException, InterruptedException {
return exec(new byte[0], args);
return exec(null, args);
}

/** Creates a process with the given arguments, the given byte array is written to stdin immediately. */
public Result exec(byte[] stdin, List<String> args) throws IOException, InterruptedException {
public Result exec(@Nullable byte[] stdin, List<String> args) throws IOException, InterruptedException {
return exec(null, null, stdin, args);
}

/** Creates a process with the given arguments, the given byte array is written to stdin immediately. */
public Result exec(@Nullable File cwd, @Nullable Map<String, String> environment, @Nullable byte[] stdin, List<String> args) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder(args);
if (cwd != null) {
builder.directory(cwd);
}
if (environment != null) {
builder.environment().putAll(environment);
}
if (stdin == null) {
stdin = new byte[0];
}
Process process = builder.start();
Future<byte[]> outputFut = threadStdOut.submit(() -> drainToBytes(process.getInputStream(), bufStdOut));
Future<byte[]> errorFut = threadStdErr.submit(() -> drainToBytes(process.getErrorStream(), bufStdErr));
Expand Down Expand Up @@ -147,6 +170,14 @@ public byte[] stdErr() {
return stdErr;
}

public String stdOutUtf8() {
return new String(stdOut, StandardCharsets.UTF_8);
}

public String stdErrUtf8() {
return new String(stdErr, StandardCharsets.UTF_8);
}

/** Returns true if the exit code was not zero. */
public boolean exitNotZero() {
return exitCode != 0;
Expand Down
6 changes: 2 additions & 4 deletions plugin-gradle/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,11 @@ dependencies {
testImplementation "com.diffplug.durian:durian-testlib:${VER_DURIAN}"
}

test {
useJUnitPlatform()
apply from: rootProject.file('gradle/special-tests.gradle')
tasks.named('test') {
testLogging.showStandardStreams = true
}

apply from: rootProject.file('gradle/special-tests.gradle')

//////////////////////////
// GRADLE PLUGIN PORTAL //
//////////////////////////
Expand Down
1 change: 1 addition & 0 deletions plugin-maven/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
### Fixed
* The default list of type annotations used by `formatAnnotations` has had 8 more annotations from the Checker Framework added [#1494](https://github.com/diffplug/spotless/pull/1494)
### Changes
* Spotless' custom build was replaced by [`maven-plugin-development`](https://github.com/britter/maven-plugin-development). ([#1496](https://github.com/diffplug/spotless/pull/1496) fixes [#554](https://github.com/diffplug/spotless/issues/554))

## [2.30.0] - 2023-01-13
### Added
Expand Down
188 changes: 23 additions & 165 deletions plugin-maven/build.gradle
Original file line number Diff line number Diff line change
@@ -1,71 +1,29 @@
buildscript {
repositories { mavenCentral() }
dependencies { classpath "com.github.spullara.mustache.java:compiler:${VER_MUSTACHE}" }
}
plugins {
id 'cz.malohlava.visteg' version '1.0.5' // https://github.com/mmalohlava/gradle-visteg
// https://www.benediktritter.de/maven-plugin-development/#release-history
id 'de.benediktritter.maven-plugin-development' version '0.4.0'
}

repositories { mavenCentral() }
apply from: rootProject.file('gradle/changelog.gradle')
apply from: rootProject.file('gradle/spotless-freshmark.gradle')

// to generate taskGraph.pdf
// - set enabled (below) to true
// - run: ./gradlew :plugin-maven:test
// - run: rm plugin-maven/output.pdf
// - run: dot -Tpdf plugin-maven/build/reports/visteg.dot > plugin-maven/taskGraph.pdf
visteg {
enabled = false
nodeShape = 'box'
startNodeShape = 'box'
endNodeShape = 'box'
colorscheme = 'pastel24' // https://www.graphviz.org/doc/info/colors.html
}

import com.github.mustachejava.DefaultMustacheFactory

import java.nio.file.Files

import static java.nio.charset.StandardCharsets.UTF_8
import static java.nio.file.StandardOpenOption.CREATE
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING

ext.artifactId = project.artifactIdMaven
version = spotlessChangelog.versionNext
apply from: rootProject.file("gradle/java-setup.gradle")
apply from: rootProject.file("gradle/java-publish.gradle")

final MAVEN_PROJECT_DIR = project.layout.buildDirectory.dir("mavenProject").get()
final LOCAL_MAVEN_REPO_DIR = project.layout.buildDirectory.dir("localMavenRepository").get()
apply from: rootProject.file("gradle/java-setup.gradle")
apply from: rootProject.file('gradle/spotless-freshmark.gradle')

def mvnw(String args) {
boolean isWin = System.getProperty('os.name').toLowerCase().contains('win')
if (isWin) {
return [
'cmd',
'/c',
'mvnw.cmd -e ' + args
]
} else {
return [
'/bin/sh',
'-c',
'./mvnw -e ' + args
]
}
apply plugin: 'de.benediktritter.maven-plugin-development'
mavenPlugin {
name = 'Spotless Maven Plugin'
artifactId = project.artifactIdMaven
description = project.description
}

String libVersion = version.endsWith('-SNAPSHOT') ?
rootProject.spotlessChangelog.versionNext :
rootProject.spotlessChangelog.versionLast
String VER_MAVEN_API = '3.0'
String VER_ECLIPSE_AETHER = '1.1.0'
String VER_PLEXUS_RESOURCES = '1.2.0'
dependencies {
if (version.endsWith('-SNAPSHOT') || (rootProject.spotlessChangelog.versionNext == rootProject.spotlessChangelog.versionLast)) {
implementation project(':lib')
implementation project(':lib-extra')
} else {
implementation "com.diffplug.spotless:spotless-lib:${libVersion}"
implementation "com.diffplug.spotless:spotless-lib-extra:${libVersion}"
}
implementation project(':lib')
implementation project(':lib-extra')

compileOnly "org.apache.maven:maven-plugin-api:${VER_MAVEN_API}"
compileOnly "org.apache.maven.plugin-tools:maven-plugin-annotations:${VER_MAVEN_API}"
Expand All @@ -83,119 +41,19 @@ dependencies {
testImplementation "org.assertj:assertj-core:${VER_ASSERTJ}"
testImplementation "org.mockito:mockito-core:${VER_MOCKITO}"
testImplementation "com.diffplug.durian:durian-io:${VER_DURIAN}"
testImplementation "com.github.spullara.mustache.java:compiler:${VER_MUSTACHE}"
testImplementation 'com.github.spullara.mustache.java:compiler:0.9.10'
testImplementation "org.apache.maven:maven-plugin-api:${VER_MAVEN_API}"
testImplementation "org.eclipse.aether:aether-api:${VER_ECLIPSE_AETHER}"
testImplementation "org.codehaus.plexus:plexus-resources:${VER_PLEXUS_RESOURCES}"
testImplementation "org.apache.maven:maven-core:${VER_MAVEN_API}"
}

task copySourceFiles(type: Sync) {
from "src/main/java"
into MAVEN_PROJECT_DIR.dir("src/main/java")
}

task copyMvnw(type: Copy, dependsOn: copySourceFiles) {
from 'src/test/resources'
include 'mvnw'
include 'mvnw.cmd'
include '.mvn/**'
into MAVEN_PROJECT_DIR
}

task installLocalDependencies
def libs = [
'lib',
'lib-extra',
'testlib'
]
libs.each {
def groupId = 'com.diffplug.spotless'
def artifactId = "spotless-${it}"
def jarTask = tasks.getByPath(":${it}:jar")
def file = jarTask.archivePath

def installDependency = task "install_${artifactId}"(type: Exec) {
workingDir MAVEN_PROJECT_DIR

inputs.file(file)
outputs.dir(LOCAL_MAVEN_REPO_DIR.file(groupId.replace('.', '/') + "/" + artifactId + "/" + version))
commandLine mvnw("org.apache.maven.plugins:maven-install-plugin:2.3.1:install-file " +
"-Dfile=${file} " +
"-DgroupId=${groupId} " +
"-DartifactId=${artifactId} " +
"-Dversion=${libVersion} " +
"-Dpackaging=jar " +
"-DlocalRepositoryPath=${LOCAL_MAVEN_REPO_DIR}")
}
installDependency.dependsOn(jarTask)

installLocalDependencies.dependsOn installDependency
}

task createPomXml(dependsOn: installLocalDependencies) {
def newPomXml = MAVEN_PROJECT_DIR.file("pom.xml").asFile.toPath()

outputs.file(newPomXml)
doLast {
def additionalDependencies = project.configurations.runtimeClasspath.resolvedConfiguration.resolvedArtifacts.findAll {
return !libs.contains(it.moduleVersion.id.name)
}.collect {
return " <dependency>\n" +
" <groupId>${it.moduleVersion.id.group}</groupId>\n" +
" <artifactId>${it.moduleVersion.id.name}</artifactId>\n" +
" <version>${it.moduleVersion.id.version}</version>\n" +
" </dependency>\n"
}.join()

def versions = [
spotlessMavenPluginVersion: version,
mavenApiVersion : VER_MAVEN_API,
eclipseAetherVersion : VER_ECLIPSE_AETHER,
spotlessLibVersion : libVersion,
jsr305Version : VER_JSR_305,
additionalDependencies : additionalDependencies
]

def pomXmlTemplate = project.layout.projectDirectory.file("src/test/resources/pom-build.xml.mustache").asFile.toPath()

Files.newBufferedReader(pomXmlTemplate).withCloseable { reader ->
Files.newBufferedWriter(newPomXml, UTF_8, CREATE, TRUNCATE_EXISTING).withCloseable { writer ->
def mustache = new DefaultMustacheFactory().compile(reader, "pom")
mustache.execute(writer, versions)
}
}
}
}

task runMavenBuild(type: Exec, dependsOn: [
copySourceFiles,
copyMvnw,
createPomXml
]) {
outputs.dir(LOCAL_MAVEN_REPO_DIR)

workingDir MAVEN_PROJECT_DIR
// -B batch mode to make dependency download logging less verbose
commandLine mvnw("clean install -B -Dmaven.repo.local=${LOCAL_MAVEN_REPO_DIR}")
}

jar.setActions Arrays.asList()
jar.dependsOn(runMavenBuild)
File jarIn = MAVEN_PROJECT_DIR.file("target/spotless-maven-plugin-${version}.jar").asFile
File jarOut = jar.archivePath
jar.inputs.file(jarIn)
jar.outputs.file(jarOut)
jar.doLast {
Files.copy(jarIn.toPath(), jarOut.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING)
}

test { useJUnitPlatform() }

apply from: rootProject.file('gradle/special-tests.gradle')

tasks.withType(Test) {
systemProperty "localMavenRepositoryDir", LOCAL_MAVEN_REPO_DIR.asFile
systemProperty "spotlessMavenPluginVersion", project.version
dependsOn(jar)
tasks.withType(Test).configureEach {
systemProperty 'spotlessMavenPluginVersion', project.version
dependsOn 'publishToMavenLocal'
dependsOn ':lib:publishToMavenLocal'
dependsOn ':lib-extra:publishToMavenLocal'
}

apply from: rootProject.file("gradle/java-publish.gradle")
Loading