all: migrate gradle publish from maven to use maven-publish plugin (#5289)

This commit is contained in:
Jihun Cho 2019-01-31 17:38:43 -08:00 committed by GitHub
parent c75d9bc19f
commit 1c3432c3fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 203 additions and 183 deletions

View File

@ -20,7 +20,7 @@ before_install:
- echo "errorProne=true" >> $HOME/.gradle/gradle.properties - echo "errorProne=true" >> $HOME/.gradle/gradle.properties
install: install:
- ./gradlew assemble generateTestProto install - ./gradlew assemble generateTestProto publishToMavenLocal
- pushd examples && ./gradlew build && popd - pushd examples && ./gradlew build && popd
- pushd examples && mvn verify && popd - pushd examples && mvn verify && popd
- pushd examples/example-alts && ../gradlew build && popd - pushd examples/example-alts && ../gradlew build && popd

View File

@ -19,7 +19,7 @@ $ ./gradlew build
To install the artifacts to your Maven local repository for use in your own To install the artifacts to your Maven local repository for use in your own
project, run: project, run:
``` ```
$ ./gradlew install $ ./gradlew publishToMavenLocal
``` ```
### Notes for IntelliJ ### Notes for IntelliJ
@ -82,7 +82,7 @@ $ export CXXFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib"
When building on Windows and VC++, you need to specify project properties for When building on Windows and VC++, you need to specify project properties for
Gradle to find protobuf: Gradle to find protobuf:
``` ```
.\gradlew install ^ .\gradlew publishToMavenLocal ^
-PvcProtobufInclude=C:\path\to\protobuf-3.5.1\src ^ -PvcProtobufInclude=C:\path\to\protobuf-3.5.1\src ^
-PvcProtobufLibs=C:\path\to\protobuf-3.5.1\vsprojects\Release ^ -PvcProtobufLibs=C:\path\to\protobuf-3.5.1\vsprojects\Release ^
-PtargetArch=x86_32 -PtargetArch=x86_32

View File

@ -61,15 +61,10 @@ import net.ltgt.gradle.errorprone.CheckSeverity
javadoc { exclude 'io/grpc/alts/internal/**' } javadoc { exclude 'io/grpc/alts/internal/**' }
artifacts {
archives shadowJar
}
jar { jar {
// Must use a different classifier to avoid conflicting with shadowJar // Must use a different classifier to avoid conflicting with shadowJar
classifier = 'original' classifier = 'original'
} }
configurations.archives.artifacts.removeAll { it.classifier == "original" }
// We want to use grpc-netty-shaded instead of grpc-netty. But we also want our // We want to use grpc-netty-shaded instead of grpc-netty. But we also want our
// source to work with Bazel, so we rewrite the code as part of the build. // source to work with Bazel, so we rewrite the code as part of the build.
@ -82,14 +77,21 @@ shadowJar {
relocate 'io.netty', 'io.grpc.netty.shaded.io.netty' relocate 'io.netty', 'io.grpc.netty.shaded.io.netty'
} }
[ publishing {
install.repositories.mavenInstaller, publications {
uploadArchives.repositories.mavenDeployer, maven(MavenPublication) {
]*.pom*.whenConfigured { pom -> artifact shadowJar
def netty = pom.dependencies.find {dep -> dep.artifactId == 'grpc-netty'}
// Swap our dependency to grpc-netty-shaded. Projects depending on this via pom.withXml {
// project(':grpc-alts') will still be using the non-shaded form. // Swap our dependency to grpc-netty-shaded. Projects depending on this via
netty.artifactId = "grpc-netty-shaded" // project(':grpc-alts') will still be using the non-shaded form.
// Depend on specific version of grpc-netty-shaded because it is unstable API asNode().dependencies.'*'.findAll() { dep ->
netty.version = "[" + netty.version + "]" dep.artifactId.text() == 'grpc-netty'
}.each() { netty ->
netty.artifactId*.value = 'grpc-netty-shaded'
netty.version*.value = "[" + netty.version.text() + "]"
}
}
}
}
} }

View File

@ -134,7 +134,6 @@ uploadArchives.repositories.mavenDeployer {
name "gRPC Contributors" name "gRPC Contributors"
email "grpc-io@googlegroups.com" email "grpc-io@googlegroups.com"
url "https://grpc.io/" url "https://grpc.io/"
// https://issues.gradle.org/browse/GRADLE-2719
organization = "gRPC Authors" organization = "gRPC Authors"
organizationUrl "https://www.google.com" organizationUrl "https://www.google.com"
} }

View File

@ -19,6 +19,7 @@ subprojects {
apply plugin: "checkstyle" apply plugin: "checkstyle"
apply plugin: "java" apply plugin: "java"
apply plugin: "maven" apply plugin: "maven"
apply plugin: "maven-publish"
apply plugin: "idea" apply plugin: "idea"
apply plugin: "signing" apply plugin: "signing"
apply plugin: "jacoco" apply plugin: "jacoco"
@ -277,11 +278,6 @@ subprojects {
'org.openjdk.jmh:jmh-generator-bytecode:1.19' 'org.openjdk.jmh:jmh-generator-bytecode:1.19'
} }
signing {
required false
sign configurations.archives
}
// Disable JavaDoc doclint on Java 8. It's annoying. // Disable JavaDoc doclint on Java 8. It's annoying.
if (JavaVersion.current().isJava8Compatible()) { if (JavaVersion.current().isJava8Compatible()) {
allprojects { allprojects {
@ -300,9 +296,7 @@ subprojects {
} }
} }
jacoco { jacoco { toolVersion = "0.8.2" }
toolVersion = "0.8.2"
}
checkstyle { checkstyle {
configDir = file("$rootDir/buildscripts") configDir = file("$rootDir/buildscripts")
@ -348,79 +342,99 @@ subprojects {
from sourceSets.main.allSource from sourceSets.main.allSource
} }
artifacts { archives javadocJar, sourcesJar } publishing {
publications {
uploadArchives.repositories.mavenDeployer { // do not use mavenJava, as java plugin will modify it via "magic"
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } maven(MavenPublication) {
if (rootProject.hasProperty('repositoryDir')) { if (!project.name.contains("grpc-netty-shaded") && !name.contains("grpc-alts")
repository(url: new File(rootProject.repositoryDir).toURI()) && !name.contains("grpc-compiler")) {
} else { from components.java
String stagingUrl
if (rootProject.hasProperty('repositoryId')) {
stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' +
rootProject.repositoryId
} else {
stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
}
def configureAuth = {
if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) {
authentication(userName: rootProject.ossrhUsername, password: rootProject.ossrhPassword)
} }
}
repository(url: stagingUrl, configureAuth)
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/', configureAuth)
}
}
uploadArchives.onlyIf { !name.contains("grpc-gae-interop-testing") && !name.contains("grpc-xds") }
[ artifact javadocJar
install.repositories.mavenInstaller, artifact sourcesJar
uploadArchives.repositories.mavenDeployer,
]*.pom*.whenConfigured { pom ->
pom.project {
name "$project.group:$project.name"
description project.description
url 'https://github.com/grpc/grpc-java'
scm { pom {
connection 'scm:git:https://github.com/grpc/grpc-java.git' name = project.group + ":" + project.name
developerConnection 'scm:git:git@github.com:grpc/grpc-java.git' url = 'https://github.com/grpc/grpc-java'
url 'https://github.com/grpc/grpc-java' afterEvaluate {
} // description is not available until evaluated.
description = project.description
}
licenses { scm {
license { connection = 'scm:git:https://github.com/grpc/grpc-java.git'
name 'Apache 2.0' developerConnection = 'scm:git:git@github.com:grpc/grpc-java.git'
url 'https://opensource.org/licenses/Apache-2.0' url = 'https://github.com/grpc/grpc-java'
} }
}
developers { licenses {
developer { license {
id "grpc.io" name = 'Apache 2.0'
name "gRPC Contributors" url = 'https://opensource.org/licenses/Apache-2.0'
email "grpc-io@googlegroups.com" }
url "https://grpc.io/" }
// https://issues.gradle.org/browse/GRADLE-2719
organization = "gRPC Authors" developers {
organizationUrl "https://www.google.com" developer {
id = "grpc.io"
name = "gRPC Contributors"
email = "grpc-io@googlegroups.com"
url = "https://grpc.io/"
organization = "gRPC Authors"
organizationUrl = "https://www.google.com"
}
}
withXml {
if (!(project.name in
[
"grpc-stub",
"grpc-protobuf",
"grpc-protobuf-lite",
"grpc-protobuf-nano"
])) {
asNode().dependencies.'*'.findAll() { dep ->
dep.artifactId.text() == 'grpc-core'
}.each() { core ->
core.version*.value = "[" + core.version.text() + "]"
}
}
}
} }
} }
} }
if (!(project.name in repositories {
[ maven {
"grpc-stub", String stagingUrl
"grpc-protobuf", if (rootProject.hasProperty('repositoryId')) {
"grpc-protobuf-lite", stagingUrl = 'https://oss.sonatype.org/service/local/staging/deployByRepositoryId/' +
"grpc-protobuf-nano" rootProject.repositoryId
])) { } else {
def core = pom.dependencies.find {dep -> dep.artifactId == 'grpc-core'} stagingUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
if (core != null) { }
// Depend on specific version of grpc-core because internal package is unstable credentials {
core.version = "[" + core.version + "]" if (rootProject.hasProperty('ossrhUsername') && rootProject.hasProperty('ossrhPassword')) {
username = rootProject.ossrhUsername
password = rootProject.ossrhPassword
}
}
def releaseUrl = stagingUrl
def snapshotUrl = 'https://oss.sonatype.org/content/repositories/snapshots/'
url = version.endsWith('SNAPSHOT') ? snapshotUrl : releaseUrl
} }
} }
} }
signing {
required false
sign publishing.publications.maven
}
publishMavenPublicationToMavenRepository.onlyIf {
!name.contains("grpc-gae-interop-testing") && !name.contains("grpc-xds")
}
// At a test failure, log the stack trace to the console so that we don't // At a test failure, log the stack trace to the console so that we don't
// have to open the HTML in a browser. // have to open the HTML in a browser.
test { test {

View File

@ -19,7 +19,7 @@ export OS_NAME=$(uname)
# Proto deps # Proto deps
buildscripts/make_dependencies.sh buildscripts/make_dependencies.sh
./gradlew install ./gradlew publishToMavenLocal
# Build and run interop instrumentation tests on Firebase Test Lab # Build and run interop instrumentation tests on Firebase Test Lab

View File

@ -19,7 +19,7 @@ export OS_NAME=$(uname)
# Proto deps # Proto deps
buildscripts/make_dependencies.sh buildscripts/make_dependencies.sh
./gradlew install ./gradlew publishToMavenLocal
# Build grpc-cronet # Build grpc-cronet
@ -79,7 +79,7 @@ new_apk_size="$(stat --printf=%s $HELLO_WORLD_OUTPUT_DIR/apk/release/app-release
cd $BASE_DIR/github/grpc-java cd $BASE_DIR/github/grpc-java
git checkout HEAD^ git checkout HEAD^
./gradlew install ./gradlew publishToMavenLocal
cd examples/android/helloworld/ cd examples/android/helloworld/
../../gradlew build ../../gradlew build

View File

@ -46,7 +46,7 @@ export CXXFLAGS="-I/tmp/protobuf/include"
if [[ -z "${SKIP_TESTS:-}" ]]; then if [[ -z "${SKIP_TESTS:-}" ]]; then
# Ensure all *.proto changes include *.java generated code # Ensure all *.proto changes include *.java generated code
./gradlew assemble generateTestProto install $GRADLE_FLAGS ./gradlew assemble generateTestProto publishToMavenLocal $GRADLE_FLAGS
if [[ -z "${SKIP_CLEAN_CHECK:-}" && ! -z $(git status --porcelain) ]]; then if [[ -z "${SKIP_CLEAN_CHECK:-}" && ! -z $(git status --porcelain) ]]; then
git status git status
@ -70,11 +70,11 @@ fi
LOCAL_MVN_TEMP=$(mktemp -d) LOCAL_MVN_TEMP=$(mktemp -d)
# Note that this disables parallel=true from GRADLE_FLAGS # Note that this disables parallel=true from GRADLE_FLAGS
if [[ -z "${ALL_ARTIFACTS:-}" ]]; then if [[ -z "${ALL_ARTIFACTS:-}" ]]; then
./gradlew grpc-compiler:build grpc-compiler:uploadArchives $GRADLE_FLAGS \ ./gradlew grpc-compiler:build grpc-compiler:publishToMavenLocal $GRADLE_FLAGS \
-Dorg.gradle.parallel=false -PrepositoryDir=$LOCAL_MVN_TEMP -Dorg.gradle.parallel=false -Dmaven.repo.local=$LOCAL_MVN_TEMP
else else
./gradlew uploadArchives $GRADLE_FLAGS \ ./gradlew publishToMavenLocal $GRADLE_FLAGS \
-Dorg.gradle.parallel=false -PrepositoryDir=$LOCAL_MVN_TEMP -Dorg.gradle.parallel=false -Dmaven.repo.local=$LOCAL_MVN_TEMP
fi fi
readonly MVN_ARTIFACT_DIR="${MVN_ARTIFACT_DIR:-$GRPC_JAVA_DIR/mvn-artifacts}" readonly MVN_ARTIFACT_DIR="${MVN_ARTIFACT_DIR:-$GRPC_JAVA_DIR/mvn-artifacts}"

View File

@ -48,4 +48,4 @@ IF NOT %GRADLEEXIT% == 0 (
@rem make sure no daemons have any files open @rem make sure no daemons have any files open
cmd.exe /C "%WORKSPACE%\gradlew.bat --stop" cmd.exe /C "%WORKSPACE%\gradlew.bat --stop"
cmd.exe /C "%WORKSPACE%\gradlew.bat %GRADLE_FLAGS% -Dorg.gradle.parallel=false -PrepositoryDir=%WORKSPACE%\artifacts clean grpc-compiler:build grpc-compiler:uploadArchives" || exit /b 1 cmd.exe /C "%WORKSPACE%\gradlew.bat %GRADLE_FLAGS% -Dorg.gradle.parallel=false -Dmaven.repo.local=%WORKSPACE%\artifacts clean grpc-compiler:build grpc-compiler:publishToMavenLocal" || exit /b 1

View File

@ -32,4 +32,4 @@ SET GRADLE_FLAGS=-PtargetArch=%TARGET_ARCH% -PfailOnWarnings=%FAIL_ON_WARNINGS%
@rem make sure no daemons have any files open @rem make sure no daemons have any files open
cmd.exe /C "%WORKSPACE%\gradlew.bat --stop" cmd.exe /C "%WORKSPACE%\gradlew.bat --stop"
cmd.exe /C "%WORKSPACE%\gradlew.bat %GRADLE_FLAGS% -Dorg.gradle.parallel=false -PrepositoryDir=%WORKSPACE%\artifacts clean grpc-compiler:build grpc-compiler:uploadArchives" || exit /b 1 cmd.exe /C "%WORKSPACE%\gradlew.bat %GRADLE_FLAGS% -Dorg.gradle.parallel=false -Dmaven.repo.local=%WORKSPACE%\artifacts clean grpc-compiler:build grpc-compiler:publishToMavenLocal" || exit /b 1

View File

@ -53,7 +53,7 @@ This will compile a codegen and put it under your ``~/.m2/repository``. This
will make it available to any build tool that pulls codegens from Maven will make it available to any build tool that pulls codegens from Maven
repostiories. repostiories.
``` ```
$ ../gradlew install $ ../gradlew publishToMavenLocal
``` ```
## Creating a release of GRPC Java ## Creating a release of GRPC Java

View File

@ -232,77 +232,71 @@ task buildArtifacts(type: Copy) {
archivesBaseName = "$protocPluginBaseName" archivesBaseName = "$protocPluginBaseName"
artifacts { task checkArtifacts {
archives("$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" as File) { dependsOn buildArtifacts
classifier osdetector.os + "-" + arch doLast {
type "exe" if (!usingVisualCpp) {
extension "exe" def ret = exec {
builtBy buildArtifacts executable 'bash'
args 'check-artifact.sh', osdetector.os, arch
}
if (ret.exitValue != 0) {
throw new GradleException("check-artifact.sh exited with " + ret.exitValue)
}
} else {
def exeName = "$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe"
def os = new ByteArrayOutputStream()
def ret = exec {
executable 'dumpbin'
args '/nologo', '/dependents', exeName
standardOutput = os
}
if (ret.exitValue != 0) {
throw new GradleException("dumpbin exited with " + ret.exitValue)
}
def dlls = os.toString() =~ /Image has the following dependencies:\s+(.*)\s+Summary/
if (dlls[0][1] != "KERNEL32.dll") {
throw new Exception("unexpected dll deps: " + dlls[0][1]);
}
os.reset()
ret = exec {
executable 'dumpbin'
args '/nologo', '/headers', exeName
standardOutput = os
}
if (ret.exitValue != 0) {
throw new GradleException("dumpbin exited with " + ret.exitValue)
}
def machine = os.toString() =~ / machine \(([^)]+)\)/
def expectedArch = [x86_32: "x86", x86_64: "x64"][arch]
if (machine[0][1] != expectedArch) {
throw new Exception("unexpected architecture: " + machine[0][1]);
}
}
} }
} }
// Exe files are skipped by Maven by default. Override it. // Exe files are skipped by Maven by default. Override it.
// Also skip jar files that is generated by the java plugin. // Also skip jar files that is generated by the java plugin.
[ publishing {
install.repositories.mavenInstaller, publications {
uploadArchives.repositories.mavenDeployer, maven(MavenPublication) {
]*.setFilter {artifact, file -> // Removes all artifacts since grpc-compiler doesn't generates any Jar
! (file.getName().endsWith('jar') || file.getName().endsWith('jar.asc')) artifacts = []
} artifactId 'protoc-gen-grpc-java'
artifact("$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" as File) {
[ classifier osdetector.os + "-" + arch
uploadArchives.repositories.mavenDeployer, extension "exe"
]*.beforeDeployment { it -> builtBy checkArtifacts
if (!usingVisualCpp) { }
def ret = exec { pom.withXml {
executable 'bash' // This isn't any sort of Java archive artifact, and OSSRH doesn't enforce
args 'check-artifact.sh', osdetector.os, arch // javadoc for 'pom' packages. 'exe' would be a more appropriate packaging
// value, but it isn't clear how that will be interpreted. In addition,
// 'pom' is typically the value used when building an exe with Maven.
asNode().project.packaging*.value = 'pom'
}
} }
if (ret.exitValue != 0) {
throw new GradleException("check-artifact.sh exited with " + ret.exitValue)
}
} else {
def exeName = "$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe"
def os = new ByteArrayOutputStream()
def ret = exec {
executable 'dumpbin'
args '/nologo', '/dependents', exeName
standardOutput = os
}
if (ret.exitValue != 0) {
throw new GradleException("dumpbin exited with " + ret.exitValue)
}
def dlls = os.toString() =~ /Image has the following dependencies:\s+(.*)\s+Summary/
if (dlls[0][1] != "KERNEL32.dll") {
throw new Exception("unexpected dll deps: " + dlls[0][1]);
}
os.reset()
ret = exec {
executable 'dumpbin'
args '/nologo', '/headers', exeName
standardOutput = os
}
if (ret.exitValue != 0) {
throw new GradleException("dumpbin exited with " + ret.exitValue)
}
def machine = os.toString() =~ / machine \(([^)]+)\)/
def expectedArch = [x86_32: "x86", x86_64: "x64"][arch]
if (machine[0][1] != expectedArch) {
throw new Exception("unexpected architecture: " + machine[0][1]);
}
}
}
[
install.repositories.mavenInstaller,
uploadArchives.repositories.mavenDeployer,
]*.pom*.whenConfigured { pom ->
pom.project {
// This isn't any sort of Java archive artifact, and OSSRH doesn't enforce
// javadoc for 'pom' packages. 'exe' would be a more appropriate packaging
// value, but it isn't clear how that will be interpreted. In addition,
// 'pom' is typically the value used when building an exe with Maven.
packaging = "pom"
} }
} }

View File

@ -56,18 +56,18 @@ checkArch ()
echo Format=$format echo Format=$format
if [[ "$OS" == linux ]]; then if [[ "$OS" == linux ]]; then
if [[ "$ARCH" == x86_32 ]]; then if [[ "$ARCH" == x86_32 ]]; then
assertEq $format "elf32-i386" $LINENO assertEq "$format" "elf32-i386" $LINENO
elif [[ "$ARCH" == x86_64 ]]; then elif [[ "$ARCH" == x86_64 ]]; then
assertEq $format "elf64-x86-64" $LINENO assertEq "$format" "elf64-x86-64" $LINENO
else else
fail "Unsupported arch: $ARCH" fail "Unsupported arch: $ARCH"
fi fi
else else
# $OS == windows # $OS == windows
if [[ "$ARCH" == x86_32 ]]; then if [[ "$ARCH" == x86_32 ]]; then
assertEq $format "pei-i386" $LINENO assertEq "$format" "pei-i386" $LINENO
elif [[ "$ARCH" == x86_64 ]]; then elif [[ "$ARCH" == x86_64 ]]; then
assertEq $format "pei-x86-64" $LINENO assertEq "$format" "pei-x86-64" $LINENO
else else
fail "Unsupported arch: $ARCH" fail "Unsupported arch: $ARCH"
fi fi
@ -76,9 +76,9 @@ checkArch ()
format="$(file -b "$1" | grep -o "[^ ]*$")" format="$(file -b "$1" | grep -o "[^ ]*$")"
echo Format=$format echo Format=$format
if [[ "$ARCH" == x86_32 ]]; then if [[ "$ARCH" == x86_32 ]]; then
assertEq $format "i386" $LINENO assertEq "$format" "i386" $LINENO
elif [[ "$ARCH" == x86_64 ]]; then elif [[ "$ARCH" == x86_64 ]]; then
assertEq $format "x86_64" $LINENO assertEq "$format" "x86_64" $LINENO
else else
fail "Unsupported arch: $ARCH" fail "Unsupported arch: $ARCH"
fi fi

View File

@ -20,15 +20,10 @@ dependencies {
shadow project(':grpc-core') shadow project(':grpc-core')
} }
artifacts { // We want uploadArchives to handle the shadowJar; we don't care about
// uploadShadow
archives shadowJar }
jar { jar {
// Must use a different classifier to avoid conflicting with shadowJar // Must use a different classifier to avoid conflicting with shadowJar
classifier = 'original' classifier = 'original'
} }
configurations.archives.artifacts.removeAll { it.classifier == "original" }
shadowJar { shadowJar {
classifier = null classifier = null
@ -46,13 +41,26 @@ shadowJar {
mergeServiceFiles() mergeServiceFiles()
} }
// This is a hack to have shadow plugin modify the uploadArchives POM's publishing {
// dependencies. If we delete the uploadShadow task, then the plugin will no publications {
// longer modify the POM. This probably can break horribly with parallel build, maven(MavenPublication) {
// but that's broken anyway with install/uploadArchives // Ideally swap to project.shadow.component(it) when it isn't broken for project deps
uploadShadow.repositories.addAll(uploadArchives.repositories) artifact shadowJar
// And then we use a further hack to share that POM with install
install.repositories.mavenInstaller.pom = uploadArchives.repositories.mavenDeployer.pom pom.withXml {
def dependencies = asNode().appendNode('dependencies')
project.configurations.shadow.allDependencies.each { dep ->
def dependencyNode = dependencies.appendNode('dependency')
dependencyNode.appendNode('groupId', dep.group)
dependencyNode.appendNode('artifactId', dep.name)
def version = (dep.name == 'grpc-core') ? '[' + dep.version + ']' : dep.version
dependencyNode.appendNode('version', version)
dependencyNode.appendNode('scope', 'runtime')
}
}
}
}
}
task testShadow(type: Test) { task testShadow(type: Test) {
testClassesDirs = sourceSets.testShadow.output.classesDirs testClassesDirs = sourceSets.testShadow.output.classesDirs

View File

@ -47,3 +47,6 @@ if (settings.hasProperty('skipCodegen') && skipCodegen.toBoolean()) {
include ":grpc-compiler" include ":grpc-compiler"
project(':grpc-compiler').projectDir = "$rootDir/compiler" as File project(':grpc-compiler').projectDir = "$rootDir/compiler" as File
} }
// Gradle 5.0 changed the behavior of publishing block, use new stable behavior
enableFeaturePreview('STABLE_PUBLISHING')