Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task to update plugin and dependencies #193

Merged
merged 16 commits into from
Dec 7, 2021
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Gradle plugin to create a java and kotlin application based on Clean Architectur
- [Generate Acceptance Tests](#generate-acceptance-test)
- [Validate Structure](#validate-structure)
- [Delete Module](#delete-module)
- [Update Project](#update-project)
- [How can I help?](#how-can-i-help)
- [Whats Next?](#whats-next)

Expand Down Expand Up @@ -438,6 +439,17 @@ The **`deleteModule | dm`** task will delete a sub project, this task has one re
```

<br><br><br>

## Update Project

The **`updateCleanArchitecture | u`** task will update plugin and dependencies in all sub projects, this task has one optional parameter `dependencies`
if you only want to update some dependencies the dependency need to contain the group, and the artifact for example for the dependency **cleanArchitecture** you will need to append **co.com.bancolombia:cleanArchitecture**.

```shell
gradle updateCleanArchitecture --dependencies=[dependency1, dependency2, ...]
gradle u --dependencies=[dependency1, dependency2, ...]
```


# How can I help?

Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies {
api 'com.github.spullara.mustache.java:compiler:0.9.6'
api 'com.fasterxml.jackson.core:jackson-databind:2.11.0'
api 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11.0'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0'
api 'commons-io:commons-io:2.7'
api gradleApi()
testImplementation "org.mockito:mockito-core:2.9.0"
Expand All @@ -56,6 +57,8 @@ dependencies {

compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
testImplementation "com.squareup.okhttp3:mockwebserver:4.9.0"
}

gradlePlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;

/** A simple functional test for the 'co.com.bancolombia.greeting' plugin. */
public class PluginCleanFunctionalTest {
File projectDir = new File("build/functionalTest");
static File projectDir = new File("build/functionalTest");
GradleRunner runner;

@Before
Expand All @@ -41,7 +42,12 @@ public void init() throws IOException {
runner.withPluginClasspath();
}

private void deleteStructure(Path sourcePath) {
@AfterClass
public static void clean() {
deleteStructure(projectDir.toPath());
}

private static void deleteStructure(Path sourcePath) {

try {
Files.walkFileTree(
Expand Down Expand Up @@ -937,6 +943,31 @@ public void shouldGenerateMQDrivenAdapterNoReactive() {
assertEquals(result.task(":" + task).getOutcome(), TaskOutcome.SUCCESS);
}

@Test
public void shouldUpdateProject() {
canRunTaskGenerateStructureWithOutParameters();

String task = "updateCleanArchitecture";

runner.withArguments(task);
runner.withProjectDir(projectDir);
BuildResult result = runner.build();

assertEquals(result.task(":" + task).getOutcome(), TaskOutcome.SUCCESS);
}

@Test
public void shouldUpdateProjectWithOneDependency() {
canRunTaskGenerateStructureWithOutParameters();
String task = "updateCleanArchitecture";

runner.withArguments(task, "--dependencies=org.mockito:mockito-core org.projectlombok:lombok");
runner.withProjectDir(projectDir);
BuildResult result = runner.build();

assertEquals(result.task(":" + task).getOutcome(), TaskOutcome.SUCCESS);
}

private void writeString(File file, String string) throws IOException {
try (Writer writer = new FileWriter(file)) {
writer.write(string);
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/co/com/bancolombia/PluginClean.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,14 @@ private List<TaskModel> initTasks() {
.group(Constants.PLUGIN_TASK_GROUP)
.taskAction(GenerateHelperTask.class)
.build());

tasksModels.add(
TaskModel.builder()
.name("updateCleanArchitecture")
.shortcut("u")
.description("Update project dependencies")
.group(Constants.PLUGIN_TASK_GROUP)
.taskAction(UpdateProjectTask.class)
.build());
return tasksModels;
}

Expand Down
49 changes: 49 additions & 0 deletions src/main/java/co/com/bancolombia/adapters/RestService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package co.com.bancolombia.adapters;

import co.com.bancolombia.models.DependencyRelease;
import co.com.bancolombia.models.Release;
import co.com.bancolombia.utils.RestConsumer;
import java.util.Optional;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;

public class RestService {
public static final String PLUGIN_RELEASES =
"http://api.github.com/repos/bancolombia/scaffold-clean-architecture/releases";
public static final String DEPENDENCY_RELEASES =
"https://search.maven.org/solrsearch/select?q=g:%22%s%22+AND+a:%22%s%22&core=gav&rows=1&wt=json";
private final Logger logger = Logging.getLogger(RestService.class);

public Release getLatestPluginVersion() {
try {
return RestConsumer.callRequest(PLUGIN_RELEASES, Release[].class)[0];
} catch (Exception e) {
logger.lifecycle(
"\tx Can't check the latest version of the plugin, reason: {}", e.getMessage());
return null;
}
}

public Optional<DependencyRelease> getTheLastDependencyRelease(String dependency) {
try {
return Optional.of(
RestConsumer.callRequest(getDependencyEndpoint(dependency), DependencyRelease.class));
} catch (Exception e) {
logger.lifecycle(
"\tx Can't update this dependency {}, reason: {}", dependency, e.getMessage());
return Optional.empty();
}
}

private String getDependencyEndpoint(String dependency) {
String[] id = dependency.split(":");
if (id.length >= 2) {
return DEPENDENCY_RELEASES.replaceFirst("%s", id[0]).replace("%s", id[1]);
}
throw new IllegalArgumentException(
dependency
+ " is not a valid dependency usage: gradle u "
+ "--dependency "
+ "dependency.group:artifact");
}
}
45 changes: 44 additions & 1 deletion src/main/java/co/com/bancolombia/factory/ModuleBuilder.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package co.com.bancolombia.factory;

import co.com.bancolombia.Constants;
import co.com.bancolombia.adapters.RestService;
import co.com.bancolombia.exceptions.ParamNotFoundException;
import co.com.bancolombia.exceptions.ValidationException;
import co.com.bancolombia.factory.validations.Validation;
import co.com.bancolombia.models.FileModel;
import co.com.bancolombia.models.Release;
import co.com.bancolombia.models.TemplateDefinition;
import co.com.bancolombia.utils.FileUpdater;
import co.com.bancolombia.utils.FileUtils;
Expand All @@ -21,8 +23,11 @@
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.SneakyThrows;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;

Expand All @@ -42,6 +47,7 @@ public class ModuleBuilder {
private final Logger logger;
@Getter private final Project project;
private ObjectNode properties;
private final RestService restService = new RestService();

public ModuleBuilder(Project project) {
this.project = project;
Expand All @@ -66,7 +72,18 @@ public ModuleBuilder(Project project) {
}

public void persist() throws IOException {
Release latestRelease = restService.getLatestPluginVersion();
if (latestRelease != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

if (latestRelease != null && !latestRelease.getTagName().equals(Utils.getVersionPlugin()))
in a if the evaluation is left to right

if (!latestRelease.getTagName().equals(Utils.getVersionPlugin())) {
logger.lifecycle(
"WARNING: You have an old version of the plugin, the latest version is: {}",
latestRelease.getTagName());
params.put("latestRelease", latestRelease);
}
}
logger.lifecycle("Applying changes");

logger.lifecycle("");
dirs.forEach(
dir -> {
getProject().mkdir(dir);
Expand Down Expand Up @@ -125,6 +142,27 @@ public void removeFromSettings(String module) throws IOException {
});
}

@SneakyThrows
public void updateExpression(String path, String regex, String value) {
updateFile(path, properties -> Utils.replaceExpression(properties, regex, value));
}

@SneakyThrows
public Set<String> findExpressions(String path, String regex) {
logger.lifecycle(
"find "
+ Pattern.compile(regex).matcher(readFile(path)).results().count()
+ " dependencies in "
+ path);
return Pattern.compile(regex)
.matcher(readFile(path))
.results()
.map(MatchResult::group)
.map(s -> s.replaceAll("'", ""))
.map(s -> s.replaceAll("\"", ""))
.collect(Collectors.toSet());
}

public void appendDependencyToModule(String module, String dependency) throws IOException {
logger.lifecycle("adding dependency {} to module {}", dependency, module);
String buildFilePath = project.getChildProjects().get(module).getBuildFile().getPath();
Expand Down Expand Up @@ -254,14 +292,19 @@ private Boolean getABooleanProperty(String property) {
}

private void updateFile(String path, FileUpdater updater) throws IOException {
String content = readFile(path);
addFile(path, updater.update(content));
}

private String readFile(String path) throws IOException {
FileModel current = files.get(path);
String content;
if (current == null) {
content = FileUtils.readFile(getProject(), path).collect(Collectors.joining("\n"));
} else {
content = current.getContent();
}
addFile(path, updater.update(content));
return content;
}

private ObjectNode getNode(ObjectNode node, List<String> attributes) {
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/co/com/bancolombia/models/DependencyRelease.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package co.com.bancolombia.models;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@JsonDeserialize(using = DependencyReleasesDeserializer.class)
public class DependencyRelease {
@JsonProperty("v")
private String version;

@JsonProperty("g")
private String group;

@JsonProperty("a")
private String artifact;

@Override
public String toString() {
return String.format("%s:%s:%s", this.getGroup(), this.getArtifact(), this.getVersion());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package co.com.bancolombia.models;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;

public class DependencyReleasesDeserializer extends StdDeserializer<DependencyRelease> {

public DependencyReleasesDeserializer() {
this(null);
}

public DependencyReleasesDeserializer(Class<?> vc) {
super(vc);
}

@Override
public DependencyRelease deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {

JsonNode productNode = jp.getCodec().readTree(jp);
DependencyRelease dependencyRelease = new DependencyRelease();
dependencyRelease.setGroup(productNode.get("response").get("docs").get(0).get("g").textValue());
dependencyRelease.setArtifact(
productNode.get("response").get("docs").get(0).get("a").textValue());
dependencyRelease.setVersion(
productNode.get("response").get("docs").get(0).get("v").textValue());
return dependencyRelease;
}
}
16 changes: 16 additions & 0 deletions src/main/java/co/com/bancolombia/models/Release.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package co.com.bancolombia.models;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.OffsetDateTime;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class Release {
@JsonProperty("tag_name")
private String tagName;

@JsonProperty("published_at")
private OffsetDateTime publishedAt;
}
Loading