Skip to content

Commit a58d23f

Browse files
committed
Add custom exception for user errors in contribute task
1 parent 4ea3f77 commit a58d23f

File tree

4 files changed

+82
-59
lines changed

4 files changed

+82
-59
lines changed

tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/ContributionTask.java

Lines changed: 52 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
77
import com.fasterxml.jackson.databind.ObjectMapper;
88
import com.fasterxml.jackson.databind.SerializationFeature;
9+
import org.graalvm.internal.tck.exceptions.ContributingException;
910
import org.graalvm.internal.tck.model.MetadataIndexEntry;
1011
import org.graalvm.internal.tck.model.contributing.Question;
1112
import org.graalvm.internal.tck.utils.ConfigurationStringBuilder;
@@ -25,9 +26,18 @@
2526
import java.nio.file.Files;
2627
import java.nio.file.Path;
2728
import java.nio.file.StandardOpenOption;
28-
import java.util.*;
29+
import java.util.ArrayList;
30+
import java.util.Arrays;
31+
import java.util.Comparator;
32+
import java.util.HashMap;
33+
import java.util.HashSet;
34+
import java.util.List;
35+
import java.util.Map;
36+
import java.util.Optional;
37+
import java.util.Set;
2938

3039
public abstract class ContributionTask extends DefaultTask {
40+
private static final String BRANCH_NAME_PREFIX = "add-support-for-";
3141
private static final String METADATA_INDEX = "metadata/index.json";
3242
private static final String BUILD_FILE = "build.gradle";
3343
private static final String USER_CODE_FILTER_FILE = "user-code-filter.json";
@@ -52,16 +62,16 @@ private record ContributingQuestion(String question, String help) {}
5262
private final Map<String, ContributingQuestion> questions = new HashMap<>();
5363

5464
private void initializeWorkingDirectories(){
55-
testsDirectory = Path.of(getProject().file(CoordinateUtils.replace("tests/src/$group$/$artifact$/$version$", coordinates)).getAbsolutePath());
56-
metadataDirectory = Path.of(getProject().file(CoordinateUtils.replace("metadata/$group$/$artifact$/$version$", coordinates)).getAbsolutePath());
57-
this.gradlew = Path.of(getProject().file("gradlew").getAbsolutePath());
65+
testsDirectory = getProject().file(CoordinateUtils.replace("tests/src/$group$/$artifact$/$version$", coordinates)).toPath();
66+
metadataDirectory = getProject().file(CoordinateUtils.replace("metadata/$group$/$artifact$/$version$", coordinates)).toPath();
67+
gradlew = Path.of(getProject().file("gradlew").getAbsolutePath());
5868
}
5969

6070
private void loadQuestions() throws IOException {
6171
File questionsJson = getProject().file("tests/tck-build-logic/src/main/resources/contributing/questions.json");
6272
List<Question> contributingQuestions = objectMapper.readValue(questionsJson, new TypeReference<>() {});
6373
for (var question : contributingQuestions) {
64-
this.questions.put(question.questionKey(), new ContributingQuestion(question.question(), question.help()));
74+
questions.put(question.questionKey(), new ContributingQuestion(question.question(), question.help()));
6575
}
6676
}
6777

@@ -72,7 +82,7 @@ void run() throws IOException {
7282

7383
loadQuestions();
7484

75-
this.coordinates = getCoordinates();
85+
coordinates = getCoordinates();
7686
InteractiveTaskUtils.closeSection();
7787

7888
Path coordinatesMetadataRoot = getProject().file(CoordinateUtils.replace("metadata/$group$/$artifact$", coordinates)).toPath();
@@ -98,7 +108,7 @@ void run() throws IOException {
98108
createStubs(isExistingLibrary);
99109
updateAllowedPackages(packages, isExistingLibrary);
100110

101-
// generate necessary infrastructure
111+
// generate necessary boilerplate code
102112
addTests(testsLocation);
103113
addResources(resourcesLocation);
104114
addDockerImages(dockerImages);
@@ -112,11 +122,11 @@ void run() throws IOException {
112122
// create a PR
113123
boolean shouldCreatePR = shouldCreatePullRequest();
114124
if (shouldCreatePR) {
115-
String branch = "add-support-for-" + coordinates.toString().replace(':', '-');
125+
String branch = BRANCH_NAME_PREFIX + coordinates.toString().replace(':', '-');
116126
createPullRequest(branch);
117127

118128
InteractiveTaskUtils.printUserInfo("After your pull requests gets generated, please update the pull request description to mention all places where your pull request" +
119-
"accesses files, network, docker, or any other external service, and check if all checks in the description are correctly marked");
129+
"accesses files, network, docker, or any other external service, and check if all checks in the description are correctly marked.");
120130
}
121131

122132
InteractiveTaskUtils.printSuccessfulStatement("Contribution successfully completed! Thank you!");
@@ -125,15 +135,11 @@ void run() throws IOException {
125135
private Coordinates getCoordinates() {
126136
ContributingQuestion question = questions.get("coordinates");
127137
return InteractiveTaskUtils.askQuestion(question.question(), question.help(), (answer) -> {
128-
String[] coordinatesParts = answer.split(":");
129-
if (coordinatesParts.length != 3) {
130-
throw new IllegalStateException("Maven coordinates not provided in the correct format. Type help for explanation.");
138+
try {
139+
return CoordinateUtils.fromString(answer);
140+
} catch (IllegalArgumentException ex) {
141+
throw new ContributingException(ex.getMessage());
131142
}
132-
133-
String group = coordinatesParts[0];
134-
String artifact = coordinatesParts[1];
135-
String version = coordinatesParts[2];
136-
return new Coordinates(group, artifact, version);
137143
});
138144
}
139145

@@ -142,11 +148,11 @@ private Path getTestsLocation() {
142148
return InteractiveTaskUtils.askQuestion(question.question(), question.help(), (answer) -> {
143149
Path testsLocation = Path.of(answer).toAbsolutePath();
144150
if (!Files.exists(testsLocation)) {
145-
throw new IllegalStateException("Cannot find tests directory on the given location: " + testsLocation + ". Type help for explanation.");
151+
throw new ContributingException("Cannot find tests directory on the given location: " + testsLocation + ". Type help for explanation.");
146152
}
147153

148154
if (!Files.isDirectory(testsLocation)) {
149-
throw new IllegalStateException("Provided path does not represent a directory: " + testsLocation + ". Type help for explanation.");
155+
throw new ContributingException("Provided path does not represent a directory: " + testsLocation + ". Type help for explanation.");
150156
}
151157

152158
checkPackages(testsLocation);
@@ -155,32 +161,32 @@ private Path getTestsLocation() {
155161
});
156162
}
157163

158-
private void checkPackages(Path testsPath) {
164+
private void checkPackages(Path testsPath) throws ContributingException {
159165
List<Path> javaFiles = new ArrayList<>();
160166
try {
161167
FilesUtils.findJavaFiles(testsPath, javaFiles);
162168
} catch (IOException e) {
163-
throw new RuntimeException("Cannot find java files. Reason: " + e);
169+
throw new ContributingException("Cannot find java files. Reason: " + e);
164170
}
165171

166-
javaFiles.forEach(file -> {
172+
for (Path file : javaFiles) {
167173
try {
168174
Optional<String> packageLine = Files.readAllLines(file).stream().filter(line -> line.contains("package ")).findFirst();
169175
if (packageLine.isEmpty()) {
170-
throw new RuntimeException("Java file: " + file + " does not contain declared package");
176+
throw new ContributingException("Java file: " + file + " does not contain declared package");
171177
}
172178

173179
String declaredPackage = packageLine.get().split(" ")[1].replace(";", "");
174180
String packagePath = declaredPackage.replace(".", File.separator);
175181
if (!Files.exists(testsPath.resolve(packagePath))) {
176-
throw new IllegalStateException("File: " + file + " has package: " + declaredPackage +
182+
throw new ContributingException("File: " + file + " has package: " + declaredPackage +
177183
" that cannot be found on tests location: " + testsPath +
178184
". Please make sure that the location you provided is a directory that contains packages with tests implementations");
179185
}
180186
} catch (IOException e) {
181-
throw new RuntimeException(e);
187+
throw new ContributingException(e.getMessage());
182188
}
183-
});
189+
}
184190
}
185191

186192
private Path getResourcesLocation(){
@@ -192,11 +198,11 @@ private Path getResourcesLocation(){
192198

193199
Path resourcesLocation = Path.of(answer).toAbsolutePath();
194200
if (!Files.exists(resourcesLocation)) {
195-
throw new IllegalStateException("Cannot find resources directory on the given location: " + resourcesLocation + ". Type help for explanation.");
201+
throw new ContributingException("Cannot find resources directory on the given location: " + resourcesLocation + ". Type help for explanation.");
196202
}
197203

198204
if (!Files.isDirectory(resourcesLocation)) {
199-
throw new IllegalStateException("Provided path does not represent a directory: " + resourcesLocation + ". Type help for explanation.");
205+
throw new ContributingException("Provided path does not represent a directory: " + resourcesLocation + ". Type help for explanation.");
200206
}
201207

202208
return resourcesLocation;
@@ -210,7 +216,7 @@ private List<String> getDockerImages() {
210216
while (true) {
211217
String nextImage = InteractiveTaskUtils.askQuestion(question.question(), question.help(), answer -> {
212218
if (!answer.equalsIgnoreCase("-") && answer.split(":").length != 2) {
213-
throw new IllegalStateException("Docker image name not provided in the correct format. Type help for explanation.");
219+
throw new ContributingException("Docker image name not provided in the correct format. Type help for explanation.");
214220
}
215221

216222
return answer;
@@ -255,15 +261,11 @@ private List<Coordinates> getAdditionalDependencies() {
255261
return null;
256262
}
257263

258-
String[] coordinatesParts = answer.split(":");
259-
if (coordinatesParts.length != 3) {
260-
throw new IllegalStateException("Maven coordinates not provided in the correct format. Type help for explanation.");
264+
try {
265+
return CoordinateUtils.fromString(answer);
266+
} catch (IllegalArgumentException ex) {
267+
throw new ContributingException(ex.getMessage());
261268
}
262-
263-
String group = coordinatesParts[0];
264-
String artifact = coordinatesParts[1];
265-
String version = coordinatesParts[2];
266-
return new Coordinates(group, artifact, version);
267269
});
268270

269271
if (dependency == null) {
@@ -378,7 +380,7 @@ private void addUserCodeFilterFile(List<String> packages) throws IOException {
378380
objectMapper.writer(prettyPrinter).writeValue(testsDirectory.resolve(USER_CODE_FILTER_FILE).toFile(), Map.of("rules", filterFileRules));
379381
}
380382

381-
private void addAdditionalDependencies(List<Coordinates> dependencies) {
383+
private void addAdditionalDependencies(List<Coordinates> dependencies) throws IOException {
382384
if (dependencies == null) {
383385
return;
384386
}
@@ -390,27 +392,23 @@ private void addAdditionalDependencies(List<Coordinates> dependencies) {
390392
throw new RuntimeException("Cannot add additional dependencies to " + buildFilePath + ". Please check if a " + BUILD_FILE + " exists on that location.");
391393
}
392394

393-
try {
394-
ConfigurationStringBuilder sb = new ConfigurationStringBuilder();
395-
List<String> content = Files.readAllLines(buildFilePath);
396-
for (var line : content) {
397-
sb.append(line).newLine();
398-
if (line.trim().equalsIgnoreCase("dependencies {")) {
399-
sb.indent();
400-
for (var dependency : dependencies) {
401-
sb.append("testImplementation").space().quote(dependency.toString()).newLine();
402-
}
403-
sb.unindent();
395+
ConfigurationStringBuilder sb = new ConfigurationStringBuilder();
396+
List<String> content = Files.readAllLines(buildFilePath);
397+
for (var line : content) {
398+
sb.append(line).newLine();
399+
if (line.trim().equalsIgnoreCase("dependencies {")) {
400+
sb.indent();
401+
for (var dependency : dependencies) {
402+
sb.append("testImplementation").space().quote(dependency.toString()).newLine();
404403
}
404+
sb.unindent();
405405
}
406-
407-
writeToFile(buildFilePath, sb.toString(), StandardOpenOption.WRITE);
408-
} catch (IOException e) {
409-
throw new RuntimeException(e);
410406
}
407+
408+
writeToFile(buildFilePath, sb.toString(), StandardOpenOption.WRITE);
411409
}
412410

413-
private void addAgentConfigBlock() {
411+
private void addAgentConfigBlock() throws IOException {
414412
Path buildFilePath = testsDirectory.resolve(BUILD_FILE);
415413
InteractiveTaskUtils.printUserInfo("Configuring agent block in: " + BUILD_FILE);
416414

@@ -425,8 +423,6 @@ private void addAgentConfigBlock() {
425423

426424
String content = System.lineSeparator() + (new String(stream.readAllBytes(), StandardCharsets.UTF_8));
427425
writeToFile(buildFilePath, content, StandardOpenOption.APPEND);
428-
} catch (IOException e) {
429-
throw new RuntimeException("Cannot add agent block into: " + buildFilePath);
430426
}
431427
}
432428

tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/CoordinateUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.graalvm.internal.tck;
22

3+
34
public abstract class CoordinateUtils {
45
public static String replace(String template, Coordinates coordinates) {
56
return template
@@ -11,4 +12,16 @@ public static String replace(String template, Coordinates coordinates) {
1112
.replace("$version$", coordinates.version());
1213
}
1314

15+
public static Coordinates fromString(String coordinates) {
16+
String[] coordinatesParts = coordinates.split(":");
17+
if (coordinatesParts.length != 3) {
18+
throw new IllegalArgumentException("Maven coordinates not provided in the correct format.");
19+
}
20+
21+
String group = coordinatesParts[0];
22+
String artifact = coordinatesParts[1];
23+
String version = coordinatesParts[2];
24+
return new Coordinates(group, artifact, version);
25+
}
26+
1427
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.graalvm.internal.tck.exceptions;
2+
3+
public class ContributingException extends Exception{
4+
public ContributingException(String msg) {
5+
super(msg);
6+
}
7+
}

tests/tck-build-logic/src/main/java/org/graalvm/internal/tck/utils/InteractiveTaskUtils.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package org.graalvm.internal.tck.utils;
22

3+
import org.graalvm.internal.tck.exceptions.ContributingException;
4+
35
import java.util.Scanner;
4-
import java.util.function.Function;
56

67
public class InteractiveTaskUtils {
7-
public static <R> R askQuestion(String question, String helpMessage, Function<String, R> handleAnswer) {
8+
9+
@FunctionalInterface
10+
public interface ContributingHandler<V, R> {
11+
R apply(V v) throws ContributingException;
12+
}
13+
14+
public static <R> R askQuestion(String question, String helpMessage, ContributingHandler<String, R> handleAnswer) {
815
Scanner scanner = new Scanner(System.in);
916

1017
while (true) {
@@ -18,7 +25,7 @@ public static <R> R askQuestion(String question, String helpMessage, Function<St
1825

1926
try {
2027
return handleAnswer.apply(answer);
21-
} catch (IllegalStateException ex) {
28+
} catch (ContributingException ex) {
2229
printErrorMessage(ex.getMessage());
2330
}
2431
}

0 commit comments

Comments
 (0)