Skip to content

Commit

Permalink
Add recipe to enable Develocity build cache in xml configuration (#4856)
Browse files Browse the repository at this point in the history
* Add enable buildcache recipe

* Polish

* Use `<local><enabled>`

* Rename recipe to be Develocity specific, to avoid confusion with Maven build cache

---------

Co-authored-by: Tim te Beek <[email protected]>
  • Loading branch information
nielsdebruin and timtebeek authored Jan 7, 2025
1 parent 621dcfa commit 15f7751
Show file tree
Hide file tree
Showing 2 changed files with 255 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2025 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.maven;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.xml.XmlVisitor;
import org.openrewrite.xml.tree.Xml;

@Value
@EqualsAndHashCode(callSuper = false)
public class EnableDevelocityBuildCache extends Recipe {

@Override
public String getDisplayName() {
return "Enable Develocity build cache";
}

@Override
public String getDescription() {
return "Add Develocity build cache configuration to any `.mvn/` Develocity configuration file that lack existing configuration.";
}

@Option(displayName = "Enable local build cache",
description = "Value for `//develocity/buildCache/local/enabled`.",
example = "true",
required = false)
@Nullable
String buildCacheLocalEnabled;

@Option(displayName = "Enable remote build cache",
description = "Value for `//develocity/buildCache/remote/enabled`.",
example = "true",
required = false)
@Nullable
String buildCacheRemoteEnabled;

@Option(displayName = "Enable remote build cache store",
description = "Value for `//develocity/buildCache/remote/storeEnabled`.",
example = "#{isTrue(env['CI'])}",
required = false)
@Nullable
String buildCacheRemoteStoreEnabled;

@Override
public Validated<Object> validate(ExecutionContext ctx) {
return super.validate(ctx)
.and(Validated.notBlank("buildCacheLocalEnabled", buildCacheLocalEnabled)
.or(Validated.notBlank("buildCacheRemoteEnabled", buildCacheRemoteEnabled))
.or(Validated.notBlank("buildCacheRemoteStoreEnabled", buildCacheRemoteStoreEnabled)));
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
XmlVisitor<ExecutionContext> visitor = new XmlVisitor<ExecutionContext>() {
@Override
public Xml visitDocument(Xml.Document document, ExecutionContext ctx) {
Xml.Tag rootTag = document.getRoot();

if ("develocity".equals(rootTag.getName()) && !rootTag.getChild("buildCache").isPresent()) {
Xml.Tag tag = Xml.Tag.build(buildCacheConfig());
rootTag = maybeAutoFormat(rootTag, rootTag.withContent(ListUtils.concat(rootTag.getChildren(), tag)), ctx);
return document.withRoot(rootTag);
}
return document;
}
};

return Preconditions.check(new FindSourceFiles(".mvn/*.xml"), visitor);
}

private String buildCacheConfig() {
StringBuilder sb = new StringBuilder("<buildCache>");
if (!StringUtils.isBlank(buildCacheLocalEnabled)) {
sb.append("<local>");
sb.append("<enabled>").append(buildCacheLocalEnabled).append("</enabled>");
sb.append("</local>");
}
if (!StringUtils.isBlank(buildCacheRemoteEnabled) || !StringUtils.isBlank(buildCacheRemoteStoreEnabled)) {
sb.append("<remote>");
if (!StringUtils.isBlank(buildCacheRemoteEnabled)) {
sb.append("<enabled>").append(buildCacheRemoteEnabled).append("</enabled>");
}
if (!StringUtils.isBlank(buildCacheRemoteStoreEnabled)) {
sb.append("<storeEnabled>").append(buildCacheRemoteStoreEnabled).append("</storeEnabled>");
}
sb.append("</remote>");
}
sb.append("</buildCache>");
return sb.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright 2025 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.maven;

import org.junit.jupiter.api.Test;
import org.openrewrite.DocumentExample;
import org.openrewrite.InMemoryExecutionContext;
import org.openrewrite.Validated;
import org.openrewrite.test.RewriteTest;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.openrewrite.xml.Assertions.xml;

class EnableDevelocityBuildCacheTest implements RewriteTest {

@DocumentExample
@Test
void addBuildCacheAllConfigWithOptions() {
rewriteRun(
spec -> spec.recipe(new EnableDevelocityBuildCache("true", "true", "#{isTrue(env['CI'])}")),
xml(
"""
<develocity>
</develocity>
""",
"""
<develocity>
<buildCache>
<local>
<enabled>true</enabled>
</local>
<remote>
<enabled>true</enabled>
<storeEnabled>#{isTrue(env['CI'])}</storeEnabled>
</remote>
</buildCache>
</develocity>
""",
spec -> spec.path(".mvn/develocity.xml")
)
);
}

@Test
void requireAtLeastOneOption() {
Validated<Object> validate = new EnableDevelocityBuildCache(null, null, null).validate(new InMemoryExecutionContext());
assertThat(validate.isValid()).isFalse();
}

@Test
void addBuildCacheConfigWithLocalOnly() {
rewriteRun(
spec -> spec.recipe(new EnableDevelocityBuildCache("true", null, null)),
xml(
"""
<develocity>
</develocity>
""",
"""
<develocity>
<buildCache>
<local>
<enabled>true</enabled>
</local>
</buildCache>
</develocity>
""",
spec -> spec.path(".mvn/develocity.xml")
)
);
}

@Test
void addBuildCacheAllConfigWithRemoteOnly() {
rewriteRun(
spec -> spec.recipe(new EnableDevelocityBuildCache(null, "true", "#{isTrue(env['CI'])}")),
xml(
"""
<develocity>
</develocity>
""",
"""
<develocity>
<buildCache>
<remote>
<enabled>true</enabled>
<storeEnabled>#{isTrue(env['CI'])}</storeEnabled>
</remote>
</buildCache>
</develocity>
""",
spec -> spec.path(".mvn/develocity.xml")
)
);
}

@Test
void shouldNotModifyExistingConfiguration() {
rewriteRun(
spec -> spec.recipe(new EnableDevelocityBuildCache("true", "true", "true")),
xml(
"""
<develocity>
<buildCache>
<local>
<enabled>false</enabled>
</local>
<remote>
<enabled>false</enabled>
<storeEnabled>false</storeEnabled>
</remote>
</buildCache>
</develocity>
""",
spec -> spec.path(".mvn/develocity.xml")
)
);
}

@Test
void shouldNotModifyOtherLocations() {
rewriteRun(
spec -> spec.recipe(new EnableDevelocityBuildCache("true", "true", "true")),
xml(
"""
<develocity>
</develocity>
""",
spec -> spec.path("src/test/resources/develocity.xml")
)
);
}
}

0 comments on commit 15f7751

Please sign in to comment.