Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ class BuildPlugin implements Plugin<Project> {
project.pluginManager.apply('nebula.info-scm')
project.pluginManager.apply('nebula.info-jar')

project.getTasks().create("exportBuildResources", ExportElasticsearchBuildResourcesTask)

globalBuildInfo(project)
configureRepositories(project)
configureConfigurations(project)
Expand All @@ -101,6 +103,7 @@ class BuildPlugin implements Plugin<Project> {
configureDependenciesInfo(project)
}


/** Performs checks on the build environment and prints information about the build environment. */
static void globalBuildInfo(Project project) {
if (project.rootProject.ext.has('buildChecksDone') == false) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* 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.
*/
package org.elasticsearch.gradle;

import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.SkipWhenEmpty;
import org.gradle.api.tasks.StopExecutionException;
import org.gradle.api.tasks.TaskAction;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
* Export Elasticsearch build resources to configurable paths
* <p>
* Wil overwrite existing files and create missing directories.
* Useful for resources that that need to be passed to other processes trough the filesystem or otherwise can't be
* consumed from the classpath.
*/
public class ExportElasticsearchBuildResourcesTask extends DefaultTask {

private final Logger logger = Logging.getLogger(ExportElasticsearchBuildResourcesTask.class);

private final Set<String> resources = new HashSet<>();

private DirectoryProperty outputDir;

public ExportElasticsearchBuildResourcesTask() {
outputDir = getProject().getLayout().directoryProperty(
getProject().getLayout().getBuildDirectory().dir("build-tools-exported")
);
}

@OutputDirectory
public DirectoryProperty getOutputDir() {
return outputDir;
}

@Input
@SkipWhenEmpty
public Set<String> getResources() {
return Collections.unmodifiableSet(resources);
}

@Classpath
public String getResourcesClasspath() {
// This will make sure the task is not considered up to date if the resources are changed.
logger.info("Classpath: {}", System.getProperty("java.class.path"));
return System.getProperty("java.class.path");
}

public void setOutputDir(DirectoryProperty outputDir) {
this.outputDir = outputDir;
}

public RegularFileProperty resource(String resource) {
resources.add(resource);
return getProject().getLayout().fileProperty(outputDir.file(resource));
}

@TaskAction
public void doExport() {
if (resources.isEmpty()) {
throw new StopExecutionException();
}
resources.stream().parallel()
.forEach(resourcePath -> {
Path destination = outputDir.get().file(resourcePath).getAsFile().toPath();
try (InputStream is = getClass().getClassLoader().getResourceAsStream(resourcePath)) {
if (is == null) {
throw new GradleException("Can't export `" + resourcePath + "` from build-tools: not found");
}
Files.copy(is, destination);
} catch (IOException e) {
throw new GradleException("Can't write resource `" + resourcePath + "` to " + destination);
}
});
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package org.elasticsearch.gradle;

/*
* 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.elasticsearch.gradle.test.GradleIntegrationTestCase;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.BuildTask;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.TaskOutcome;

import java.nio.file.Files;
import java.nio.file.Path;

public class ExportElasticsearchBuildResourcesTaskIT extends GradleIntegrationTestCase {

public static final String PROJECT_NAME = "elasticsearch-build-resources";

public void testUpToDateWithSourcesConfigured() {
GradleRunner.create()
.withProjectDir(getProjectDir(PROJECT_NAME))
.withArguments("clean", "-s")
.withPluginClasspath()
.build();

BuildResult result = GradleRunner.create()
.withProjectDir(getProjectDir(PROJECT_NAME))
.withArguments("exportBuildResources", "-s", "-i")
.withPluginClasspath()
.build();
assertTaskSuccessFull(result, ":exportBuildResources");
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle.xml");


result = GradleRunner.create()
.withProjectDir(getProjectDir(PROJECT_NAME))
.withArguments("exportBuildResources", "-s", "-i")
.withPluginClasspath()
.build();
assertEquals(TaskOutcome.UP_TO_DATE, result.task(":exportBuildResources").getOutcome());
assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle.xml");
}

public void testImplicitTaskDependencyCopy() {
BuildResult result = GradleRunner.create()
.withProjectDir(getProjectDir(PROJECT_NAME))
.withArguments("clean", "sampleCopyAll", "-s", "-i")
.withPluginClasspath()
.build();
assertTaskSuccessFull(result, ":exportBuildResources");
assertTaskSuccessFull(result, ":sampleCopyAll");
assertBuildFileExists(result, PROJECT_NAME, "sampleCopyAll/checkstyle.xml");
}

public void testImplicitTaskDependencyInputFileOfOther() {
BuildResult result = GradleRunner.create()
.withProjectDir(getProjectDir(PROJECT_NAME))
.withArguments("clean", "sample", "-s", "-i")
.withPluginClasspath()
.build();

assertBuildFileExists(result, PROJECT_NAME, "build-tools-exported/checkstyle.xml");
}

private void assertTaskSuccessFull(BuildResult result, String taskName) {
BuildTask task = result.task(taskName);
if (task == null) {
fail("Expected task `" + taskName + "` to be successful, but it did not run");
}
assertEquals(TaskOutcome.SUCCESS, task.getOutcome());
}

private void assertBuildFileExists(BuildResult result, String projectName, String path) {
Path absPath = getBuildDir(projectName).toPath().resolve(path);
assertTrue(
result.getOutput() + "\n\nExpected `" + absPath + "` to exists but it did not",
Files.exists(absPath)
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ protected File getProjectDir(String name) {
throw new RuntimeException("Could not find resources dir for integration tests. " +
"Note that these tests can only be ran by Gradle and are not currently supported by the IDE");
}
return new File(root, name);
return new File(root, name).getAbsoluteFile();
}

protected GradleRunner getGradleRunner(String sampleProject) {
Expand Down
29 changes: 29 additions & 0 deletions buildSrc/src/testKit/elasticsearch-build-resources/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
plugins {
id 'elasticsearch.build'
}

ext.licenseFile = file("$buildDir/dummy/license")
ext.noticeFile = file("$buildDir/dummy/notice")

exportBuildResources {
resource 'checkstyle.xml'
resource 'minimumCompilerVersion'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use other files, e.x. forbidden APIs to avoid confusion.

}

task sampleCopyAll(type: Sync) {
/** Note: no explicit dependency. This works with tasks that use the Provider API a.k.a "Lazy Configuration" **/
from exportBuildResources
into "$buildDir/sampleCopyAll"
}

task sample {
// This does not work, task dependencies can't be providers
// dependsOn exportBuildResources.resource('minimumRuntimeVersion')
// Nor does this, despite https://github.com/gradle/gradle/issues/3811
// dependsOn exportBuildResources.outputDir
// for now it's just
dependsOn exportBuildResources
doLast {
println "This task is using ${file(exportBuildResources.resource('minimumRuntimeVersion'))}"
}
}