123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- /*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you 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.
- */
- import org.apache.tools.ant.taskdefs.condition.Os
- import org.apache.tools.ant.filters.ReplaceTokens
- import org.elasticsearch.gradle.BuildPlugin
- import org.elasticsearch.gradle.LoggedExec
- import org.elasticsearch.gradle.Version
- import org.elasticsearch.gradle.VersionCollection
- import org.elasticsearch.gradle.VersionProperties
- import org.gradle.plugins.ide.eclipse.model.SourceFolder
- import org.gradle.api.tasks.wrapper.Wrapper
- import org.gradle.api.tasks.wrapper.Wrapper.DistributionType
- import org.gradle.util.GradleVersion
- import org.gradle.util.DistributionLocator
- import java.nio.file.Files
- import java.nio.file.Path
- import java.security.MessageDigest
- // common maven publishing configuration
- subprojects {
- group = 'org.elasticsearch'
- version = VersionProperties.elasticsearch.toString()
- description = "Elasticsearch subproject ${project.path}"
- }
- subprojects {
- project.ext.licenseName = 'The Apache Software License, Version 2.0'
- project.ext.licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
- // we only use maven publish to add tasks for pom generation
- plugins.withType(MavenPublishPlugin).whenPluginAdded {
- publishing {
- publications {
- // add license information to generated poms
- all {
- pom.withXml { XmlProvider xml ->
- Node node = xml.asNode()
- node.appendNode('inceptionYear', '2009')
- Node license = node.appendNode('licenses').appendNode('license')
- license.appendNode('name', project.licenseName)
- license.appendNode('url', project.licenseUrl)
- license.appendNode('distribution', 'repo')
- Node developer = node.appendNode('developers').appendNode('developer')
- developer.appendNode('name', 'Elastic')
- developer.appendNode('url', 'http://www.elastic.co')
- }
- }
- }
- }
- }
- plugins.withType(BuildPlugin).whenPluginAdded {
- project.licenseFile = project.rootProject.file('licenses/APACHE-LICENSE-2.0.txt')
- project.noticeFile = project.rootProject.file('NOTICE.txt')
- }
- }
- /* Introspect all versions of ES that may be tested against for backwards
- * compatibility. It is *super* important that this logic is the same as the
- * logic in VersionUtils.java, throwing out alphas because they don't have any
- * backwards compatibility guarantees and only keeping the latest beta or rc
- * in a branch if there are only betas and rcs in the branch so we have
- * *something* to test against. */
- VersionCollection versions = new VersionCollection(file('server/src/main/java/org/elasticsearch/Version.java').readLines('UTF-8'))
- if (versions.currentVersion != VersionProperties.elasticsearch) {
- throw new GradleException("The last version in Versions.java [${versions.currentVersion}] does not match " +
- "VersionProperties.elasticsearch [${VersionProperties.elasticsearch}]")
- }
- // build metadata from previous build, contains eg hashes for bwc builds
- String buildMetadataValue = System.getenv('BUILD_METADATA')
- if (buildMetadataValue == null) {
- buildMetadataValue = ''
- }
- Map<String, String> buildMetadataMap = buildMetadataValue.tokenize(';').collectEntries {
- def (String key, String value) = it.split('=')
- return [key, value]
- }
- // injecting groovy property variables into all projects
- allprojects {
- project.ext {
- // for ide hacks...
- isEclipse = System.getProperty("eclipse.launcher") != null || gradle.startParameter.taskNames.contains('eclipse') || gradle.startParameter.taskNames.contains('cleanEclipse')
- isIdea = System.getProperty("idea.active") != null || gradle.startParameter.taskNames.contains('idea') || gradle.startParameter.taskNames.contains('cleanIdea')
- // for BWC testing
- bwcVersions = versions
- buildMetadata = buildMetadataMap
- }
- }
- task verifyVersions {
- doLast {
- if (gradle.startParameter.isOffline()) {
- throw new GradleException("Must run in online mode to verify versions")
- }
- // Read the list from maven central
- Node xml
- new URL('https://repo1.maven.org/maven2/org/elasticsearch/elasticsearch/maven-metadata.xml').openStream().withStream { s ->
- xml = new XmlParser().parse(s)
- }
- Set<Version> knownVersions = new TreeSet<>(xml.versioning.versions.version.collect { it.text() }.findAll { it ==~ /\d\.\d\.\d/ }.collect { Version.fromString(it) })
- // Limit the known versions to those that should be index compatible, and are not future versions
- knownVersions = knownVersions.findAll { it.major >= bwcVersions.currentVersion.major - 1 && it.before(VersionProperties.elasticsearch) }
- /* Limit the listed versions to those that have been marked as released.
- * Versions not marked as released don't get the same testing and we want
- * to make sure that we flip all unreleased versions to released as soon
- * as possible after release. */
- Set<Version> actualVersions = new TreeSet<>(bwcVersions.indexCompatible.findAll { false == it.snapshot })
- // Finally, compare!
- if (knownVersions.equals(actualVersions) == false) {
- throw new GradleException("out-of-date released versions\nActual :" + actualVersions + "\nExpected:" + knownVersions +
- "\nUpdate Version.java. Note that Version.CURRENT doesn't count because it is not released.")
- }
- }
- }
- /*
- * When adding backcompat behavior that spans major versions, temporarily
- * disabling the backcompat tests is necessary. This flag controls
- * the enabled state of every bwc task. It should be set back to true
- * after the backport of the backcompat code is complete.
- */
- final boolean bwc_tests_enabled = true
- final String bwc_tests_disabled_issue = "" /* place a PR link here when commiting bwc changes */
- if (bwc_tests_enabled == false) {
- if (bwc_tests_disabled_issue.isEmpty()) {
- throw new GradleException("bwc_tests_disabled_issue must be set when bwc_tests_enabled == false")
- }
- println "========================= WARNING ========================="
- println " Backwards compatibility tests are disabled!"
- println "See ${bwc_tests_disabled_issue}"
- println "==========================================================="
- }
- subprojects {
- ext.bwc_tests_enabled = bwc_tests_enabled
- }
- task verifyBwcTestsEnabled {
- doLast {
- if (bwc_tests_enabled == false) {
- throw new GradleException('Bwc tests are disabled. They must be re-enabled after completing backcompat behavior backporting.')
- }
- }
- }
- task branchConsistency {
- description 'Ensures this branch is internally consistent. For example, that versions constants match released versions.'
- group 'Verification'
- dependsOn verifyVersions, verifyBwcTestsEnabled
- }
- subprojects {
- // ignore missing javadocs
- tasks.withType(Javadoc) { Javadoc javadoc ->
- // the -quiet here is because of a bug in gradle, in that adding a string option
- // by itself is not added to the options. By adding quiet, both this option and
- // the "value" -quiet is added, separated by a space. This is ok since the javadoc
- // command already adds -quiet, so we are just duplicating it
- // see https://discuss.gradle.org/t/add-custom-javadoc-option-that-does-not-take-an-argument/5959
- javadoc.options.encoding='UTF8'
- javadoc.options.addStringOption('Xdoclint:all,-missing', '-quiet')
- }
- /* Sets up the dependencies that we build as part of this project but
- register as thought they were external to resolve internally. We register
- them as external dependencies so the build plugin that we use can be used
- to build elasticsearch plugins outside of the elasticsearch source tree. */
- ext.projectSubstitutions = [
- "org.elasticsearch.gradle:build-tools:${version}": ':build-tools',
- "org.elasticsearch:rest-api-spec:${version}": ':rest-api-spec',
- "org.elasticsearch:elasticsearch:${version}": ':server',
- "org.elasticsearch:elasticsearch-cli:${version}": ':server:cli',
- "org.elasticsearch:elasticsearch-core:${version}": ':libs:elasticsearch-core',
- "org.elasticsearch:elasticsearch-nio:${version}": ':libs:elasticsearch-nio',
- "org.elasticsearch:elasticsearch-x-content:${version}": ':libs:x-content',
- "org.elasticsearch:elasticsearch-secure-sm:${version}": ':libs:secure-sm',
- "org.elasticsearch.client:elasticsearch-rest-client:${version}": ':client:rest',
- "org.elasticsearch.client:elasticsearch-rest-client-sniffer:${version}": ':client:sniffer',
- "org.elasticsearch.client:elasticsearch-rest-high-level-client:${version}": ':client:rest-high-level',
- "org.elasticsearch.client:test:${version}": ':client:test',
- "org.elasticsearch.client:transport:${version}": ':client:transport',
- "org.elasticsearch.test:framework:${version}": ':test:framework',
- "org.elasticsearch.distribution.integ-test-zip:elasticsearch:${version}": ':distribution:archives:integ-test-zip',
- "org.elasticsearch.distribution.zip:elasticsearch:${version}": ':distribution:archives:zip',
- "org.elasticsearch.distribution.zip:elasticsearch-oss:${version}": ':distribution:archives:oss-zip',
- "org.elasticsearch.distribution.tar:elasticsearch:${version}": ':distribution:archives:tar',
- "org.elasticsearch.distribution.tar:elasticsearch-oss:${version}": ':distribution:archives:oss-tar',
- "org.elasticsearch.distribution.rpm:elasticsearch:${version}": ':distribution:packages:rpm',
- "org.elasticsearch.distribution.rpm:elasticsearch-oss:${version}": ':distribution:packages:oss-rpm',
- "org.elasticsearch.distribution.deb:elasticsearch:${version}": ':distribution:packages:deb',
- "org.elasticsearch.distribution.deb:elasticsearch-oss:${version}": ':distribution:packages:oss-deb',
- "org.elasticsearch.test:logger-usage:${version}": ':test:logger-usage',
- // for transport client
- "org.elasticsearch.plugin:transport-netty4-client:${version}": ':modules:transport-netty4',
- "org.elasticsearch.plugin:reindex-client:${version}": ':modules:reindex',
- "org.elasticsearch.plugin:lang-mustache-client:${version}": ':modules:lang-mustache',
- "org.elasticsearch.plugin:parent-join-client:${version}": ':modules:parent-join',
- "org.elasticsearch.plugin:aggs-matrix-stats-client:${version}": ':modules:aggs-matrix-stats',
- "org.elasticsearch.plugin:percolator-client:${version}": ':modules:percolator',
- "org.elasticsearch.plugin:rank-eval-client:${version}": ':modules:rank-eval',
- ]
- bwcVersions.snapshotProjectNames.each { snapshotName ->
- Version snapshot = bwcVersions.getSnapshotForProject(snapshotName)
- if (snapshot != null ) {
- String snapshotProject = ":distribution:bwc:${snapshotName}"
- project(snapshotProject).ext.bwcVersion = snapshot
- ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${snapshot}"] = snapshotProject
- ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${snapshot}"] = snapshotProject
- ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${snapshot}"] = snapshotProject
- if (snapshot.onOrAfter('6.3.0')) {
- ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch-oss:${snapshot}"] = snapshotProject
- ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch-oss:${snapshot}"] = snapshotProject
- ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch-oss:${snapshot}"] = snapshotProject
- }
- }
- }
- /*
- * Gradle only resolve project substitutions during dependency resolution but
- * we sometimes want to do the resolution at other times. This creates a
- * convenient method we can call to do it.
- */
- ext.dependencyToProject = { Dependency dep ->
- if (dep instanceof ProjectDependency) {
- return dep.dependencyProject
- } else {
- String substitution = projectSubstitutions.get("${dep.group}:${dep.name}:${dep.version}")
- if (substitution != null) {
- return findProject(substitution)
- }
- return null
- }
- }
- project.afterEvaluate {
- configurations.all {
- resolutionStrategy.dependencySubstitution { DependencySubstitutions subs ->
- projectSubstitutions.each { k,v ->
- subs.substitute(subs.module(k)).with(subs.project(v))
- }
- }
- }
- // Handle javadoc dependencies across projects. Order matters: the linksOffline for
- // org.elasticsearch:elasticsearch must be the last one or all the links for the
- // other packages (e.g org.elasticsearch.client) will point to server rather than
- // their own artifacts.
- if (project.plugins.hasPlugin(BuildPlugin)) {
- String artifactsHost = VersionProperties.elasticsearch.isSnapshot() ? "https://snapshots.elastic.co" : "https://artifacts.elastic.co"
- Closure sortClosure = { a, b -> b.group <=> a.group }
- Closure depJavadocClosure = { dep ->
- if (dep.group != null && dep.group.startsWith('org.elasticsearch')) {
- Project upstreamProject = dependencyToProject(dep)
- if (upstreamProject != null) {
- project.javadoc.dependsOn "${upstreamProject.path}:javadoc"
- String artifactPath = dep.group.replaceAll('\\.', '/') + '/' + dep.name.replaceAll('\\.', '/') + '/' + dep.version
- project.javadoc.options.linksOffline artifactsHost + "/javadoc/" + artifactPath, "${upstreamProject.buildDir}/docs/javadoc/"
- }
- }
- }
- project.configurations.compile.dependencies.findAll().toSorted(sortClosure).each(depJavadocClosure)
- project.configurations.compileOnly.dependencies.findAll().toSorted(sortClosure).each(depJavadocClosure)
- }
- }
- }
- // Ensure similar tasks in dependent projects run first. The projectsEvaluated here is
- // important because, while dependencies.all will pickup future dependencies,
- // it is not necessarily true that the task exists in both projects at the time
- // the dependency is added.
- gradle.projectsEvaluated {
- allprojects {
- if (project.path == ':test:framework') {
- // :test:framework:test cannot run before and after :server:test
- return
- }
- configurations.all {
- dependencies.all { Dependency dep ->
- Project upstreamProject = dependencyToProject(dep)
- if (upstreamProject != null) {
- if (project.path == upstreamProject.path) {
- // TODO: distribution integ tests depend on themselves (!), fix that
- return
- }
- for (String taskName : ['test', 'integTest']) {
- Task task = project.tasks.findByName(taskName)
- Task upstreamTask = upstreamProject.tasks.findByName(taskName)
- if (task != null && upstreamTask != null) {
- task.mustRunAfter(upstreamTask)
- }
- }
- }
- }
- }
- }
- }
- // intellij configuration
- allprojects {
- apply plugin: 'idea'
- if (isIdea) {
- project.buildDir = file('build-idea')
- }
- idea {
- module {
- inheritOutputDirs = false
- outputDir = file('build-idea/classes/main')
- testOutputDir = file('build-idea/classes/test')
- // also ignore other possible build dirs
- excludeDirs += file('build')
- excludeDirs += file('build-eclipse')
- iml {
- // fix so that Gradle idea plugin properly generates support for resource folders
- // see also https://issues.gradle.org/browse/GRADLE-2975
- withXml {
- it.asNode().component.content.sourceFolder.findAll { it.@url == 'file://$MODULE_DIR$/src/main/resources' }.each {
- it.attributes().remove('isTestSource')
- it.attributes().put('type', 'java-resource')
- }
- it.asNode().component.content.sourceFolder.findAll { it.@url == 'file://$MODULE_DIR$/src/test/resources' }.each {
- it.attributes().remove('isTestSource')
- it.attributes().put('type', 'java-test-resource')
- }
- }
- }
- }
- }
- task cleanIdeaBuildDir(type: Delete) {
- delete 'build-idea'
- }
- cleanIdeaBuildDir.setGroup("ide")
- cleanIdeaBuildDir.setDescription("Deletes the IDEA build directory.")
- tasks.cleanIdea.dependsOn(cleanIdeaBuildDir)
- }
- idea {
- project {
- vcs = 'Git'
- }
- }
- // Make sure gradle idea was run before running anything in intellij (including import).
- File ideaMarker = new File(projectDir, '.local-idea-is-configured')
- tasks.idea.doLast {
- ideaMarker.setText('', 'UTF-8')
- }
- if (System.getProperty('idea.active') != null && ideaMarker.exists() == false) {
- throw new GradleException('You must run gradle idea from the root of elasticsearch before importing into IntelliJ')
- }
- // eclipse configuration
- allprojects {
- apply plugin: 'eclipse'
- // Name all the non-root projects after their path so that paths get grouped together when imported into eclipse.
- if (path != ':') {
- eclipse.project.name = path
- if (Os.isFamily(Os.FAMILY_WINDOWS)) {
- eclipse.project.name = eclipse.project.name.replace(':', '_')
- }
- }
- plugins.withType(JavaBasePlugin) {
- File eclipseBuild = project.file('build-eclipse')
- eclipse.classpath.defaultOutputDir = eclipseBuild
- if (isEclipse) {
- // set this so generated dirs will be relative to eclipse build
- project.buildDir = eclipseBuild
- }
- eclipse.classpath.file.whenMerged { classpath ->
- // give each source folder a unique corresponding output folder
- int i = 0;
- classpath.entries.findAll { it instanceof SourceFolder }.each { folder ->
- i++;
- // this is *NOT* a path or a file.
- folder.output = "build-eclipse/" + i
- }
- }
- }
- File licenseHeaderFile;
- if (eclipse.project.name.startsWith(':x-pack')) {
- licenseHeaderFile = new File(project.rootDir, 'buildSrc/src/main/resources/license-headers/elastic-license-header.txt')
- } else {
- licenseHeaderFile = new File(project.rootDir, 'buildSrc/src/main/resources/license-headers/oss-license-header.txt')
- }
- String licenseHeader = licenseHeaderFile.getText('UTF-8').replace('\n', '\\\\n')
- task copyEclipseSettings(type: Copy) {
- // TODO: "package this up" for external builds
- from new File(project.rootDir, 'buildSrc/src/main/resources/eclipse.settings')
- into '.settings'
- filter{ it.replaceAll('@@LICENSE_HEADER_TEXT@@', licenseHeader)}
- }
- // otherwise .settings is not nuked entirely
- task wipeEclipseSettings(type: Delete) {
- delete '.settings'
- }
- tasks.cleanEclipse.dependsOn(wipeEclipseSettings)
- // otherwise the eclipse merging is *super confusing*
- tasks.eclipse.dependsOn(cleanEclipse, copyEclipseSettings)
- }
- // we need to add the same --debug-jvm option as
- // the real RunTask has, so we can pass it through
- class Run extends DefaultTask {
- boolean debug = false
- @org.gradle.api.internal.tasks.options.Option(
- option = "debug-jvm",
- description = "Enable debugging configuration, to allow attaching a debugger to elasticsearch."
- )
- public void setDebug(boolean enabled) {
- project.project(':distribution').run.clusterConfig.debug = enabled
- }
- }
- task run(type: Run) {
- dependsOn ':distribution:run'
- description = 'Runs elasticsearch in the foreground'
- group = 'Verification'
- impliesSubProjects = true
- }
- task wrapper(type: Wrapper)
- gradle.projectsEvaluated {
- allprojects {
- tasks.withType(Wrapper) { Wrapper wrapper ->
- wrapper.distributionType = DistributionType.ALL
- wrapper.doLast {
- final DistributionLocator locator = new DistributionLocator()
- final GradleVersion version = GradleVersion.version(wrapper.gradleVersion)
- final URI distributionUri = locator.getDistributionFor(version, wrapper.distributionType.name().toLowerCase(Locale.ENGLISH))
- final URI sha256Uri = new URI(distributionUri.toString() + ".sha256")
- final String sha256Sum = new String(sha256Uri.toURL().bytes)
- wrapper.getPropertiesFile() << "distributionSha256Sum=${sha256Sum}\n"
- }
- }
- }
- }
- static void assertLinesInFile(final Path path, final List<String> expectedLines) {
- final List<String> actualLines = Files.readAllLines(path)
- int line = 0
- for (final String expectedLine : expectedLines) {
- final String actualLine = actualLines.get(line)
- if (expectedLine != actualLine) {
- throw new GradleException("expected line [${line + 1}] in [${path}] to be [${expectedLine}] but was [${actualLine}]")
- }
- line++
- }
- }
- /*
- * Check that all generated JARs have our NOTICE.txt and an appropriate
- * LICENSE.txt in them. We configurate this in gradle but we'd like to
- * be extra paranoid.
- */
- subprojects { project ->
- project.tasks.withType(Jar).whenTaskAdded { jarTask ->
- final Task extract = project.task("extract${jarTask.name.capitalize()}", type: LoggedExec) {
- dependsOn jarTask
- ext.destination = project.buildDir.toPath().resolve("jar-extracted/${jarTask.name}")
- commandLine "${->new File(rootProject.compilerJavaHome, 'bin/jar')}",
- 'xf', "${-> jarTask.outputs.files.singleFile}", 'META-INF/LICENSE.txt', 'META-INF/NOTICE.txt'
- workingDir destination
- doFirst {
- project.delete(destination)
- Files.createDirectories(destination)
- }
- }
- final Task checkNotice = project.task("verify${jarTask.name.capitalize()}Notice") {
- dependsOn extract
- doLast {
- final List<String> noticeLines = Files.readAllLines(project.noticeFile.toPath())
- final Path noticePath = extract.destination.resolve('META-INF/NOTICE.txt')
- assertLinesInFile(noticePath, noticeLines)
- }
- }
- project.check.dependsOn checkNotice
- final Task checkLicense = project.task("verify${jarTask.name.capitalize()}License") {
- dependsOn extract
- doLast {
- final List<String> licenseLines = Files.readAllLines(project.licenseFile.toPath())
- final Path licensePath = extract.destination.resolve('META-INF/LICENSE.txt')
- assertLinesInFile(licensePath, licenseLines)
- }
- }
- project.check.dependsOn checkLicense
- }
- }
- /* Remove assemble on all qa projects because we don't need to publish
- * artifacts for them. */
- gradle.projectsEvaluated {
- subprojects {
- if (project.path.startsWith(':qa')) {
- Task assemble = project.tasks.findByName('assemble')
- if (assemble) {
- project.tasks.remove(assemble)
- project.build.dependsOn.remove('assemble')
- }
- }
- }
- }
|