Skip to content

Commit

Permalink
WIP: Example app running Spring Boot Upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
fabapp2 committed Oct 18, 2023
1 parent 8d3cda1 commit faf353b
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 35 deletions.
16 changes: 11 additions & 5 deletions sbm-support-rewrite/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,6 @@
<artifactId>rewrite-maven</artifactId>
<version>${rewrite.version}</version>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java</artifactId>
<version>${rewrite.version}</version>
</dependency>
<dependency>
<groupId>org.openrewrite</groupId>
<artifactId>rewrite-java-17</artifactId>
Expand Down Expand Up @@ -183,6 +178,17 @@
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-migrate-java</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.openrewrite.recipe</groupId>
<artifactId>rewrite-spring</artifactId>
<version>5.0.10</version>
</dependency>


<dependency>
<groupId>org.openrewrite.maven</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
import org.openrewrite.Recipe;
import org.openrewrite.Result;
import org.openrewrite.SourceFile;
import org.openrewrite.config.RecipeDescriptor;
import org.openrewrite.internal.InMemoryLargeSourceSet;

import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.joining;

// TODO: make package private
public class ProjectResourceSet {

Expand Down Expand Up @@ -103,9 +106,40 @@ public List<Recipe> getRecipeList() {
.getChangeset()
.getAllResults();

results.forEach(r -> logRecipesThatMadeChanges(r));

migrationResultMerger.mergeResults(this, results);
}

protected void logRecipesThatMadeChanges(Result result) {
String indent = " ";
String prefix = " ";
for (RecipeDescriptor recipeDescriptor : result.getRecipeDescriptorsThatMadeChanges()) {
logRecipe(recipeDescriptor, prefix);
prefix = prefix + indent;
}
}

private void logRecipe(RecipeDescriptor rd, String prefix) {
StringBuilder recipeString = new StringBuilder(prefix + rd.getName());
if (!rd.getOptions().isEmpty()) {
String opts = rd.getOptions().stream().map(option -> {
if (option.getValue() != null) {
return option.getName() + "=" + option.getValue();
}
return null;
}
).filter(Objects::nonNull).collect(joining(", "));
if (!opts.isEmpty()) {
recipeString.append(": {").append(opts).append("}");
}
}
System.out.println(recipeString);
for (RecipeDescriptor rchild : rd.getRecipeList()) {
logRecipe(rchild, prefix + " ");
}
}

void clearDeletedResources() {
Iterator<RewriteSourceFileHolder<? extends SourceFile>> iterator = this.projectResources.iterator();
while (iterator.hasNext()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2021 - 2023 the original author or authors.
*
* 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
*
* https://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.springframework.sbm.example;

import org.apache.commons.io.FileUtils;
import org.openrewrite.Recipe;
import org.openrewrite.SourceFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.sbm.parsers.ProjectScanner;
import org.springframework.sbm.parsers.RewriteProjectParser;
import org.springframework.sbm.parsers.RewriteProjectParsingResult;
import org.springframework.sbm.project.resource.ProjectResourceSet;
import org.springframework.sbm.project.resource.ProjectResourceSetFactory;
import org.springframework.sbm.project.resource.ProjectResourceSetSerializer;
import org.springframework.sbm.recipes.RewriteRecipeDiscovery;
import org.springframework.sbm.test.util.GitTestHelper;

import java.nio.file.Path;
import java.util.List;

import static java.util.stream.Collectors.joining;

@SpringBootApplication
public class BootUpgradeExample implements CommandLineRunner {

public static void main(String[] args) {
SpringApplication.run(BootUpgradeExample.class, args);
}

@Autowired
ProjectScanner scanner;
@Autowired
RewriteProjectParser parser;
@Autowired
RewriteRecipeDiscovery discovery;
@Autowired
ProjectResourceSetSerializer serializer;
@Autowired
ProjectResourceSetFactory factory;

@Override
public void run(String... args) throws Exception {

// Clone Spring PetClinic using Boot 2.7
String tmpDir = System.getProperty("java.io.tmpdir");
String target = tmpDir + "/cloned";
FileUtils.forceDelete(Path.of(target).toFile());
Path baseDir = GitTestHelper.cloneProjectCommit("https://github.com/spring-projects/spring-petclinic.git", target, "9ecdc1111e3da388a750ace41a125287d9620534");

// parse
RewriteProjectParsingResult parsingResult = parser.parse(baseDir);
List<SourceFile> sourceFiles = parsingResult.sourceFiles();

// create ProjectResourceSet
ProjectResourceSet projectResourceSet = factory.create(baseDir, sourceFiles);

// find recipe
String recipeName = "org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_1";
List<Recipe> recipes = discovery.discoverRecipes();
System.out.println("Discovered %d recipes.".formatted(recipes.size()));
Recipe recipe = recipes.stream().filter(r -> r.getName().equals(recipeName)).findFirst().get();

// apply recipe
System.out.println("Apply recipe '%s'".formatted(recipe.getName()));
projectResourceSet.apply(recipe);

// write changes to fs
serializer.writeChanges(projectResourceSet);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.recipes;
package org.springframework.sbm.example.recipes;

import org.openrewrite.Recipe;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package org.springframework.sbm.parsers;

import com.example.recipes.DummyRecipe;
import org.springframework.sbm.example.recipes.DummyRecipe;
import io.example.recipes.AnotherDummyRecipe;
import org.assertj.core.data.Index;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -79,17 +79,17 @@ void shouldDiscoverDummyRecipes() {
void providingAcceptedPackagesShouldOnlyShowRecipesWithMatchingPackage() {
ClasspathScanningLoader resourceLoader1 = new ClasspathScanningLoader(new Properties(), new String[]{"com.example"});
Collection<Recipe> recipes = resourceLoader1.listRecipes();
assertThat(recipes).anyMatch(r -> com.example.recipes.DummyRecipe.class == r.getClass());
assertThat(recipes).anyMatch(r -> DummyRecipe.class == r.getClass());
assertThat(recipes).noneMatch(r -> io.example.recipes.AnotherDummyRecipe.class == r.getClass());

ClasspathScanningLoader resourceLoader2 = new ClasspathScanningLoader(new Properties(), new String[]{"io.example"});
Collection<Recipe> recipes2 = resourceLoader2.listRecipes();
assertThat(recipes2).noneMatch(r -> com.example.recipes.DummyRecipe.class == r.getClass());
assertThat(recipes2).noneMatch(r -> DummyRecipe.class == r.getClass());
assertThat(recipes2).anyMatch(r -> io.example.recipes.AnotherDummyRecipe.class == r.getClass());

ClasspathScanningLoader resourceLoader3 = new ClasspathScanningLoader(new Properties(), new String[]{"io.example", "com.example"});
Collection<Recipe> recipes3 = resourceLoader3.listRecipes();
assertThat(recipes3).anyMatch(r -> com.example.recipes.DummyRecipe.class == r.getClass());
assertThat(recipes3).anyMatch(r -> DummyRecipe.class == r.getClass());
assertThat(recipes3).anyMatch(r -> io.example.recipes.AnotherDummyRecipe.class == r.getClass());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.springframework.sbm.parsers.maven;

import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
Expand All @@ -40,8 +39,6 @@
import org.openrewrite.maven.MavenExecutionContextView;
import org.openrewrite.maven.MavenSettings;
import org.openrewrite.maven.cache.*;
import org.openrewrite.maven.cache.LocalMavenArtifactCache;
import org.openrewrite.maven.cache.MavenArtifactCache;
import org.openrewrite.maven.tree.MavenResolutionResult;
import org.openrewrite.shaded.jgit.api.Git;
import org.openrewrite.shaded.jgit.api.errors.GitAPIException;
Expand All @@ -58,13 +55,12 @@
import org.springframework.sbm.parsers.events.RewriteParsingEventListenerAdapter;
import org.springframework.sbm.scopes.ScanScope;
import org.springframework.sbm.test.util.DummyResource;
import org.springframework.sbm.test.util.GitTestHelper;
import org.springframework.sbm.utils.ResourceUtil;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
Expand Down Expand Up @@ -302,7 +298,7 @@ void parseMultiModule1_WithCustomParser() {
@Disabled("https://github.com/openrewrite/rewrite/issues/3409")
void parseComplexMavenReactorProject() {
String target = "./testcode/maven-projects/cwa-server";
cloneProject("https://github.com/corona-warn-app/cwa-server.git", target, "v3.2.0");
GitTestHelper.cloneProjectTag("https://github.com/corona-warn-app/cwa-server.git", target, "v3.2.0");
Path projectRoot = Path.of(target).toAbsolutePath().normalize(); // SBM root
RewriteMavenProjectParser projectParser = sut;
ExecutionContext executionContext = new InMemoryExecutionContext(t -> t.printStackTrace());
Expand Down Expand Up @@ -434,25 +430,6 @@ private static void verifyExecutionContext(RewriteProjectParsingResult parsingRe
assertThat(MavenExecutionContextView.view(resultingExecutionContext).getRepositories()).isEmpty();
}

private void cloneProject(String url, String target, String tag) {
File directory = Path.of(target).toFile();
if (directory.exists()) {
return;
}
try {
Git git = Git.cloneRepository()
.setDirectory(directory)
.setURI(url)
.call();

git.checkout()
.setName("refs/tags/" + tag)
.call();

} catch (GitAPIException e) {
throw new RuntimeException(e);
}
}

private void verifyMavenParser(RewriteProjectParsingResult parsingResult) {
verify(parsingResult.sourceFiles().get(0), Xml.Document.class, "pom.xml", document -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2021 - 2023 the original author or authors.
*
* 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
*
* https://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.springframework.sbm.test.util;

import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.shaded.jgit.api.Git;
import org.openrewrite.shaded.jgit.api.errors.GitAPIException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;

/**
* @author Fabian Krüger
*/
public class GitTestHelper {

public static Path cloneProjectCommit(String url, String target, String commitHash) {
return checkout(url, target, commitHash);
}

public static Path cloneProjectTag(String url, String target, String tag) {
String ref = "refs/tags/" + tag;
return checkout(url, target, ref);
}

@NotNull
private static Path checkout(String url, String target, String ref) {
try {
File directory = Path.of(target).toFile();
if (!directory.exists()) {
FileUtils.forceMkdir(directory.toPath().toAbsolutePath().normalize().toFile());
}
Git git = Git.cloneRepository()
.setDirectory(directory)
.setURI(url)
.call();

git.checkout()
.setName(ref)
.call();

return git.getRepository().getDirectory().toPath().getParent();
} catch (GitAPIException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

0 comments on commit faf353b

Please sign in to comment.