Skip to content

Commit 009d69c

Browse files
authored
Merge pull request #1464 from jonesbusy/feature/renovate
Add recipe to Setup Renovate and Switch from Dependabot to Renovate
2 parents 0783590 + 6fce7a0 commit 009d69c

File tree

12 files changed

+384
-7
lines changed

12 files changed

+384
-7
lines changed

plugin-modernizer-core/pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
<dependencies>
1616
<dependency>
1717
<groupId>io.jenkins.tools.bom</groupId>
18-
<artifactId>bom-2.504.x</artifactId>
19-
<version>5857.vb_f3dd0731f44</version>
18+
<artifactId>bom-2.528.x</artifactId>
19+
<version>5888.vd99c2b_38128d</version>
2020
<type>pom</type>
2121
<scope>import</scope>
2222
</dependency>
@@ -105,6 +105,10 @@
105105
<groupId>org.openrewrite</groupId>
106106
<artifactId>rewrite-groovy</artifactId>
107107
</dependency>
108+
<dependency>
109+
<groupId>org.openrewrite</groupId>
110+
<artifactId>rewrite-json</artifactId>
111+
</dependency>
108112
<dependency>
109113
<groupId>org.openrewrite</groupId>
110114
<artifactId>rewrite-maven</artifactId>

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/extractor/ArchetypeCommonFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public enum ArchetypeCommonFile {
7979
* Renovate configuration file.
8080
* Not in archetype but to skip plugins using a different bot for updates
8181
*/
82-
RENOVATE("renovate.json"),
82+
RENOVATE(".github/renovate.json", "renovate.json"),
8383

8484
/**
8585
* Maven extensions file
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package io.jenkins.tools.pluginmodernizer.core.recipes;
2+
3+
import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile;
4+
import java.util.concurrent.atomic.AtomicBoolean;
5+
import org.openrewrite.ExecutionContext;
6+
import org.openrewrite.ScanningRecipe;
7+
import org.openrewrite.SourceFile;
8+
import org.openrewrite.Tree;
9+
import org.openrewrite.TreeVisitor;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
/**
14+
* Remove dependabot configuration files.
15+
*/
16+
public class RemoveDependabot extends ScanningRecipe<AtomicBoolean> {
17+
18+
/**
19+
* LOGGER.
20+
*/
21+
private static final Logger LOG = LoggerFactory.getLogger(RemoveDependabot.class);
22+
23+
@Override
24+
public String getDisplayName() {
25+
return "Remove dependabot";
26+
}
27+
28+
@Override
29+
public String getDescription() {
30+
return "Remove dependabot configuration file.";
31+
}
32+
33+
@Override
34+
public AtomicBoolean getInitialValue(ExecutionContext ctx) {
35+
return new AtomicBoolean(false);
36+
}
37+
38+
@Override
39+
public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean shouldRemove) {
40+
return new TreeVisitor<>() {
41+
42+
@Override
43+
public Tree visit(Tree tree, ExecutionContext ctx) {
44+
SourceFile sourceFile = (SourceFile) tree;
45+
if (ArchetypeCommonFile.DEPENDABOT.same(sourceFile.getSourcePath())) {
46+
shouldRemove.set(true);
47+
}
48+
return tree;
49+
}
50+
};
51+
}
52+
53+
@Override
54+
public TreeVisitor<?, ExecutionContext> getVisitor(AtomicBoolean shouldRemove) {
55+
return new TreeVisitor<>() {
56+
@Override
57+
public Tree visit(Tree tree, ExecutionContext ctx) {
58+
LOG.info("Checking if Dependabot should be removed");
59+
if (shouldRemove.get() && tree instanceof SourceFile sourceFile) {
60+
if (ArchetypeCommonFile.DEPENDABOT.same(sourceFile.getSourcePath())) {
61+
LOG.info("Deleting Dependabot file: {}", sourceFile.getSourcePath());
62+
return null;
63+
}
64+
}
65+
return tree;
66+
}
67+
};
68+
}
69+
}

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/recipes/SetupDependabot.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean shouldCreate) {
6464
@Override
6565
public Tree visit(Tree tree, ExecutionContext ctx) {
6666
SourceFile sourceFile = (SourceFile) tree;
67-
if (sourceFile.getSourcePath().equals(ArchetypeCommonFile.RENOVATE.getPath())) {
67+
if (ArchetypeCommonFile.RENOVATE.same(sourceFile.getSourcePath())) {
6868
LOG.info("Project is using Renovate. Doing nothing.");
6969
shouldCreate.set(false);
7070
}
71-
if (sourceFile.getSourcePath().equals(ArchetypeCommonFile.DEPENDABOT.getPath())) {
71+
if (ArchetypeCommonFile.DEPENDABOT.same(sourceFile.getSourcePath())) {
7272
LOG.info("Project is using Dependabot already. Doing nothing.");
7373
shouldCreate.set(false);
7474
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package io.jenkins.tools.pluginmodernizer.core.recipes;
2+
3+
import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile;
4+
import java.util.Collection;
5+
import java.util.Collections;
6+
import java.util.concurrent.atomic.AtomicBoolean;
7+
import java.util.stream.Collectors;
8+
import org.intellij.lang.annotations.Language;
9+
import org.openrewrite.ExecutionContext;
10+
import org.openrewrite.Option;
11+
import org.openrewrite.ScanningRecipe;
12+
import org.openrewrite.SourceFile;
13+
import org.openrewrite.Tree;
14+
import org.openrewrite.TreeVisitor;
15+
import org.openrewrite.json.JsonParser;
16+
import org.slf4j.Logger;
17+
import org.slf4j.LoggerFactory;
18+
19+
/**
20+
* Setup Renovate.
21+
*/
22+
public class SetupRenovate extends ScanningRecipe<AtomicBoolean> {
23+
24+
/**
25+
* The renovate file.
26+
*/
27+
@Language("json")
28+
public static final String RENOVATE_FILE = """
29+
{
30+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
31+
"extends": [
32+
"github>jenkinsci/renovate-config"
33+
]
34+
}
35+
""";
36+
37+
/**
38+
* LOGGER.
39+
*/
40+
private static final Logger LOG = LoggerFactory.getLogger(SetupRenovate.class);
41+
42+
/**
43+
* Force adding Renovate even if Dependabot is already setup.
44+
*/
45+
@Option(
46+
displayName = "Force",
47+
description = "Force adding Renovate even if Dependabot exists",
48+
example = "true",
49+
required = false)
50+
Boolean force;
51+
52+
public SetupRenovate() {
53+
this.force = null;
54+
}
55+
56+
public SetupRenovate(Boolean force) {
57+
this.force = force;
58+
}
59+
60+
@Override
61+
public String getDisplayName() {
62+
return "Setup Renovate";
63+
}
64+
65+
@Override
66+
public String getDescription() {
67+
return "Setup Renovate for the project. If not already setup. Ignore also if Dependabot is already setup.";
68+
}
69+
70+
@Override
71+
public AtomicBoolean getInitialValue(ExecutionContext ctx) {
72+
return new AtomicBoolean(true);
73+
}
74+
75+
@Override
76+
public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean shouldCreate) {
77+
return new TreeVisitor<>() {
78+
79+
@Override
80+
public Tree visit(Tree tree, ExecutionContext ctx) {
81+
SourceFile sourceFile = (SourceFile) tree;
82+
LOG.info("Force value: {}", force);
83+
if (sourceFile.getSourcePath().equals(ArchetypeCommonFile.DEPENDABOT.getPath())
84+
&& (force == null || !force)) {
85+
LOG.info("Project is using Dependabot. Doing nothing.");
86+
shouldCreate.set(false);
87+
}
88+
if (sourceFile.getSourcePath().equals(ArchetypeCommonFile.RENOVATE.getPath())) {
89+
LOG.info("Project is using Renovate already. Doing nothing.");
90+
shouldCreate.set(false);
91+
}
92+
return tree;
93+
}
94+
};
95+
}
96+
97+
@Override
98+
public Collection<SourceFile> generate(AtomicBoolean shouldCreate, ExecutionContext ctx) {
99+
if (shouldCreate.get()) {
100+
return JsonParser.builder()
101+
.build()
102+
.parse(RENOVATE_FILE)
103+
.map(brandNewFile ->
104+
(SourceFile) brandNewFile.withSourcePath(ArchetypeCommonFile.RENOVATE.getPath()))
105+
.collect(Collectors.toList());
106+
}
107+
return Collections.emptyList();
108+
}
109+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import io.jenkins.tools.pluginmodernizer.core.model.Plugin
2+
@import io.jenkins.tools.pluginmodernizer.core.model.Recipe
3+
@param Plugin plugin
4+
@param Recipe recipe
5+
chore(dependencies): Automate dependency updates with Renovate
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import io.jenkins.tools.pluginmodernizer.core.model.Plugin
2+
@import io.jenkins.tools.pluginmodernizer.core.model.Recipe
3+
@param Plugin plugin
4+
@param Recipe recipe
5+
chore(dependencies): Switch to Renovate for automated dependency updates

plugin-modernizer-core/src/main/resources/META-INF/rewrite/recipes.yml

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,13 +649,31 @@ recipeList:
649649
---
650650
type: specs.openrewrite.org/v1beta/recipe
651651
name: io.jenkins.tools.pluginmodernizer.SetupDependabot
652-
displayName: Setup dependabot
653-
description: Setup dependabot for the Jenkins plugin if it doesn't exist.
652+
displayName: Setup Dependabot
653+
description: Setup Dependabot for the Jenkins plugin if it doesn't exist.
654654
tags: ['chore', 'skip-verification']
655655
recipeList:
656656
- io.jenkins.tools.pluginmodernizer.core.recipes.SetupDependabot
657657
---
658658
type: specs.openrewrite.org/v1beta/recipe
659+
name: io.jenkins.tools.pluginmodernizer.SetupRenovate
660+
displayName: Setup Renovate
661+
description: Setup Renovate for the Jenkins plugin if it doesn't exist.
662+
tags: ['chore', 'skip-verification']
663+
recipeList:
664+
- io.jenkins.tools.pluginmodernizer.core.recipes.SetupRenovate
665+
---
666+
type: specs.openrewrite.org/v1beta/recipe
667+
name: io.jenkins.tools.pluginmodernizer.SwitchToRenovate
668+
displayName: Switch from Dependabot to Renovate
669+
description: Switch from Dependabot to Renovate for the Jenkins plugin.
670+
tags: ['chore', 'skip-verification']
671+
recipeList:
672+
- io.jenkins.tools.pluginmodernizer.core.recipes.SetupRenovate:
673+
force: true
674+
- io.jenkins.tools.pluginmodernizer.core.recipes.RemoveDependabot
675+
---
676+
type: specs.openrewrite.org/v1beta/recipe
659677
name: io.jenkins.tools.pluginmodernizer.RemoveReleaseDrafter
660678
displayName: Remove Release Drafter if CD is enabled
661679
description: Remove Release Drafter if CD is enabled. See https://www.jenkins.io/doc/developer/publishing/releasing-cd/#configure-release-drafter.

plugin-modernizer-core/src/test/java/io/jenkins/tools/pluginmodernizer/core/recipes/DeclarativeRecipesTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import static org.openrewrite.java.Assertions.srcMainJava;
77
import static org.openrewrite.java.Assertions.srcMainResources;
88
import static org.openrewrite.java.Assertions.srcTestJava;
9+
import static org.openrewrite.json.Assertions.json;
910
import static org.openrewrite.maven.Assertions.pomXml;
1011
import static org.openrewrite.test.SourceSpecs.text;
1112
import static org.openrewrite.yaml.Assertions.yaml;
@@ -3874,6 +3875,50 @@ void shouldAddDependabot() {
38743875
}));
38753876
}
38763877

3878+
@Test
3879+
void shouldAddRenovate() {
3880+
rewriteRun(
3881+
spec -> spec.recipeFromResource(
3882+
"/META-INF/rewrite/recipes.yml", "io.jenkins.tools.pluginmodernizer.SetupRenovate"),
3883+
text(""), // Need one minimum file to trigger the recipe
3884+
// language=yaml
3885+
json(null, """
3886+
{
3887+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3888+
"extends": [
3889+
"github>jenkinsci/renovate-config"
3890+
]
3891+
}
3892+
""", sourceSpecs -> {
3893+
sourceSpecs.path(ArchetypeCommonFile.RENOVATE.getPath());
3894+
}));
3895+
}
3896+
3897+
@Test
3898+
void shouldSwitchToRenovate() {
3899+
rewriteRun(
3900+
spec -> spec.recipeFromResource(
3901+
"/META-INF/rewrite/recipes.yml", "io.jenkins.tools.pluginmodernizer.SwitchToRenovate"),
3902+
// language=yaml
3903+
yaml("""
3904+
---
3905+
version: 2
3906+
""", null, sourceSpecs -> {
3907+
sourceSpecs.path(ArchetypeCommonFile.DEPENDABOT.getPath());
3908+
}),
3909+
// language=yaml
3910+
json(null, """
3911+
{
3912+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
3913+
"extends": [
3914+
"github>jenkinsci/renovate-config"
3915+
]
3916+
}
3917+
""", sourceSpecs -> {
3918+
sourceSpecs.path(ArchetypeCommonFile.RENOVATE.getPath());
3919+
}));
3920+
}
3921+
38773922
/**
38783923
* Note this test need to be adapted to fix the Jenkinsfile to use latest archetype
38793924
*/
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.jenkins.tools.pluginmodernizer.core.recipes;
2+
3+
import static org.openrewrite.yaml.Assertions.yaml;
4+
5+
import io.jenkins.tools.pluginmodernizer.core.extractor.ArchetypeCommonFile;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.parallel.Execution;
8+
import org.junit.jupiter.api.parallel.ExecutionMode;
9+
import org.openrewrite.test.RewriteTest;
10+
11+
/**
12+
* Test for {@link RemoveDependabot}.
13+
*/
14+
@Execution(ExecutionMode.CONCURRENT)
15+
public class RemoveDependabotTest implements RewriteTest {
16+
17+
@Test
18+
void shouldRemoveDependabot() {
19+
rewriteRun(
20+
spec -> spec.recipe(new RemoveDependabot()),
21+
// language=yaml
22+
yaml("{}", null, sourceSpecs -> {
23+
sourceSpecs.path(ArchetypeCommonFile.DEPENDABOT.getPath());
24+
}));
25+
}
26+
}

0 commit comments

Comments
 (0)