-
Notifications
You must be signed in to change notification settings - Fork 503
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
gradle implementation for the Ark plugin #1012
Conversation
WalkthroughThe changes introduce the Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
Outside diff range and nitpick comments (10)
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (4)
12-22
: LGTM: Class declaration and setup method are well-structured.The class declaration and setup method are correctly implemented. The use of
ProjectBuilder
for creating a test Gradle project is appropriate, and the plugin application and extension retrieval are done correctly.Consider adding a comment explaining the purpose of applying "sofa.ark.plugin.gradle.plugin" to the project. This would enhance the readability and maintainability of the test setup.
@Before public void setup() { project = ProjectBuilder.builder().build(); + // Apply the Sofa Ark Gradle plugin to the test project project.getPluginManager().apply("sofa.ark.plugin.gradle.plugin"); extension = project.getExtensions().getByType(ArkPluginExtension.class); }
24-31
: LGTM: Default values are thoroughly tested.The
testDefaultValues
method comprehensively checks all important default values of theArkPluginExtension
. The use ofFile.separator
for the output directory path ensures cross-platform compatibility, which is a good practice.To improve robustness, consider using
assertTrue
withendsWith
for the output directory check instead of relying on the exact path structure. This would make the test less brittle to potential changes in the build directory structure.-assertTrue(extension.getOutputDirectory().get().getAsFile().getPath().endsWith("build" + File.separator + "libs")); +assertTrue(extension.getOutputDirectory().get().getAsFile().getPath().toLowerCase().endsWith(("build" + File.separator + "libs").toLowerCase()));This change makes the test case more flexible and less likely to fail due to minor changes in the build structure or differences in path capitalization across operating systems.
33-47
: LGTM: Setter and getter methods are thoroughly tested.The
testSetAndGetValues
method effectively tests the setter and getter methods for all important properties of theArkPluginExtension
. The test covers priority, pluginName, description, activator, and attach properties, setting new values and verifying them correctly.To ensure complete coverage, consider adding a test for the
outputDirectory
setter method. This would make the test suite more comprehensive.@Test public void testSetAndGetValues() { extension.getPriority().set("200"); extension.getPluginName().set("test-plugin"); extension.getDescription().set("Test description"); extension.getActivator().set("com.example.TestActivator"); extension.getAttach().set(true); + File newOutputDir = new File(project.getBuildDir(), "custom-output"); + extension.getOutputDirectory().set(newOutputDir); assertEquals("200", extension.getPriority().get()); assertEquals("test-plugin", extension.getPluginName().get()); assertEquals("Test description", extension.getDescription().get()); assertEquals("com.example.TestActivator", extension.getActivator().get()); assertTrue(extension.getAttach().get()); + assertEquals(newOutputDir, extension.getOutputDirectory().get().getAsFile()); }This addition would ensure that all settable properties of the
ArkPluginExtension
are thoroughly tested.
1-48
: Overall, excellent test implementation with room for minor enhancements.This test class provides comprehensive coverage of the
ArkPluginExtension
functionality. The use of Gradle'sProjectBuilder
and proper setup ensures realistic testing conditions. The tests cover both default values and setter/getter methods effectively.To further improve the test suite, consider the following suggestions:
- Add edge case tests, such as setting invalid values (e.g., negative priority) to ensure proper error handling.
- Include tests for any custom validation logic that might exist in the
ArkPluginExtension
class.- Consider adding tests for any interactions between different properties, if applicable.
- If there are any methods in
ArkPluginExtension
that perform complex operations, add specific tests for those methods.These additions would make the test suite even more robust and comprehensive, ensuring the
ArkPluginExtension
behaves correctly under various scenarios.sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/BaseConfig.java (1)
24-27
: LGTM: Class and field declarations are well-structured.The abstract class and field declarations are appropriate for a base configuration. The fields are clearly named and initialized to prevent null pointer exceptions.
Consider using
final
for the list fields to prevent accidental reassignment:- private List<String> packages = new ArrayList<>(); - private List<String> classes = new ArrayList<>(); - private List<String> resources = new ArrayList<>(); + private final List<String> packages = new ArrayList<>(); + private final List<String> classes = new ArrayList<>(); + private final List<String> resources = new ArrayList<>();This change would ensure that the list references cannot be changed, while still allowing modifications to the list contents.
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (1)
35-45
: Add JavaDoc comments to abstract methods.While the method names are descriptive, adding JavaDoc comments would greatly improve the usability and maintainability of this class. This is especially important for an extension class that will be used by other developers.
Consider adding JavaDoc comments to each abstract method. For example:
/** * Gets the set of shades for the Ark plugin. * @return A SetProperty containing the shades. */ abstract public SetProperty<String> getShades(); /** * Gets the priority of the Ark plugin. * @return A Property containing the priority as a string. */ abstract public Property<String> getPriority(); // Add similar comments for other abstract methodssofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginCopyAction.java (2)
114-120
: Avoid redundantinputStream.close()
infinally
blockThe
inputStream
is already managed by a try-with-resources statement in the calling method (setupStoredEntry
). Explicitly closing it again in thefinally
block may lead to unnecessary overhead.You can remove the explicit
inputStream.close()
call:CrcAndSize(InputStream inputStream) throws IOException { try { load(inputStream); } - } - finally { - inputStream.close(); } }
35-140
: Consider adding unit tests for the new classArkPluginCopyAction
To ensure the reliability and correctness of the
ArkPluginCopyAction
class, it's important to have comprehensive unit tests that cover various scenarios, including error handling and edge cases.Do you want me to help generate unit tests for this class or open a GitHub issue to track this task?
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginJarTask.java (2)
133-154
: Consolidate duplicate manifest attributesIn the
configureManifest
method, both standard and custom manifest attributes are set with potentially overlapping information. For example:
- Lines 137 and 144:
Ark-Plugin-Name
andpluginName
both store the plugin name.- Lines 138 and 142:
Ark-Plugin-Version
andversion
both store the project version.Consider consolidating these attributes or clearly distinguishing their purposes to avoid redundancy and potential confusion.
92-109
: Enhance error messages inresolveArtifact()
The method
resolveArtifact()
throwsIllegalArgumentException
with generic messages when it encounters issues. Providing more detailed error messages, including which part of the shade string caused the problem or suggestions for the correct format, will help users diagnose and fix issues more efficiently.
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (6)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPlugin.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginCopyAction.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginJarTask.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/BaseConfig.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (1 hunks)
Additional comments not posted (18)
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPlugin.java (5)
1-17
: LGTM: License header and package declaration are correct.The Apache License 2.0 header is properly included, and the package name follows Java naming conventions.
19-20
: LGTM: Import statements are correct and concise.The necessary Gradle API classes are imported without any redundancy.
22-22
: LGTM: Class declaration is correct for a Gradle plugin.The
ArkPlugin
class properly implementsPlugin<Project>
and is declared as public, which is necessary for Gradle to use it.
24-33
: LGTM: Theapply
method is well-implemented.The method correctly creates an extension and registers a task, following Gradle plugin best practices. The task is properly configured with a group and description.
26-31
: Verify the existence ofArkPluginExtension
andArkPluginJarTask
classes.The
apply
method usesArkPluginExtension
andArkPluginJarTask
, but these classes are not imported. Please ensure that these classes exist in the same package or add the necessary import statements.Run the following script to verify the existence of these classes:
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (1)
1-11
: LGTM: Package declaration and imports are appropriate.The package declaration and imports are correct and relevant for the test class. Good job on keeping the imports concise and avoiding unnecessary ones.
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/BaseConfig.java (4)
1-17
: LGTM: License header and package declaration are correct.The Apache License 2.0 header is properly included, and the package declaration follows Java naming conventions.
19-22
: LGTM: Imports are appropriate and concise.The imported classes (ArrayList, HashMap, List, and Map) are all used in the implementation and no unnecessary imports are present.
29-51
: LGTM: Getter and setter methods are correctly implemented.The getter and setter methods for all three fields (packages, classes, and resources) follow Java bean naming conventions and are correctly implemented.
1-61
: Overall assessment: Well-structured base configuration class with room for minor improvements.The
BaseConfig
class provides a solid foundation for managing configuration related to packages, classes, and resources. It follows Java conventions and is generally well-implemented. The suggested improvements, if applied, would enhance the robustness and readability of the code.Key points:
- Good use of abstract class for base configuration.
- Clear and descriptive field names with proper initialization.
- Correct implementation of getter and setter methods.
- The
toAttributes
method effectively converts list data to a map format, though it could be improved for better null handling and readability.These changes align well with the PR objective of implementing Gradle support for the Ark plugin, providing a structured way to manage configuration data.
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (4)
1-24
: LGTM: Package and imports are appropriate.The package declaration and imports are suitable for a Gradle plugin extension. The use of Gradle API classes indicates proper integration with the Gradle ecosystem.
47-64
: Clarify the purpose of ImportedConfig and ExportedConfig.The code structure for handling
ImportedConfig
andExportedConfig
is well-implemented. However, the purpose and usage of these configurations are not immediately clear from the code.Could you provide more context on the intended use of
ImportedConfig
andExportedConfig
? This information would be valuable for maintainers and users of this extension. Consider adding comments or documentation to explain:
- What these configurations represent in the context of the Ark plugin?
- How are they expected to be used by consumers of this extension?
- Are there any specific rules or constraints for these configurations?
Adding this information would greatly improve the usability and maintainability of the extension.
66-73
: Clarify the purpose of empty nested classes.The
ImportedConfig
andExportedConfig
classes are currently empty and extendBaseConfig
. This structure suggests planned functionality, but the current implementation doesn't provide any specific behavior.Please clarify the following:
- What is the purpose of these empty nested classes?
- Is there planned functionality to be added in the future?
- What does the
BaseConfig
class contain, and why is it necessary for these configurations?If these classes are placeholders for future implementation, consider adding TODO comments to indicate the planned functionality. If they're not needed, you might want to remove them to avoid confusion.
1-74
: Overall assessment: Good foundation with room for improvement.The
ArkPluginExtension
class provides a solid foundation for integrating the Ark plugin with Gradle. The structure and use of Gradle APIs are appropriate. However, there are several areas where the implementation could be improved:
- Adding JavaDoc comments to abstract methods would enhance usability and maintainability.
- Clarifying the purpose and usage of
ImportedConfig
andExportedConfig
would provide better context for users and maintainers.- Consider using the
@Inject
annotation for the constructor to better integrate with Gradle's dependency injection system.- The empty nested classes (
ImportedConfig
andExportedConfig
) need clarification on their purpose and planned functionality.Addressing these points will significantly improve the overall quality and usability of this extension. Great work on laying the groundwork for the Ark plugin's Gradle implementation!
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginCopyAction.java (1)
88-89
: Ensure correct Unix file permissions are setThe calculation of
unixMode
combines the original mode with the file or directory flag. Verify that thedetails.getMode()
provides the correct permission bits and that the bitwise OR operation results in the intended permissions.Run the following script to confirm the correctness of Unix modes:
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginJarTask.java (3)
76-83
: Clarify multipleinto("lib")
blocks inconfigureArtifacts()
The
configureArtifacts()
method contains twointo("lib")
blocks:
- Lines 76-79 handle adding artifact files.
- Lines 81-83 handle adding shade files.
While this separation might be intentional, consider combining them or adding comments to explain their distinct purposes. This will enhance code clarity and maintainability.
119-124
: Ensure null safety infindArtifactByFileName()
The method
findArtifactByFileName()
may returnnull
if no matching artifact is found. Ensure that any methods calling this one handle the potentialnull
value appropriately to preventNullPointerException
s.
40-73
: Overall implementation is well-structuredThe constructor of
ArkPluginJarTask
is setting up the task with appropriate configurations, including destination directory, archive file name, source sets, artifact handling, manifest configuration, and adding the Ark plugin marker. The use of Gradle'sProvider
API and lazy configuration is commendable.
public Map<String, String> toAttributes(String prefix) { | ||
Map<String, String> attributes = new HashMap<>(); | ||
attributes.put(prefix + "-packages", packages != null ? String.join(",", packages) : ""); | ||
attributes.put(prefix + "-classes", classes != null ? String.join(",", classes) : ""); | ||
attributes.put(prefix + "-resources", resources != null ? String.join(",", resources) : ""); | ||
return attributes; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Improve robustness and readability of toAttributes
method.
While the current implementation is functional, consider the following improvements:
- Use
Optional
to handle potential null values more elegantly. - Utilize Java streams for a more concise and readable implementation.
Here's a suggested refactoring:
public Map<String, String> toAttributes(String prefix) {
- Map<String, String> attributes = new HashMap<>();
- attributes.put(prefix + "-packages", packages != null ? String.join(",", packages) : "");
- attributes.put(prefix + "-classes", classes != null ? String.join(",", classes) : "");
- attributes.put(prefix + "-resources", resources != null ? String.join(",", resources) : "");
- return attributes;
+ return Map.of(
+ prefix + "-packages", Optional.ofNullable(packages).map(list -> String.join(",", list)).orElse(""),
+ prefix + "-classes", Optional.ofNullable(classes).map(list -> String.join(",", list)).orElse(""),
+ prefix + "-resources", Optional.ofNullable(resources).map(list -> String.join(",", list)).orElse("")
+ );
}
This refactoring:
- Uses
Optional
to handle null values more elegantly. - Uses
Map.of
for a more concise map creation. - Improves readability by using method references and lambda expressions.
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public Map<String, String> toAttributes(String prefix) { | |
Map<String, String> attributes = new HashMap<>(); | |
attributes.put(prefix + "-packages", packages != null ? String.join(",", packages) : ""); | |
attributes.put(prefix + "-classes", classes != null ? String.join(",", classes) : ""); | |
attributes.put(prefix + "-resources", resources != null ? String.join(",", resources) : ""); | |
return attributes; | |
} | |
public Map<String, String> toAttributes(String prefix) { | |
return Map.of( | |
prefix + "-packages", Optional.ofNullable(packages).map(list -> String.join(",", list)).orElse(""), | |
prefix + "-classes", Optional.ofNullable(classes).map(list -> String.join(",", list)).orElse(""), | |
prefix + "-resources", Optional.ofNullable(resources).map(list -> String.join(",", list)).orElse("") | |
); | |
} |
abstract public class ArkPluginExtension { | ||
|
||
public ArkPluginExtension(Project project){ | ||
getPriority().convention(project.provider(() -> "100")); | ||
getOutputDirectory().convention(project.getLayout().getBuildDirectory().dir("libs")); | ||
getPluginName().convention("sofa-ark-plugin-gradle-plugin"); | ||
getDescription().convention("ark plugin"); | ||
getActivator().convention(""); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider using @Inject
annotation for the constructor.
The constructor is well-structured, setting default values for various properties. However, for better integration with Gradle's dependency injection system, consider annotating the constructor with @Inject
.
Apply this change to the constructor:
+import javax.inject.Inject;
abstract public class ArkPluginExtension {
+ @Inject
public ArkPluginExtension(Project project){
// ... (rest of the constructor remains the same)
}
}
This change ensures that Gradle properly manages the lifecycle of this extension and provides the correct Project
instance.
Committable suggestion was skipped due to low confidence.
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) { | ||
zipStream.setEncoding(String.valueOf(StandardCharsets.UTF_8)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper encoding is set without unnecessary conversions
The encoding is set using String.valueOf(StandardCharsets.UTF_8)
, which is unnecessary. You can directly use "UTF-8"
or StandardCharsets.UTF_8.name()
for clarity.
Apply this diff to simplify the encoding setting:
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) {
- zipStream.setEncoding(String.valueOf(StandardCharsets.UTF_8));
+ zipStream.setEncoding(StandardCharsets.UTF_8.name());
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) { | |
zipStream.setEncoding(String.valueOf(StandardCharsets.UTF_8)); | |
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) { | |
zipStream.setEncoding(StandardCharsets.UTF_8.name()); |
String path = details.getRelativePath().getPathString(); | ||
|
||
if (path.startsWith("lib")) { | ||
setupStoredEntry(entry, details); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve path checking for 'lib' directory
Using path.startsWith("lib")
may incorrectly match paths like "library/"
. To ensure only files in the "lib"
directory are processed, check the first segment of the relative path.
Apply this diff to improve the path checking:
String path = details.getRelativePath().getPathString();
-if (path.startsWith("lib")) {
+if (details.getRelativePath().getSegments()[0].equals("lib")) {
setupStoredEntry(entry, details);
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
String path = details.getRelativePath().getPathString(); | |
if (path.startsWith("lib")) { | |
setupStoredEntry(entry, details); | |
} | |
String path = details.getRelativePath().getPathString(); | |
if (details.getRelativePath().getSegments()[0].equals("lib")) { | |
setupStoredEntry(entry, details); | |
} |
} catch (Exception e) { | ||
System.out.println("Warning: Unable to process JAR file in lib directory: " + details.getPath()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a logging framework instead of System.out.println
Directly using System.out.println
for logging is not advisable in production code. It is better to use a logging framework to handle log messages appropriately and consistently.
Apply this diff to replace System.out.println
with a logger:
} catch (Exception e) {
- System.out.println("Warning: Unable to process JAR file in lib directory: " + details.getPath());
+ // Replace with appropriate logging framework
+ logger.warn("Unable to process JAR file in lib directory: {}", details.getPath(), e);
}
Ensure you have a logger instantiated at the beginning of the class:
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class ArkPluginCopyAction implements CopyAction {
+ private static final Logger logger = LoggerFactory.getLogger(ArkPluginCopyAction.class);
Committable suggestion was skipped due to low confidence.
private void configureArtifacts(Project project, Set<ResolvedArtifact> filteredArtifacts){ | ||
from(project.provider(() -> { | ||
return filteredArtifacts.stream() | ||
.map(ResolvedArtifact::getFile) | ||
.collect(Collectors.toSet()); | ||
})); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove or utilize the unused method configureArtifacts(Project, Set<ResolvedArtifact>)
The method configureArtifacts(Project project, Set<ResolvedArtifact> filteredArtifacts)
is defined but never called within the class. Unused methods can lead to confusion and should be removed or implemented if they are intended for future use.
private void configureCopySpec(Project project) { | ||
|
||
from(project.provider(() -> { | ||
Configuration runtimeClasspath = project.getConfigurations().getByName("runtimeClasspath"); | ||
Set<ResolvedArtifact> artifacts = runtimeClasspath.getResolvedConfiguration().getResolvedArtifacts(); | ||
return filterArtifacts(artifacts); | ||
})); | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eliminate the unused method configureCopySpec(Project)
The method configureCopySpec(Project project)
is declared but not invoked anywhere in the codebase. It's advisable to remove unused methods to keep the code clean and avoid potential confusion.
private void collectExcludeRules() { | ||
Project project = getProject(); | ||
Configuration configuration = project.getConfigurations().getByName("compileClasspath"); | ||
excludeRules.addAll(configuration.getExcludeRules()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the unused method collectExcludeRules()
The method collectExcludeRules()
is defined but not used anywhere in the class. Unused methods can clutter the code and should be removed unless they are planned for future implementation.
private void addArkPluginMark() { | ||
String markContent = "this is plugin mark"; | ||
String markPath = "com/alipay/sofa/ark/plugin"; | ||
|
||
from(getProject().provider(() -> { | ||
try { | ||
File tempFile = File.createTempFile("mark", null); | ||
tempFile.deleteOnExit(); | ||
Files.write(tempFile.toPath(), markContent.getBytes(StandardCharsets.UTF_8)); | ||
return tempFile; | ||
} catch (IOException e) { | ||
throw new RuntimeException("Failed to create mark file", e); | ||
} | ||
}), copySpec -> { | ||
copySpec.into(markPath); | ||
copySpec.rename(fileName -> "mark"); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplify the creation of the Ark plugin marker
In the addArkPluginMark()
method, a temporary file is created to add a marker to the JAR file. Instead of writing to a temporary file and then including it, consider adding the marker content directly using an in-memory stream. This would simplify the code and reduce unnecessary I/O operations.
for (ResolvedArtifact artifact : artifacts) { | ||
String artifactId = artifact.getName(); | ||
if (existArtifacts.containsKey(artifactId)) { | ||
conflictArtifacts.add(artifact); | ||
ResolvedArtifact existingArtifact = existArtifacts.get(artifactId); | ||
if (existingArtifact != null) { | ||
conflictArtifacts.add(existingArtifact); | ||
} | ||
} else { | ||
existArtifacts.put(artifactId, artifact); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refine conflict detection in filterConflictArtifacts()
The current implementation considers artifacts conflicting if they share the same artifact ID, regardless of their group ID. This might incorrectly identify artifacts from different groups but with the same name as conflicts. It's recommended to include both group ID and artifact ID in the conflict check to accurately detect true conflicts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (11)
sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (3)
1-6
: LGTM! Consider clarifying the commented-out plugin.The plugin configuration is appropriate for a Gradle plugin project. The 'java' and 'java-gradle-plugin' plugins are correctly applied.
Consider adding a TODO comment or clarifying the intention behind the commented-out 'maven-publish' plugin. This will help other developers understand future plans for the project.
18-20
: LGTM! Consider updating Java compatibility.The project metadata is well-defined with appropriate group and version.
Consider updating the
sourceCompatibility
to a more recent Java version (e.g., Java 11 or higher) if the project requirements allow. This can provide access to newer language features and improved performance.
22-30
: Consider updating and clarifying test dependencies.The repository and implementation dependency configurations look good.
Consider the following suggestions for the test dependencies:
- Update JUnit to the latest version (currently 4.13.2).
- Clarify the testing strategy. The mix of JUnit 4 and JUnit 5 (Vintage) suggests a transition. Consider fully migrating to JUnit 5 if possible, or add a comment explaining the need for both versions.
Example update:
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' // Kept for legacy tests, remove when migration to JUnit 5 is complete testImplementation 'junit:junit:4.13.2' testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.9.2'sofa-ark-parent/support/ark-plugin-gradle-plugin/README.md (8)
1-5
: Improve document structure with proper heading levelsThe document structure can be improved by using proper heading levels. Currently, the main title is an H1, but the subsequent sections use H3. To maintain a consistent and logical structure:
- Keep the main title as H1
- Use H2 for main sections (e.g., "Configuration", "Usage")
- Use H3 for subsections
Here's an example of how to structure the beginning of the document:
# Ark Plugin Gradle打包插件使用 ## 介绍 `sofa-ark-plugin-gradle-plugin`模块是Ark Plugin打包工具的Gradle版本实现,和Maven打包工具`sofa-ark-plugin-maven-plugin`有同样的功能。在后文,使用**Gradle插件**来指代`sofa-ark-plugin-gradle-plugin`。 本小节会对**Gradle插件**进行介绍,随后会展示如何使用**Gradle插件**打包Ark Plugin。 ## 配置项
6-41
: Add language specifications to code blocksTo improve readability and enable syntax highlighting, add language specifications to all code blocks. This will help users understand the code snippets better and make the documentation more professional.
Here's an example of how to add language specifications:
```groovy arkPlugin { //具体配置项 }activator = 'sample.activator.SamplePluginActivator'excludes = ['com.fasterxml.jackson.module:jackson-module-parameter-names', 'org.example:common']exported { packages = [ 'com.alipay.sofa.ark.sample.common' ] classes = [ 'sample.facade.SamplePluginService' ] resource = [ 'META-INF/spring/bean.xml' ] }<details> <summary>:toolbox: Tools</summary> <details> <summary>Markdownlint</summary><blockquote> 6-6: Expected: h2; Actual: h3 Heading levels should only increment by one level at a time (MD001, heading-increment) --- 9-9: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 16-16: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 21-21: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 26-26: null Fenced code blocks should have a language specified (MD040, fenced-code-language) </blockquote></details> </details> --- `44-50`: **Provide more information about remote inclusion** The document mentions two methods of including the plugin: local and remote. However, it only states that remote inclusion is "under application" (正在申请) without providing further details. To improve the documentation: 1. Explain what "under application" means in this context. 2. Provide an estimated timeline for when remote inclusion might be available, if possible. 3. If applicable, add a note about how users can stay updated on the status of remote inclusion. Consider adding a brief explanation like this: ```markdown 2. 远程引入(正在申请) 远程引入方法目前正在申请中,预计将在未来版本中支持。该方法将允许直接从远程仓库引入插件,简化使用流程。请关注我们的官方渠道以获取最新更新。
51-85
: Enhance the local repository publishing sectionThe instructions for publishing the Gradle plugin to a local Maven repository are generally clear, but there are a few areas for improvement:
- Code block language specification: Add language specifications to the code blocks for better readability.
- Hardcoded path: The example uses a hardcoded Windows path (
E:/repo
). Consider using a more generic example or providing alternatives for different operating systems.- Version information: The
version
in the publishing configuration is not specified. It would be helpful to explain how to set or obtain this version.Here's an example of how to improve this section:
#### 将Gradle插件发布到本地仓库 1. 在**Gradle插件**的build.gradle的plugin解开注释,如下所示: ```groovy plugins { id 'java' id 'java-gradle-plugin' // 本地调试用,发布到maven id 'maven-publish' }
- 配置publish
在build.gradle中增加如下内容:publishing { // 配置Plugin GAV publications { maven(MavenPublication) { groupId = project.group artifactId = project.name version = project.version from components.java } } // 配置仓库地址 repositories { maven { url = uri("${System.getProperty('user.home')}/.m2/repository") } } }注意:上面的例子使用了系统的用户目录来设置本地Maven仓库路径。你可以根据需要修改这个路径。
- 发布插件
在IDEA的右侧Gradle面板中,找到 Tasks > publishing > publish,双击执行该任务将插件发布到本地仓库。<details> <summary>:toolbox: Tools</summary> <details> <summary>Markdownlint</summary><blockquote> 53-53: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 65-65: null Fenced code blocks should have a language specified (MD040, fenced-code-language) </blockquote></details> </details> --- `87-120`: **Improve the local project setup instructions** The instructions for setting up a local project to use the published plugin are generally clear, but there are some areas for improvement: 1. Code block language specification: Add language specifications to the code blocks for better readability. 2. Hardcoded path: The example uses a hardcoded Windows path (`E:/repo`). Consider using a more generic example or providing alternatives for different operating systems. 3. Version consistency: Ensure that the version numbers used in the examples are consistent and up-to-date. 4. Explanation of steps: Provide brief explanations for each step to help users understand the purpose of each configuration. Here's an example of how to improve this section: ```markdown #### 在本地项目中引入 1. 在Gradle项目根目录的settings.gradle中设置pluginManagement: ```groovy pluginManagement { repositories { // 指定本地maven仓库 maven { url = uri("${System.getProperty('user.home')}/.m2/repository") } } }
这步骤确保Gradle可以从本地Maven仓库中查找插件。
- 在需要打包的项目中的build.gradle进行如下的配置:
buildscript { repositories { maven { url = uri("${System.getProperty('user.home')}/.m2/repository") } } dependencies { classpath("com.alipay.sofa:sofa-ark-gradle-plugin:${version}") } } plugins { id 'com.alipay.sofa.ark-gradle-plugin' version "${version}" }请将
${version}
替换为你发布到本地仓库的插件版本。这个配置告诉Gradle使用指定版本的sofa-ark-gradle-plugin。
- 刷新Gradle配置
在完成上述配置后,刷新你的Gradle项目。如果配置正确,你应该能在IDEA右侧的Gradle任务列表中看到新的arkPluginJar任务。
<details> <summary>:toolbox: Tools</summary> <details> <summary>Markdownlint</summary><blockquote> 91-91: null Fenced code blocks should have a language specified (MD040, fenced-code-language) --- 104-104: null Fenced code blocks should have a language specified (MD040, fenced-code-language) </blockquote></details> </details> --- `123-150`: **Enhance the configuration example section** The configuration example for the `arkPlugin` block is comprehensive, but there are some areas for improvement: 1. Code block language specification: Add a language specification to the code block for better readability. 2. Explanation of options: Provide brief explanations for each configuration option to help users understand their purpose and usage. 3. Consistency with previous examples: Ensure that the configuration options shown here are consistent with any mentioned earlier in the document. Here's an example of how to improve this section: ```markdown ### 配置示例 在需要打包的项目的build.gradle文件中,添加以下配置: ```groovy arkPlugin { // 指定输出目录 outputDirectory = layout.buildDirectory.dir("custom-output") // 指定插件的Activator类 activator = 'sample.activator.SamplePluginActivator' // 指定要排除的依赖 excludes = ['com.fasterxml.jackson.module:jackson-module-parameter-names'] // 指定要shade的依赖 shades = [ 'org.example:common:1.0' ] // 指定要导出的包、类和资源 exported { packages = [ 'com.alipay.sofa.ark.sample.common' ] classes = [ 'sample.facade.SamplePluginService' ] resources = [ 'META-INF/spring/bean.xml' ] } }
配置说明:
outputDirectory
: 指定Ark Plugin包的输出目录activator
: 指定插件的Activator类的全限定名excludes
: 列出要从最终的Ark Plugin包中排除的依赖shades
: 列出要在Ark Plugin包中进行shading处理的依赖exported
: 指定要从Ark Plugin中导出的包、类和资源确保根据你的项目需求适当调整这些配置项。
<details> <summary>:toolbox: Tools</summary> <details> <summary>Markdownlint</summary><blockquote> 127-127: null Fenced code blocks should have a language specified (MD040, fenced-code-language) </blockquote></details> </details> --- `151-151`: **Expand the instructions for building the Ark Plugin** The current instructions for building the Ark Plugin are brief and might not provide enough guidance for users unfamiliar with Gradle or IDEA. Consider expanding this section to make it more comprehensive and user-friendly. Here's a suggestion for improving this section: ```markdown ### 构建Ark Plugin 完成配置后,按照以下步骤构建Ark Plugin: 1. 刷新Gradle项目: - 在IDEA中,点击工具栏的"Refresh all Gradle projects"按钮,或 - 在项目根目录下运行命令 `./gradlew --refresh-dependencies` 2. 执行arkPluginJar任务: - 在IDEA中: a. 打开右侧的Gradle任务列表 b. 展开 Tasks > build c. 双击 arkPluginJar 任务执行 - 或者,在命令行中运行: ``` ./gradlew arkPluginJar ``` 3. 查找输出: 构建完成后,你可以在之前配置的 `outputDirectory` 中找到生成的Ark Plugin包。默认情况下,它应该位于 `build/custom-output` 目录下。 4. 验证构建结果: 检查生成的 .ark 文件,确保它包含了所有必要的类和资源。 如果在构建过程中遇到任何问题,请检查你的配置并确保所有依赖都正确声明。
This expanded section provides more detailed steps, alternative methods for execution, and guidance on verifying the build result, which should be more helpful for users of all experience levels.
1-151
: Overall assessment and additional suggestionsThe README provides valuable information about using the Ark Plugin Gradle packaging tool. It covers the essential aspects of configuration, local repository publishing, and project setup. However, there are a few additional points to consider for improving the overall quality of the document:
- Add a table of contents at the beginning of the document to improve navigation.
- Include a section on troubleshooting common issues that users might encounter.
- Add examples of how to use the packaged Ark Plugin in a project.
- Consider adding a section on best practices or tips for efficient usage of the plugin.
- Include information about compatibility with different Gradle versions.
- Add links to related documentation or resources for further reading.
To improve the overall structure and completeness of the document, consider reorganizing it as follows:
- Introduction
- Table of Contents
- Installation
3.1 Local Repository Publishing
3.2 Project Setup- Configuration
4.1 Available Options
4.2 Configuration Example- Usage
5.1 Building the Ark Plugin
5.2 Using the Ark Plugin in a Project- Best Practices
- Troubleshooting
- Compatibility
- Further Reading
This structure would provide a more comprehensive guide for users of all experience levels and make it easier to find specific information.
🧰 Tools
Markdownlint
6-6: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time(MD001, heading-increment)
9-9: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
16-16: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
21-21: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
26-26: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
53-53: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
65-65: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
91-91: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
104-104: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
127-127: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/README.md (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (1 hunks)
🧰 Additional context used
Markdownlint
sofa-ark-parent/support/ark-plugin-gradle-plugin/README.md
6-6: Expected: h2; Actual: h3
Heading levels should only increment by one level at a time(MD001, heading-increment)
9-9: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
16-16: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
21-21: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
26-26: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
53-53: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
65-65: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
91-91: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
104-104: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
127-127: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
🔇 Additional comments not posted (2)
sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (2)
32-34
: LGTM! Test configuration is correct.The test task is correctly configured to use the JUnit Platform, which allows running both JUnit 4 (via Vintage) and JUnit 5 tests.
9-16
: LGTM! Verify the implementation class.The gradlePlugin configuration correctly defines the 'DependenciesPlugin' with an appropriate ID.
Please ensure that the implementation class 'com.alipay.sofa.ark.boot.mojo.ArkPlugin' exists and is correctly implemented. Run the following script to verify:
✅ Verification successful
Implementation class 'com.alipay.sofa.ark.boot.mojo.ArkPlugin' exists and is correctly implemented.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the existence of the ArkPlugin class # Test: Search for the ArkPlugin class definition ast-grep --lang java --pattern 'class ArkPlugin { $$$ }'Length of output: 60
Script:
#!/bin/bash # Description: Perform a broader search for the ArkPlugin class using ripgrep # Search for 'ArkPlugin' in all Java files rg 'class\s+ArkPlugin' --type javaLength of output: 1317
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginCopyAction.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginJarTask.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginJarTask.java
🔇 Additional comments (3)
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginCopyAction.java (3)
177-209
: CrcAndSize class implementation looks goodThe
CrcAndSize
class is well-implemented for calculating CRC and size efficiently. It uses a buffer for reading, which is good for performance. ThesetUpStoredEntry
method correctly sets the necessary attributes for a stored (uncompressed) ZIP entry.The implementation is correct and efficient. No changes are needed.
1-211
: Summary of review findingsOverall, the implementation of
ArkPluginCopyAction
and its inner classes is well-structured and functional. However, there are several areas for improvement:
- Simplify the encoding setting in the
execute
method.- Enhance error handling and logging throughout the classes.
- Improve path checking for the 'lib' directory to ensure accuracy.
- Replace
System.out.println
with proper logging.- Refactor the error handling in the
processFile
method for better context and separation of concerns.The
CrcAndSize
class is well-implemented and doesn't require changes.Please address these issues to improve the overall quality and robustness of the code.
50-51
:⚠️ Potential issueSimplify encoding setting
The encoding is set using
String.valueOf(StandardCharsets.UTF_8)
, which is unnecessary. You can directly useStandardCharsets.UTF_8.name()
for clarity.Apply this diff to simplify the encoding setting:
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) { - zipStream.setEncoding(String.valueOf(StandardCharsets.UTF_8)); + zipStream.setEncoding(StandardCharsets.UTF_8.name());Likely invalid or redundant comment.
@Override | ||
public WorkResult execute(CopyActionProcessingStream stream) { | ||
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) { | ||
zipStream.setEncoding(String.valueOf(StandardCharsets.UTF_8)); | ||
StreamAction action = new StreamAction(zipStream, shadeFiles); | ||
stream.process(action); | ||
return WorkResults.didWork(true); | ||
} catch (IOException e) { | ||
throw new RuntimeException("Failed to create JAR file", e); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding error handling and logging
The execute
method wraps the entire operation in a try-catch block, which is good. However, it might be beneficial to add more granular error handling and logging.
Consider adding more detailed error handling and logging:
@Override
public WorkResult execute(CopyActionProcessingStream stream) {
try (ZipArchiveOutputStream zipStream = new ZipArchiveOutputStream(jarFile)) {
zipStream.setEncoding(StandardCharsets.UTF_8.name());
StreamAction action = new StreamAction(zipStream, shadeFiles);
stream.process(action);
return WorkResults.didWork(true);
} catch (IOException e) {
- throw new RuntimeException("Failed to create JAR file", e);
+ logger.error("Failed to create JAR file: {}", jarFile.getAbsolutePath(), e);
+ return WorkResults.didWork(false);
}
}
Also, consider adding a logger at the class level:
private static final Logger logger = LoggerFactory.getLogger(ArkPluginCopyAction.class);
} catch (Exception e) { | ||
System.out.println("please check this jar file"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace System.out.println with proper logging
Using System.out.println
for logging is not recommended in production code. It's better to use a logging framework for consistent and configurable logging.
Replace the System.out.println
with a logger:
} catch (Exception e) {
- System.out.println("please check this jar file");
+ logger.warn("Unable to process JAR file in lib directory: {}", details.getPath(), e);
}
Also, add a logger at the class level:
private static final Logger logger = LoggerFactory.getLogger(StreamAction.class);
if (path.startsWith("lib")) { | ||
try (InputStream inputStream = details.open()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve path checking for 'lib' directory
Using path.startsWith("lib")
may incorrectly match paths like "library/"
. To ensure only files in the "lib"
directory are processed, check the first segment of the relative path.
Apply this diff to improve the path checking:
String path = details.getRelativePath().getPathString();
-if (path.startsWith("lib")) {
+if (details.getRelativePath().getSegments()[0].equals("lib")) {
try (InputStream inputStream = details.open()) {
CrcAndSize crcAndSize = new CrcAndSize(inputStream);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (path.startsWith("lib")) { | |
try (InputStream inputStream = details.open()) { | |
String path = details.getRelativePath().getPathString(); | |
if (details.getRelativePath().getSegments()[0].equals("lib")) { | |
try (InputStream inputStream = details.open()) { |
@Override | ||
public void processFile(FileCopyDetailsInternal details) { | ||
try { | ||
if (details.isDirectory()) { | ||
addDirectory(details); | ||
} else if (shadeFiles.contains(details.getFile())) { | ||
addShadeFileContents(details.getFile()); | ||
} else { | ||
addFile(details); | ||
} | ||
} catch (IOException e) { | ||
throw new RuntimeException("Failed to add file to JAR: " + details.getPath(), e); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve error handling in processFile method
The processFile
method catches IOException
and wraps it in a RuntimeException
. Consider handling different types of exceptions separately and providing more context in the error message.
Refactor the error handling in the processFile
method:
@Override
public void processFile(FileCopyDetailsInternal details) {
try {
if (details.isDirectory()) {
addDirectory(details);
} else if (shadeFiles.contains(details.getFile())) {
addShadeFileContents(details.getFile());
} else {
addFile(details);
}
- } catch (IOException e) {
- throw new RuntimeException("Failed to add file to JAR: " + details.getPath(), e);
+ } catch (IOException e) {
+ logger.error("I/O error while adding file to JAR: {}", details.getPath(), e);
+ throw new RuntimeException("I/O error while adding file to JAR: " + details.getPath(), e);
+ } catch (Exception e) {
+ logger.error("Unexpected error while processing file: {}", details.getPath(), e);
+ throw new RuntimeException("Unexpected error while processing file: " + details.getPath(), e);
}
}
Committable suggestion was skipped due to low confidence.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #1012 +/- ##
============================================
+ Coverage 78.21% 78.36% +0.14%
Complexity 874 874
============================================
Files 171 171
Lines 7052 7052
Branches 1036 1036
============================================
+ Hits 5516 5526 +10
+ Misses 1005 994 -11
- Partials 531 532 +1 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (3)
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (3)
40-47
: LGTM: Comprehensive test for default values.The
testDefaultValues
method effectively checks all important default values of theArkPluginExtension
. The assertions are correct and use appropriate JUnit methods. The use ofendsWith
for the output directory path check ensures cross-platform compatibility.Consider adding a constant for the default priority value "100" to improve maintainability. For example:
private static final String DEFAULT_PRIORITY = "100"; @Test public void testDefaultValues() { assertEquals(DEFAULT_PRIORITY, extension.getPriority().get()); // ... other assertions }
49-62
: LGTM: Thorough test for setting and getting values.The
testSetAndGetValues
method effectively tests setting and retrieving all important values of theArkPluginExtension
. The assertions are correct and use appropriate JUnit methods.Consider adding the following test cases to improve coverage:
- Test setting invalid values (e.g., negative priority) to ensure proper validation.
- Test the behavior of optional properties when not set.
- Add a test for the
getExportPackages
andgetExportClasses
methods, if they exist in theArkPluginExtension
class.Example:
@Test public void testInvalidValues() { extension.getPriority().set("-1"); // Assert that an exception is thrown or the value is not set } @Test public void testOptionalProperties() { // Assuming there's an optional property called 'optionalSetting' assertFalse(extension.getOptionalSetting().isPresent()); extension.getOptionalSetting().set("value"); assertTrue(extension.getOptionalSetting().isPresent()); assertEquals("value", extension.getOptionalSetting().get()); } @Test public void testExportPackagesAndClasses() { extension.getExportPackages().set(Arrays.asList("com.example", "org.test")); extension.getExportClasses().set(Arrays.asList("com.example.Class1", "org.test.Class2")); assertEquals(Arrays.asList("com.example", "org.test"), extension.getExportPackages().get()); assertEquals(Arrays.asList("com.example.Class1", "org.test.Class2"), extension.getExportClasses().get()); }
28-64
: Good test coverage, with room for enhancement.The
ArkPluginExtensionTest
class provides solid basic coverage for theArkPluginExtension
. It effectively tests default values and the setting/getting of important properties.To further improve the test suite, consider the following enhancements:
- Add test cases for any untested methods in
ArkPluginExtension
.- Include edge case scenarios, such as setting extremely large or small values for numeric properties.
- Test the behavior when optional properties are not set.
- If applicable, add tests for any custom validation logic in the
ArkPluginExtension
.- Consider using parameterized tests for testing multiple similar scenarios efficiently.
Example of a parameterized test:
@ParameterizedTest @CsvSource({ "1, low priority", "100, default priority", "1000, high priority" }) public void testPriorityValues(String priority, String description) { extension.getPriority().set(priority); assertEquals(priority, extension.getPriority().get(), description); }These additions would provide more comprehensive coverage and increase confidence in the
ArkPluginExtension
implementation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (1 hunks)
🧰 Additional context used
🔇 Additional comments (1)
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (1)
28-38
: LGTM: Class declaration and setup method are well-structured.The class declaration and setup method follow JUnit best practices. The
@Before
annotation is correctly used, and the Gradle project setup, plugin application, and extension retrieval are implemented properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (6)
sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (1)
35-50
: Enhance publishing configuration for production deployment.
The current publishing configuration only supports local deployment. Consider adding:
- POM customization (description, developers, SCM info)
- Remote repository configuration
- Signing configuration for Gradle Plugin Portal
Example enhancement:
publishing {
publications {
maven(MavenPublication) {
from components.java
pom {
name = 'SOFAArk Gradle Plugin'
description = 'Gradle plugin for SOFAArk'
url = 'https://github.com/sofastack/sofa-ark'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'sofastack'
name = 'SOFAStack'
email = '[email protected]'
}
}
scm {
connection = 'scm:git:git://github.com/sofastack/sofa-ark.git'
developerConnection = 'scm:git:ssh://github.com/sofastack/sofa-ark.git'
url = 'https://github.com/sofastack/sofa-ark'
}
}
}
}
}
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (4)
33-38
: Consider enhancing test setup robustness.
Consider these improvements:
- Add null check for the extension
- Add error handling for plugin application
- Consider adding
@After
cleanup if needed
Here's a suggested enhancement:
@Before
public void setup() {
project = ProjectBuilder.builder().withName("test-project").build();
project.getPluginManager().apply("sofa-ark-plugin-gradle-plugin");
extension = project.getExtensions().getByType(ArkPluginExtension.class);
+ if (extension == null) {
+ throw new IllegalStateException("Failed to initialize ArkPluginExtension");
+ }
}
40-47
: Enhance default values test coverage and maintainability.
Consider these improvements:
- Extract magic values to constants
- Use platform-independent path comparison
- Add assertions for remaining properties (attach, shades, excludes)
Here's a suggested enhancement:
+ private static final String DEFAULT_PRIORITY = "100";
+ private static final String DEFAULT_DESCRIPTION = "";
+ private static final String DEFAULT_ACTIVATOR = "";
+
@Test
public void testDefaultValues() {
- assertEquals("100", extension.getPriority().get());
+ assertEquals(DEFAULT_PRIORITY, extension.getPriority().get());
assertEquals("test-project", extension.getPluginName().get());
- assertEquals("", extension.getDescription().get());
- assertEquals("", extension.getActivator().get());
- assertTrue(extension.getOutputDirectory().get().getAsFile().getPath().endsWith("build" + File.separator + "libs"));
+ assertEquals(DEFAULT_DESCRIPTION, extension.getDescription().get());
+ assertEquals(DEFAULT_ACTIVATOR, extension.getActivator().get());
+ assertEquals(
+ new File(project.getBuildDir(), "libs").getPath(),
+ extension.getOutputDirectory().get().getAsFile().getPath()
+ );
+ assertFalse(extension.getAttach().get());
+ assertTrue(extension.getShades().isEmpty());
+ assertTrue(extension.getExcludeGroupIds().isEmpty());
+ assertTrue(extension.getExcludeArtifactIds().isEmpty());
}
49-62
: Add comprehensive test coverage for all properties.
The current test covers basic properties but misses important scenarios:
- Edge cases (empty strings, null values)
- Collection properties (shades, excludes)
- Invalid inputs validation
Consider adding these test methods:
@Test
public void testCollectionProperties() {
extension.getShades().add("com.example:library:1.0.0");
extension.getExcludeGroupIds().add("com.example");
extension.getExcludeArtifactIds().add("exclude-me");
assertEquals(1, extension.getShades().size());
assertEquals(1, extension.getExcludeGroupIds().size());
assertEquals(1, extension.getExcludeArtifactIds().size());
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidPriority() {
extension.getPriority().set("-1");
}
28-64
: Consider adding documentation and integration tests.
While the unit tests are well-structured, consider these architectural improvements:
- Add class-level JavaDoc explaining the test purpose and coverage
- Consider adding integration tests that verify the plugin's behavior in a real Gradle build
Example class documentation:
/**
* Unit tests for {@link ArkPluginExtension} that verify:
* - Default property values initialization
* - Property setters and getters behavior
* - Configuration of plugin parameters
*
* @see ArkPluginExtension
*/
public class ArkPluginExtensionTest {
// ... existing code ...
}
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (1)
35-46
: Add documentation for configuration properties.
Each property getter should be documented to explain its purpose, expected values, and any constraints.
Example documentation format:
+ /**
+ * Gets the set of artifacts to be shaded into the plugin.
+ * @return SetProperty containing artifact coordinates to shade
+ */
abstract public SetProperty<String> getShades();
+ /**
+ * Gets the plugin priority which determines the loading order.
+ * Higher priority plugins are loaded first.
+ * @return Property containing priority value, defaults to "100"
+ */
abstract public Property<String> getPriority();
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- .gitignore (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (1 hunks)
- sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
- .gitignore
🔇 Additional comments (8)
sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle (4)
1-5
: LGTM! Standard plugin configuration for Gradle plugin development.
The essential plugins are correctly applied for Java-based Gradle plugin development and Maven publishing.
24-27
: LGTM! Standard repository configuration.
The repository configuration correctly includes both local and central Maven repositories.
15-22
: Review implementation class naming convention.
The implementation class name contains 'mojo' which is typically associated with Maven plugins. Consider renaming to follow Gradle plugin conventions.
7-9
: Verify the plugin ID against the Gradle Plugin Portal.
Please ensure that 'sofa-ark-plugin-gradle-plugin' doesn't conflict with existing plugins and follows your organization's naming conventions.
✅ Verification successful
Let me gather more information about this plugin ID usage within the codebase to better understand its context and uniqueness.
Let me check the publishing configuration in the build.gradle file to understand how this plugin ID is being used.
Plugin ID appears to be properly configured and scoped
The plugin ID 'sofa-ark-plugin-gradle-plugin' is appropriately namespaced under the 'com.alipay.sofa' group and is used consistently within the project. While the ID exists in the Gradle Plugin Portal, this appears to be your organization's own plugin since:
- It's part of the SOFA Ark project structure
- Uses the expected group ID 'com.alipay.sofa'
- Has proper implementation classes and configuration
The plugin ID follows the standard naming convention and is correctly scoped to your organization's namespace.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if the plugin ID exists in the Gradle Plugin Portal
# Note: This is a basic check, manual verification is still recommended
curl -s "https://plugins.gradle.org/plugin/sofa-ark-plugin-gradle-plugin" | grep -q "Not found"
if [ $? -eq 0 ]; then
echo "Plugin ID appears to be available"
else
echo "Warning: Plugin ID might already exist"
fi
Length of output: 200
Script:
#!/bin/bash
# Check for any other occurrences or configurations of this plugin ID
rg -l "sofa-ark-plugin-gradle-plugin" --type gradle --type properties
# Check build.gradle files for plugin publishing configurations
fd "build.gradle" --exec grep -l "publishing" {} \;
# Look for any plugin metadata or configuration files
fd "gradle.properties|plugin.properties|META-INF" --type f
Length of output: 282
Script:
#!/bin/bash
# Check the content of the build.gradle file to see publishing configuration
cat ./sofa-ark-parent/support/ark-plugin-gradle-plugin/build.gradle
# Check for any plugin implementation or main class files
fd -e java -e groovy --full-path "ark-plugin-gradle-plugin"
Length of output: 1885
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/test/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtensionTest.java (2)
1-18
: LGTM: License and package declaration are properly structured.
19-26
: LGTM: Imports are well-organized and necessary.
sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/ArkPluginExtension.java (2)
19-24
: Add missing import for dependency injection.
The imports section is missing javax.inject.Inject
which would be needed for proper Gradle dependency injection.
66-72
: Verify empty configuration classes.
Both ImportedConfig
and ExportedConfig
are empty. Please verify if:
- Implementation is missing, or
BaseConfig
provides all necessary functionality
Let's check the BaseConfig implementation:
✅ Verification successful
Let's examine the BaseConfig implementation to understand if it provides all necessary functionality.
Empty configuration classes are correctly implemented
The empty ImportedConfig
and ExportedConfig
classes are intentionally empty as they inherit all necessary functionality from BaseConfig
. The base class provides:
- Management of packages, classes, and resources through lists
- Getters and setters for all properties
- A
toAttributes
method to convert configurations to a map format with prefixes
This is a common pattern in Gradle plugins where specialized config classes inherit from a base implementation. No additional implementation is needed in the child classes.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for BaseConfig implementation
rg -l "class BaseConfig"
Length of output: 135
Script:
#!/bin/bash
# Get the content of BaseConfig.java
cat sofa-ark-parent/support/ark-plugin-gradle-plugin/src/main/java/com/alipay/sofa/ark/boot/mojo/BaseConfig.java
Length of output: 2204
group = 'com.alipay.sofa' | ||
version = '1.0.0' | ||
sourceCompatibility = '1.8' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider upgrading Java compatibility version.
While Java 1.8 is still widely used, consider upgrading to a more recent LTS version (e.g., 11 or 17) for better features and security, if your ecosystem supports it.
-sourceCompatibility = '1.8'
+sourceCompatibility = '11'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
group = 'com.alipay.sofa' | |
version = '1.0.0' | |
sourceCompatibility = '1.8' | |
group = 'com.alipay.sofa' | |
version = '1.0.0' | |
sourceCompatibility = '11' |
tasks.named('test') { | ||
useJUnitPlatform() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider enhancing test configuration.
While the basic JUnit Platform configuration is correct, consider adding:
- Test logging for better visibility
- Test failure handling
- Parallel test execution if applicable
tasks.named('test') {
useJUnitPlatform()
+ testLogging {
+ events "passed", "skipped", "failed"
+ exceptionFormat "full"
+ }
+ maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
tasks.named('test') { | |
useJUnitPlatform() | |
} | |
tasks.named('test') { | |
useJUnitPlatform() | |
testLogging { | |
events "passed", "skipped", "failed" | |
exceptionFormat "full" | |
} | |
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 | |
} |
dependencies { | ||
implementation 'org.apache.commons:commons-compress:1.26.0' | ||
testImplementation 'junit:junit:4.13.1' | ||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider migrating to JUnit 5 for testing.
Since this is a new project, consider using JUnit 5 directly instead of JUnit 4 with the vintage engine.
- testImplementation 'junit:junit:4.13.1'
- testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2")
+ testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
+ testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
dependencies { | |
implementation 'org.apache.commons:commons-compress:1.26.0' | |
testImplementation 'junit:junit:4.13.1' | |
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2") | |
} | |
dependencies { | |
implementation 'org.apache.commons:commons-compress:1.26.0' | |
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' | |
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' | |
} |
abstract public class ArkPluginExtension { | ||
|
||
public ArkPluginExtension(Project project){ | ||
getPriority().convention(project.provider(() -> "100")); | ||
getOutputDirectory().convention(project.getLayout().getBuildDirectory().dir("libs")); | ||
getPluginName().convention(project.getName()); | ||
getDescription().convention(""); | ||
getActivator().convention(""); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance code maintainability with constants and documentation.
Consider the following improvements:
- Extract magic numbers/strings into constants
- Add class and constructor documentation
Apply these changes:
abstract public class ArkPluginExtension {
+ private static final String DEFAULT_PRIORITY = "100";
+ private static final String DEFAULT_EMPTY = "";
+
+ /**
+ * Extension for configuring Ark Plugin properties in Gradle builds.
+ */
public ArkPluginExtension(Project project){
- getPriority().convention(project.provider(() -> "100"));
+ getPriority().convention(project.provider(() -> DEFAULT_PRIORITY));
getOutputDirectory().convention(project.getLayout().getBuildDirectory().dir("libs"));
getPluginName().convention(project.getName());
- getDescription().convention("");
- getActivator().convention("");
+ getDescription().convention(DEFAULT_EMPTY);
+ getActivator().convention(DEFAULT_EMPTY);
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
abstract public class ArkPluginExtension { | |
public ArkPluginExtension(Project project){ | |
getPriority().convention(project.provider(() -> "100")); | |
getOutputDirectory().convention(project.getLayout().getBuildDirectory().dir("libs")); | |
getPluginName().convention(project.getName()); | |
getDescription().convention(""); | |
getActivator().convention(""); | |
} | |
abstract public class ArkPluginExtension { | |
private static final String DEFAULT_PRIORITY = "100"; | |
private static final String DEFAULT_EMPTY = ""; | |
/** | |
* Extension for configuring Ark Plugin properties in Gradle builds. | |
*/ | |
public ArkPluginExtension(Project project){ | |
getPriority().convention(project.provider(() -> DEFAULT_PRIORITY)); | |
getOutputDirectory().convention(project.getLayout().getBuildDirectory().dir("libs")); | |
getPluginName().convention(project.getName()); | |
getDescription().convention(DEFAULT_EMPTY); | |
getActivator().convention(DEFAULT_EMPTY); | |
} |
* gradle implementation for the Ark plugin --------- Co-authored-by: pmupkin <[email protected]> Co-authored-by: gaosaroma <[email protected]> (cherry picked from commit 0a41e92)
* add check for auto slim config in sofa-ark-maven-plugin (#1009) (cherry picked from commit 74f7ede) * support blank in properties for slim config @lvjing2 (#1010) * add check for auto slim config in sofa-ark-maven-plugin * support blank in properties for slim config (cherry picked from commit 88fb8e2) * enable handle AfterBizStopEvent (cherry picked from commit f957314) * add clean up event handlers (cherry picked from commit 3b8c05e) * fix test (cherry picked from commit 5d66962) * simply unregister event handlers (#1014) (cherry picked from commit 6eef785) * enable not clean biz instance when stop biz failed (#1013) * simply unregister event handlers * try to fix stop failed * not remove biz install when biz stop failed * add test * rebase master (cherry picked from commit a7bc1ca) * add commit for biz state (#1015) * add comments for UNRESOLVED * add commit for biz state (cherry picked from commit 9ce12e6) * feat: support multiple version module as activated (#1018) * feat: support multiple version module as activated (cherry picked from commit 7c40ec7) * feat:baseDependencyParentIdentity_without_version (#1019) (cherry picked from commit f3b88fc) * gradle implementation for the Ark plugin (#1012) * gradle implementation for the Ark plugin --------- Co-authored-by: pmupkin <[email protected]> Co-authored-by: gaosaroma <[email protected]> (cherry picked from commit 0a41e92) * feat: initial implementation of gradle plugin #73 (#1005) * feat: initial implementation of ark gradle plugin (cherry picked from commit 30663b3) * init log space before log reinit (#1020) (cherry picked from commit 53fa805) * feat: 模块瘦身检查 && 允许不自动排除和基座相同的依赖 (#1017) * 优化显示 * fix as bizStateRecords * 更新显示 * feat: add 'build failed when exclude different base dependency'; allow not to exclude same dependency by base-starter automatically * build failed when exclude dependencies not in base * rm all gradle * fix merge * fix ut --------- Co-authored-by: leo james <[email protected]> (cherry picked from commit a99756a) --------- Co-authored-by: Lipeng <[email protected]> Co-authored-by: pmupkin <[email protected]>
Relate issue #73
This PR provides the implementation for packaging the Ark plugin in a Gradle environment.
Summary by CodeRabbit
New Features
ArkPluginCopyAction
for streamlined JAR file creation from processing streams.ArkPluginExtension
class for configuring Gradle plugins with various properties.Tests
ArkPluginExtensionTest
to validate the functionality and properties of theArkPluginExtension
class.Chores
.gitignore
to exclude Gradle-related files and directories.build.gradle
for project configuration and dependency management.