diff --git a/gradle/build.gradle b/gradle/build.gradle index 3bc3e6d4a..b975c28e5 100644 --- a/gradle/build.gradle +++ b/gradle/build.gradle @@ -6,10 +6,13 @@ buildscript { dependencies { classpath 'com.google.cloud.tools:appengine-gradle-plugin:1.3.3' + classpath 'org.sonatype.aether:aether-api:1.13.1' + classpath 'org.sonatype.aether:aether-impl:1.13.1' } } plugins { + id 'nebula.dependency-lock' version '7.1.0' id 'nebula.lint' version '10.3.5' // Config helper for annotation processors such as AutoValue and Dagger. // Ensures that source code is generated at an appropriate location. @@ -88,6 +91,8 @@ subprojects { } apply plugin: 'java' + apply plugin: 'maven-publish' + apply plugin: 'nebula.dependency-lock' apply plugin: 'nebula.lint' apply plugin: 'net.ltgt.apt' @@ -105,6 +110,100 @@ subprojects { // TODO(weiminyu): enable more dependency checks ] + publishing { + repositories { + maven { + url = project.findProperty('gcsRepo') + } + } + } + + ext.getDistinctResolvedArtifacts = { + def distinctResolvedArtifacts = [:] + + configurations.each { + if (!it.isCanBeResolved()) { + return + } + it.resolvedConfiguration.resolvedArtifacts.each { resolvedArtifact -> + if (resolvedArtifact.id.componentIdentifier.displayName in ['project :util', 'project :third_party']) { + return + } + distinctResolvedArtifacts[resolvedArtifact.id.toString()] = resolvedArtifact + } + } + + return distinctResolvedArtifacts + } + + ext.generateDependencyPublications = { + def distinctResolvedArtifacts = project.ext.getDistinctResolvedArtifacts() + + distinctResolvedArtifacts.values().eachWithIndex { resolvedArtifact, n -> + project.publishing { + publications { + "maven${n}"(MavenPublication) { + artifact(resolvedArtifact.file) { + groupId = resolvedArtifact.moduleVersion.id.group + artifactId = resolvedArtifact.moduleVersion.id.name + version = resolvedArtifact.moduleVersion.id.version + classifier = resolvedArtifact.classifier + } + } + } + } + } + } + + ext.urlExists = { url -> + def connection = (HttpURLConnection) url.openConnection() + connection.setRequestMethod("HEAD") + connection.connect() + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + return true + } else { + return false + } + } + + ext.writeMetadata = { resolvedArtifact, url, gitRepositoryPath -> + def groupId = resolvedArtifact.moduleVersion.id.group + def artifactId = resolvedArtifact.moduleVersion.id.name + def version = resolvedArtifact.moduleVersion.id.version + def relativeFileName = + [groupId, artifactId, 'README.domainregistry'].join('/') + def metadataFile = new File(gitRepositoryPath, relativeFileName) + metadataFile.parentFile.mkdirs() + def writer = metadataFile.newWriter() + writer << "Name: ${artifactId}\n" + writer << "Url: ${url}\n" + writer << "Version: ${version}\n" + writer.close() + } + + // This task generates a metadata file for each resolved dependency artifact. + // The file contains the name, url and version for the artifact. + task generateDependencyMetadata { + doLast { + def distinctResolvedArtifacts = project.ext.getDistinctResolvedArtifacts() + def defaultLayout = new org.sonatype.aether.util.layout.MavenDefaultLayout() + + distinctResolvedArtifacts.values().each { resolvedArtifact -> + def artifact = new org.sonatype.aether.util.artifact.DefaultArtifact( + resolvedArtifact.id.componentIdentifier.toString()) + for (repository in project.repositories) { + def mavenRepository = (MavenArtifactRepository) repository + def repositoryUri = URI.create(mavenRepository.url.toString()) + def artifactUri = repositoryUri.resolve(defaultLayout.getPath(artifact)) + if (project.ext.urlExists(artifactUri.toURL())) { + project.ext.writeMetadata(resolvedArtifact, artifactUri.toURL(), project.findProperty('privateRepository') + "/${project.name}") + break + } + } + } + } + } + if (project.name == 'third_party') return // Path to code generated with annotation processors. Note that this path is diff --git a/gradle/core/build.gradle b/gradle/core/build.gradle index 719ff444e..829f987ec 100644 --- a/gradle/core/build.gradle +++ b/gradle/core/build.gradle @@ -466,3 +466,4 @@ task nomulus(type: Jar) { dependsOn project(':third_party').jar } +ext.generateDependencyPublications() diff --git a/gradle/proxy/build.gradle b/gradle/proxy/build.gradle index 3c2a54b2f..2dc363e33 100644 --- a/gradle/proxy/build.gradle +++ b/gradle/proxy/build.gradle @@ -99,3 +99,5 @@ docker { ports = [30000, 30001, 30002, 30011, 30012] } } + +ext.generateDependencyPublications() diff --git a/gradle/update_dependency.sh b/gradle/update_dependency.sh new file mode 100755 index 000000000..8276f8cf2 --- /dev/null +++ b/gradle/update_dependency.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Copyright 2018 The Nomulus Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# This script runs a workflow to generate dependency lock file, run a build against +# the generated lock file, save the lock file and upload dependency JARs to a private +# Maven repository if the build succeeds. + +set -e + +ALL_SUBPROJECTS="core proxy util" +SUBPROJECTS= + +if [[ -z "$@" ]]; then + SUBPROJECTS="${ALL_SUBPROJECTS}" +else + SUBPROJECTS="$@" +fi + +for PROJECT in ${SUBPROJECTS}; do + ./gradlew ":${PROJECT}:generateLock" + ./gradlew -PdependencyLock.useGeneratedLock=true ":${PROJECT}:build" + ./gradlew ":${PROJECT}:saveLock" + ./gradlew ":${PROJECT}:publish" +done