Skip to content

Commit

Permalink
Migrate build steps to Gradle build
Browse files Browse the repository at this point in the history
Currently, certain Gradle tasks (like 'build', 'check') don't work
without running 'make generate' first. Instead of splitting logic in
between Gradle and the Makefile, migrate logic for generating code,
running license-header, and other details to the Gradle build so they
can happen in the correct order automatically. This has the side effect
that new users can use Gradle commands they are familiar with
('./gradlew build') and not have to learn the makefile conventions
separately.
  • Loading branch information
pkwarren committed Oct 11, 2023
1 parent 3fd22bf commit 133a8e4
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 74 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/conformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,5 @@ jobs:
distribution: 'temurin'
java-version: '17'
cache: 'gradle'
- name: Generate
run: make checkgenerate
- name: Test conformance
run: make conformance
49 changes: 6 additions & 43 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ SHELL := bash
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
MAKEFLAGS += --no-print-directory
BIN := .tmp/bin
COPYRIGHT_YEARS := 2023
LICENSE_IGNORE := --ignore src/main/java/build/buf/validate/ --ignore conformance/src/main/java/build/buf/validate/conformance/
JAVA = java
GO ?= go
ARGS ?= --strict_message
# When updating, also update src/test/resources/proto/buf.yaml and re-run 'buf mod update'.
PROTOVALIDATE_VERSION ?= v0.4.3

.PHONY: all
all: lint generate build docs conformance ## Run all tests and lint (default)
Expand All @@ -33,32 +25,19 @@ checkgenerate: generate ## Checks if `make generate` produces a diff.

.PHONY: clean
clean: ## Delete intermediate build artifacts
@# -X only removes untracked files, -d recurses into directories, -f actually removes files/dirs
git clean -Xdf
./gradlew clean

.PHONY: conformance
conformance: build $(BIN)/protovalidate-conformance generate ## Execute conformance tests.
./gradlew conformance:jar
$(BIN)/protovalidate-conformance $(ARGS) ./conformance/conformance.sh

.PHONY: generate-license
generate-license: $(BIN)/license-header ## Generates license headers for all source files.
$(BIN)/license-header \
--license-type apache \
--copyright-holder "Buf Technologies, Inc." \
--year-range "$(COPYRIGHT_YEARS)" $(LICENSE_IGNORE)
conformance: ## Execute conformance tests.
./gradlew conformance:conformance

.PHONY: help
help: ## Describe useful make targets
help: ## Describe useful make targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-15s %s\n", $$1, $$2}'

.PHONY: generate
generate: $(BIN)/buf generate-license ## Regenerate code and license headers
$(BIN)/buf export buf.build/bufbuild/protovalidate:$(PROTOVALIDATE_VERSION) --output src/main/resources
$(BIN)/buf generate --template buf.gen.yaml src/main/resources
$(BIN)/buf generate --template conformance/buf.gen.yaml -o conformance/ buf.build/bufbuild/protovalidate-testing:$(PROTOVALIDATE_VERSION)
$(BIN)/buf generate --template src/test/resources/proto/buf.gen.imports.yaml src/test/resources/proto --include-imports
$(BIN)/buf generate --template src/test/resources/proto/buf.gen.noimports.yaml src/test/resources/proto
generate: ## Regenerate code and license headers
./gradlew generate

.PHONY: lint
lint: ## Lint code
Expand All @@ -80,19 +59,3 @@ releaselocal: ## Release artifacts to local maven repository.
.PHONY: test
test: ## Run all tests.
./gradlew test

$(BIN):
@mkdir -p $(BIN)

$(BIN)/buf: $(BIN) Makefile
GOBIN=$(abspath $(@D)) $(GO) install \
github.com/bufbuild/buf/cmd/buf@latest

$(BIN)/license-header: $(BIN) Makefile
GOBIN=$(abspath $(@D)) $(GO) install \
github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@latest

$(BIN)/protovalidate-conformance: $(BIN) Makefile
GOBIN=$(abspath $(BIN)) $(GO) install \
github.com/bufbuild/protovalidate/tools/protovalidate-conformance@$(PROTOVALIDATE_VERSION)

121 changes: 112 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import com.vanniktech.maven.publish.JavaLibrary
import com.vanniktech.maven.publish.SonatypeHost
import com.diffplug.gradle.spotless.SpotlessExtension
import com.vanniktech.maven.publish.JavaLibrary
import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.SonatypeHost
import net.ltgt.gradle.errorprone.CheckSeverity
import net.ltgt.gradle.errorprone.errorprone

Expand All @@ -18,9 +18,108 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}

val bufCLIFile = project.layout.buildDirectory.file("gobin/buf").get().asFile
val bufCLIPath: String = bufCLIFile.absolutePath
val bufLicenseHeaderCLIFile = project.layout.buildDirectory.file("gobin/license-header").get().asFile
val bufLicenseHeaderCLIPath: String = bufLicenseHeaderCLIFile.absolutePath

tasks.register<Exec>("installBuf") {
description = "Installs the Buf CLI."
environment("GOBIN", bufCLIFile.parentFile.absolutePath)
outputs.file(bufCLIFile)
commandLine("go", "install", "github.com/bufbuild/buf/cmd/buf@latest")
}

tasks.register<Exec>("installLicenseHeader") {
description = "Installs the Buf license-header CLI."
environment("GOBIN", bufLicenseHeaderCLIFile.parentFile.absolutePath)
outputs.file(bufLicenseHeaderCLIFile)
commandLine("go", "install", "github.com/bufbuild/buf/private/pkg/licenseheader/cmd/license-header@latest")
}

tasks.register<Exec>("licenseHeader") {
dependsOn("installLicenseHeader")
description = "Runs the Buf license-header CLI."
commandLine(
bufLicenseHeaderCLIPath,
"--license-type",
"apache",
"--copyright-holder",
"Buf Technologies, Inc.",
"--year-range",
project.findProperty("license-header.years")!!.toString(),
"--ignore",
"src/main/java/build/buf/validate/",
"--ignore",
"conformance/src/main/java/build/buf/validate/conformance/",
)
}

tasks.register<Exec>("generateTestSourcesImports") {
dependsOn("installBuf")
description = "Generates code with buf generate --include-imports for unit tests."
commandLine(
bufCLIPath,
"generate",
"--template",
"src/test/resources/proto/buf.gen.imports.yaml",
"src/test/resources/proto",
"--include-imports",
)
}

tasks.register<Exec>("generateTestSourcesNoImports") {
dependsOn("installBuf")
description = "Generates code with buf generate --include-imports for unit tests."
commandLine(bufCLIPath, "generate", "--template", "src/test/resources/proto/buf.gen.noimports.yaml", "src/test/resources/proto")
}

tasks.register("generateTestSources") {
dependsOn("generateTestSourcesImports", "generateTestSourcesNoImports")
description = "Generates code with buf generate for unit tests"
}

tasks.register<Exec>("exportProtovalidateModule") {
dependsOn("installBuf")
description = "Exports the bufbuild/protovalidate module sources to src/main/resources."
commandLine(
bufCLIPath,
"export",
"buf.build/bufbuild/protovalidate:${project.findProperty("protovalidate.version")}",
"--output",
"src/main/resources",
)
}

tasks.register<Exec>("generateSources") {
dependsOn("installBuf")
description = "Generates sources for the bufbuild/protovalidate module sources to src/main/java."
commandLine(bufCLIPath, "generate", "--template", "buf.gen.yaml", "src/main/resources")
}

tasks.register<Exec>("generateConformance") {
dependsOn("installBuf")
description = "Generates sources for the bufbuild/protovalidate-testing module to conformance/src/main/java."
commandLine(bufCLIPath, "generate", "--template", "buf.gen.yaml", "src/main/resources")
}

tasks.register("generate") {
description = "Generates sources with buf generate and buf export."
dependsOn(
"generateTestSources",
"exportProtovalidateModule",
"generateSources",
"generateConformance",
"licenseHeader",
)
}

tasks.withType<JavaCompile> {
if (JavaVersion.current().isJava9Compatible) doFirst {
options.compilerArgs = mutableListOf("--release", "8")
dependsOn("generateTestSources")
if (JavaVersion.current().isJava9Compatible) {
doFirst {
options.compilerArgs = mutableListOf("--release", "8")
}
}
// Disable errorprone on generated code
options.errorprone.excludedPaths.set("(.*/src/main/java/build/buf/validate/.*|.*/build/generated/.*)")
Expand Down Expand Up @@ -60,7 +159,11 @@ sourceSets {
apply(plugin = "com.diffplug.spotless")
configure<SpotlessExtension> {
java {
targetExclude("src/main/java/build/buf/validate/**/*.java")
targetExclude("src/main/java/build/buf/validate/**/*.java", "build/generated/test-sources/bufgen/**/*.java")
}
kotlinGradle {
ktlint()
target("**/*.kts")
}
}

Expand Down Expand Up @@ -94,15 +197,16 @@ mavenPublishing {
val releaseVersion = project.findProperty("releaseVersion") as String? ?: System.getenv("VERSION")
coordinates("build.buf", "protovalidate", releaseVersion ?: "0.0.0-SNAPSHOT")
pomFromGradleProperties()
configure(JavaLibrary(
configure(
JavaLibrary(
// configures the -javadoc artifact, possible values:
// - `JavadocJar.None()` don't publish this artifact
// - `JavadocJar.Empty()` publish an emprt jar
// - `JavadocJar.Empty()` publish an empty jar
// - `JavadocJar.Javadoc()` to publish standard javadocs
javadocJar = JavadocJar.Javadoc(),
// whether to publish a sources jar
sourcesJar = true,
)
),
)
pom {
name.set("connect-library") // This is overwritten in subprojects.
Expand Down Expand Up @@ -131,7 +235,6 @@ mavenPublishing {
developerConnection.set("scm:git:ssh://[email protected]/bufbuild/protovalidate-java.git")
}
}

}

dependencies {
Expand Down
41 changes: 36 additions & 5 deletions conformance/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,38 @@ import net.ltgt.gradle.errorprone.errorprone
plugins {
`version-catalog`

application
java
alias(libs.plugins.errorprone)
}

val conformanceCLIFile = project.layout.buildDirectory.file("gobin/protovalidate-conformance").get().asFile
val conformanceCLIPath: String = conformanceCLIFile.absolutePath
val conformanceAppScript: String = project.layout.buildDirectory.file("install/conformance/bin/conformance").get().asFile.absolutePath
val conformanceArgs = (project.findProperty("protovalidate.conformance.args")?.toString() ?: "").split("\\s+".toRegex())

tasks.register<Exec>("installProtovalidateConformance") {
description = "Installs the Protovalidate Conformance CLI."
environment("GOBIN", conformanceCLIFile.parentFile.absolutePath)
outputs.file(conformanceCLIFile)
commandLine(
"go",
"install",
"github.com/bufbuild/protovalidate/tools/protovalidate-conformance@${project.findProperty("protovalidate.version")}",
)
}

tasks.register<Exec>("conformance") {
dependsOn("installDist", "installProtovalidateConformance")
description = "Runs protovalidate conformance tests."
commandLine(*(listOf(conformanceCLIPath) + conformanceArgs + listOf(conformanceAppScript)).toTypedArray())
}

tasks.withType<JavaCompile> {
if (JavaVersion.current().isJava9Compatible) doFirst {
options.compilerArgs = mutableListOf("--release", "8")
if (JavaVersion.current().isJava9Compatible) {
doFirst {
options.compilerArgs = mutableListOf("--release", "8")
}
}
// Disable errorprone on generated code
options.errorprone.excludedPaths.set(".*/src/main/java/build/buf/validate/conformance/.*")
Expand All @@ -21,18 +46,24 @@ tasks.withType<Javadoc> {
enabled = false
}

application {
mainClass.set("build.buf.protovalidate.conformance.Main")
}

tasks {
jar {
dependsOn(":jar")
manifest {
attributes(mapOf("Main-Class" to "build.buf.Main"))
attributes(mapOf("Main-Class" to "build.buf.protovalidate.conformance.Main"))
}
duplicatesStrategy = DuplicatesStrategy.INCLUDE
// This line of code recursively collects and copies all of a project's files
// and adds them to the JAR itself. One can extend this task, to skip certain
// files or particular types at will
val sourcesMain = sourceSets.main.get()
val contents = configurations.runtimeClasspath.get()
.map { if (it.isDirectory) it else zipTree(it) } +
val contents =
configurations.runtimeClasspath.get()
.map { if (it.isDirectory) it else zipTree(it) } +
sourcesMain.output
from(contents)
}
Expand Down
3 changes: 0 additions & 3 deletions conformance/conformance.sh

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package build.buf;
package build.buf.protovalidate.conformance;

import com.google.protobuf.DescriptorProtos;
import com.google.protobuf.Descriptors;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package build.buf;
package build.buf.protovalidate.conformance;

import build.buf.protovalidate.Config;
import build.buf.protovalidate.ValidationResult;
Expand Down
8 changes: 8 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# When updating, also update src/test/resources/proto/buf.yaml and re-run 'buf mod update'.
protovalidate.version = v0.4.3

# Arguments to the protovalidate-conformance CLI
protovalidate.conformance.args = --strict_message

# Argument to the license-header CLI
license-header.years = 2023
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 3 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 133a8e4

Please sign in to comment.