Skip to content

Commit

Permalink
ConfigTarTask supports custom configuration.yml location (#1646)
Browse files Browse the repository at this point in the history
* abstract task classes have closure overrides added automatically

* ConfigTar supports custom configuration.yml location

* Add generated changelog entries

---------

Co-authored-by: svc-changelog <svc-changelog@palantir.com>
  • Loading branch information
CRogers and svc-changelog authored May 16, 2024
1 parent 7a81323 commit 756b8b0
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 42 deletions.
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-1646.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: fix
fix:
description: '`ConfigTarTask` supports custom `configuration.yml` location'
links:
- https://github.com/palantir/sls-packaging/pull/1646
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* (c) Copyright 2024 Palantir Technologies Inc. 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.
*/

package com.palantir.gradle.dist;

import org.gradle.api.Action;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.ProjectLayout;

public final class DeploymentDirInclusion {

public static void includeFromDeploymentDirs(
ProjectLayout projectLayout,
BaseDistributionExtension distributionExtension,
CopySpec root,
Action<CopySpec> extraConfig) {

root.into("deployment", t -> {
// We exclude configuration.yml from the general "deployment" importer, as it is special cased and
// handled separately below.
t.exclude("configuration.yml");
t.from("deployment");
t.from(projectLayout.getBuildDirectory().dir("deployment"));
extraConfig.execute(t);
});

root.into("deployment", t -> {
// Import configuration.yml from the where it is declared in the extension, allowing tasks to
// generate it and have dependent tasks (like this distTar) get the correct task deps.
t.from(distributionExtension.getConfigurationYml().map(file -> {
// We enforce the file is called configuration.yml. Unfortunately, there is an internal
// piece of code that deduplicates files in gradle-sls-docker. This deduplication is done
// using this copyspec. Were we to just call `.rename()` on this copyspec arm (to allow plugin
// devs to output their generated configuration.ymls to some file not called configuration.yml) this
// rename happens after the renames in the file deduplication code. Unfortunately, it was very hard
// to disentangle the file deduplication from using this copyspec and maintain build performance
// - instead we choose to simply check that the `configuration.yml` is called the right thing
// so it doesn't need to be renamed here.
if (file.getAsFile().getName().equals("configuration.yml")) {
return file;
}

throw new IllegalStateException("The file set to be the value of getConfigurationYml() "
+ "must be called configuration.yml. Instead, it was called " + file.getAsFile());
}));
});
}

private DeploymentDirInclusion() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.palantir.gradle.dist.service;

import com.palantir.gradle.dist.DeploymentDirInclusion;
import java.util.Arrays;
import java.util.concurrent.Callable;
import org.gradle.api.JavaVersion;
Expand Down Expand Up @@ -100,35 +101,11 @@ static void configure(
t.setFileMode(0755);
});

root.into("deployment", t -> {
// We exclude configuration.yml from the general "deployment" importer, as it is special cased and
// handled separately below.
t.exclude("configuration.yml");
t.from("deployment");
t.from(project.getLayout().getBuildDirectory().dir("deployment"));
t.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE);
});

root.into("deployment", t -> {
// Import configuration.yml from the where it is declared in the extension, allowing tasks to
// generate it and have dependent tasks (like this distTar) get the correct task deps.
t.from(distributionExtension.getConfigurationYml().map(file -> {
// We enforce the file is called configuration.yml. Unfortunately, there is an internal
// piece of code that deduplicates files in gradle-sls-docker. This deduplication is done
// using this copyspec. Were we to just call `.rename()` on this copyspec arm (to allow plugin
// devs to output their generated configuration.ymls to some file not called configuration.yml) this
// rename happens after the renames in the file deduplication code. Unfortunately, it was very hard
// to disentangle the file deduplication from using this copyspec and maintain build performance
// - instead we choose to simply check that the `configuration.yml` is called the right thing
// so it doesn't need to be renamed here.
if (file.getAsFile().getName().equals("configuration.yml")) {
return file;
}

throw new IllegalStateException("The file set to be the value of getConfigurationYml() "
+ "must be called configuration.yml. Instead, it was called " + file.getAsFile());
}));
});
DeploymentDirInclusion.includeFromDeploymentDirs(
project.getLayout(),
distributionExtension,
root,
t -> t.setDuplicatesStrategy(DuplicatesStrategy.INCLUDE));
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
package com.palantir.gradle.dist.tasks;

import com.palantir.gradle.dist.BaseDistributionExtension;
import com.palantir.gradle.dist.DeploymentDirInclusion;
import com.palantir.gradle.dist.ObjectMappers;
import com.palantir.gradle.dist.service.JavaServiceDistributionPlugin;
import groovy.lang.Closure;
import java.io.File;
import java.io.IOException;
import org.gradle.api.Action;
import org.gradle.api.Project;
Expand All @@ -30,19 +29,12 @@
import org.gradle.api.tasks.bundling.Compression;
import org.gradle.api.tasks.bundling.Tar;

public class ConfigTarTask extends Tar {
public abstract class ConfigTarTask extends Tar {
@Override
public final AbstractCopyTask from(Object... sourcePaths) {
return this.from(sourcePaths, _ignored -> {});
}

@Override
@SuppressWarnings({"RawTypes", "deprecation"})
public final AbstractCopyTask from(Object sourcePath, Closure closure) {
// TODO(fwindheuser): Replace usage of 'ClosureBackedAction' before moving to Gradle 8.
return this.from(sourcePath, new org.gradle.util.ClosureBackedAction<>(closure));
}

@Override
public final AbstractCopyTask from(Object sourcePath, Action<? super CopySpec> configureAction) {
return super.from(sourcePath, copySpec -> {
Expand All @@ -63,8 +55,8 @@ public static TaskProvider<ConfigTarTask> createConfigTarTask(Project project, B
"Creates a compressed, gzipped tar file that contains the sls configuration files for the product");
task.setCompression(Compression.GZIP);

task.from(new File(project.getProjectDir(), "deployment"));
task.from(new File(project.getBuildDir(), "deployment"));
DeploymentDirInclusion.includeFromDeploymentDirs(project.getLayout(), ext, task, _ignored -> {});

task.getDestinationDirectory()
.set(project.getLayout().getBuildDirectory().dir("distributions"));
task.getArchiveBaseName().set(ext.getDistributionServiceName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.palantir.gradle.dist.tasks


import com.google.common.base.Throwables
import nebula.test.IntegrationSpec

class ConfigTarTaskIntegrationSpec extends IntegrationSpec {
Expand Down Expand Up @@ -74,6 +74,59 @@ class ConfigTarTaskIntegrationSpec extends IntegrationSpec {
manifest.contains('asset.v1')
}

def 'configTar task support configuration.ymls being generated to a non-standard location'() {
setup:
createUntarBuildFile(buildFile, "asset", "asset", "foo-asset")

// language=Gradle
buildFile << '''
task createConfigurationYml {
outputs.file('build/some-place/configuration.yml')
doFirst {
file('build/some-place/configuration.yml').text = 'custom: yml'
}
}
distribution {
configurationYml.fileProvider(tasks.named('createConfigurationYml').map { it.outputs.files.singleFile })
}
'''.stripIndent(true)

when:
runTasksSuccessfully(':configTar', ':untar')

then:
def configuration = new File(projectDir, 'dist/foo-asset-0.0.1/deployment/configuration.yml').text
configuration.contains('custom: yml')
}

def 'errors out if the custom configuration.yml location is not a file called configuration.yml'() {
setup:
createUntarBuildFile(buildFile, "asset", "asset", "foo-asset")

// language=Gradle
buildFile << '''
task createConfigurationYml {
outputs.file('build/some-place/something-else.yml')
doFirst {
file('build/some-place/something-else.yml').text = 'custom: yml'
}
}
distribution {
configurationYml.fileProvider(tasks.named('createConfigurationYml').map { it.outputs.files.singleFile })
}
'''.stripIndent(true)

when:
def failureMessage = Throwables.getRootCause(runTasksWithFailure(':configTar', ':untar').failure).message

then:
failureMessage.contains('must be called configuration.yml')
}

private static createUntarBuildFile(buildFile, pluginType, artifactType, name) {
buildFile << """
apply plugin: 'com.palantir.sls-${pluginType}-distribution'
Expand Down

0 comments on commit 756b8b0

Please sign in to comment.