Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

<feat> add versionRange for adaptor; support to customize adapter-mapping; support to install a few adapter #211

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

gaosaroma
Copy link
Contributor

@gaosaroma gaosaroma commented Nov 21, 2024

  1. 优化 adapter-maping.xml 的配置为范围匹配

在 adapter-mapping.xml 的配置中,支持直接配置依赖的版本范围,如:

  - matcher:
      groupId: org.springframework.boot
      artifactId: spring-boot
      versionRange: "[2.5.1,2.7.14]"
    adapter:
      artifactId: koupleless-adapter-spring-boot-logback-2.7.14

其中,版本范围遵循数学写法,比如:

  • [1.0,2.0) 表示从 1.0(包含)到 2.0(不包含)的版本。
  • [1.0,2.0] 表示从 1.0(包含)到 2.0(包含)的版本。
  • (,1.0] 表示小于或等于 1.0 的版本。
  • [2.0,) 表示大于或等于 2.0 的版本。
  1. 支持用户自定义配置 adapter-mapping

配置方式:在基座的 conf/ark/adapter-mapping.yaml 中配置

  1. 支持从远方包 koupleless-adapter-configs 中拉取最新的 adapter-mapping 配置

  2. 如果拉取不到,支持使用插件的默认配置 adapter-mapping 配置

  3. 根据 adapter-mapping 中配置的版本,支持安装部分 adapter 到远方包

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new configuration files for adapter mappings, enhancing dependency management.
    • Added new methods for version parsing and artifact matching in the build plugin.
    • Implemented a new interface for adapter configuration to improve artifact management.
  • Bug Fixes

    • Improved error handling in dependency resolution processes.
  • Tests

    • Added comprehensive unit tests for new and existing functionalities to ensure reliability.
  • Chores

    • Updated GitHub Actions workflows for improved module release processes and security handling.

Copy link
Contributor

coderabbitai bot commented Nov 21, 2024

Walkthrough

The changes in this pull request primarily involve updates to dependency management within the Koupleless build plugin. Key modifications include adding and replacing dependencies in the pom.xml file, refactoring the KouplelessBaseBuildPrePackageMojo class for improved configuration handling, and introducing new classes and interfaces for better artifact management. Additionally, several YAML configuration files have been added or modified to enhance dependency matching capabilities. Unit tests have also been added to ensure the functionality of the new and updated components.

Changes

File Change Summary
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml Added dependency for maven-resolver-util and replaced jackson-dataformat-yaml with snakeyaml.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java Refactored to use CompositeKouplelessAdapterConfig, made several fields public, added new parameters, and improved error handling.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java Restructured class, removed annotations, added new fields and methods for version range handling.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java Introduced a new test class for MatcherUtils, initializing configurations from a YAML file.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml Updated adapter mappings to use specific groupId, artifactId, and versionRange pairs.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java Modified test class structure, removed @InjectMocks, and adjusted test methods for direct instantiation.
.github/workflows/koupleless_runtime_release.yml Updated workflow for JDK 8 with new steps for finding Maven modules and determining JDK versions.
.github/workflows/koupleless_runtime_release_2.1.x.yml Commented out build_and_test job and enhanced release_for_jdk17 job with new filtering logic for Maven modules.
.github/workflows/koupleless_runtime_snapshot.yml Introduced release_for_jdk8 job, focusing on the release process for JDK 8 with improved module handling.
.github/workflows/koupleless_runtime_snapshot_2.1.x.yml Added release_for_jdk17 job with enhanced logic for managing Maven modules and their versions.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/AdapterConfig.java Added new interface AdapterConfig with methods for artifact mapping and common dependencies.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java Introduced class implementing AdapterConfig, managing multiple configurations and dependency retrieval.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java Updated to implement AdapterConfig, added new matching logic and methods for dependency handling.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java Added methods for parsing version and version ranges.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml New YAML configuration file defining version and adapter mappings for various components.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfigTest.java New test class for CompositeKouplelessAdapterConfig, validating initialization and matching logic.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfigTest.java New test class for KouplelessAdapterConfig, verifying matching logic against artifacts.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/utils/ReflectionUtils.java Added method getField for retrieving field values via reflection.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/mockBaseDir/conf/ark/adapter-mapping.yaml New YAML configuration file specifying versioning and adapter mappings for the build plugin.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java Class removed, which was responsible for testing artifact mapping based on a YAML configuration file.
koupleless-ext/koupleless-build-plugin/pom.xml Added dependency for org.yaml:snakeyaml:2.3 in the <dependencyManagement> section.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfigTest.java New test class added for CompositeKouplelessAdapterConfig, validating various functionalities.
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfigTest.java New test class added for KouplelessAdapterConfig, validating matching logic against artifacts.

Possibly related PRs

Suggested reviewers

  • lvjing2: Suggested reviewer for the pull request.

🐰 In the meadow, hops a change,
Dependencies shift, and configurations rearrange.
New mappings and tests, oh what a delight,
With YAML and Java, our future is bright!
Let’s build and adapt, as we dance through the code,
A hop and a skip on this development road! 🌼✨


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (10)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (4)

55-58: Consider using version range for RocketMQ.

The current matcher is very specific to version 4.4.0. Consider using a version range (e.g., 4\\.4\\..*) if the adapter is compatible with patch versions.


59-66: Consider using version ranges for Spring AOP.

The current matchers use exact versions (5.3.27 and 6.0.8/6.0.9). Consider using version ranges if the adapters are compatible with minor/patch versions to reduce maintenance overhead.


67-72: Add newline at end of file.

The version range usage is good, but the file is missing a newline at the end.

   adapter:
     artifactId: koupleless-adapter-spring-boot-logback-2.7.14
+
🧰 Tools
🪛 yamllint

[error] 72-72: no new line character at the end of file

(new-line-at-end-of-file)


1-72: Consider standardizing version matching approach.

The file uses two different approaches for version matching:

  1. Regular expressions (regexp)
  2. Version ranges (versionRange)

Consider standardizing on versionRange where possible, as it's more maintainable and less error-prone than regular expressions. This would make the configuration more consistent and easier to maintain.

🧰 Tools
🪛 yamllint

[error] 72-72: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml (1)

20-24: Consider adding explicit scope

For better clarity and dependency management, consider adding an explicit scope to the dependency.

 <dependency>
     <groupId>org.apache.maven.resolver</groupId>
     <artifactId>maven-resolver-util</artifactId>
     <version>1.9.18</version>
+    <scope>compile</scope>
 </dependency>
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (2)

86-95: Add input validation and null checks to getMatcherAdaptor

The method should validate inputs and handle edge cases gracefully.

Apply this diff:

 private List<Dependency> getMatcherAdaptor(Artifact artifact) throws InvalidVersionSpecificationException {
+    if (artifact == null) {
+        return Collections.emptyList();
+    }
     List<Dependency> adapterDependencies = new ArrayList<>();
     for (MavenDependencyAdapterMapping adapterMapping : adapterMappings) {
+        if (adapterMapping == null || adapterMapping.getMatcher() == null) {
+            continue;
+        }
         MavenDependencyMatcher matcher = adapterMapping.getMatcher();
         if (mojo.matches(matcher, artifact)) {
             adapterDependencies.add(adapterMapping.getAdapter());
         }
     }
     return adapterDependencies;
 }

97-103: Enhance mockArtifact for better test coverage

Consider enhancing the mock creation to support more Artifact properties and validate inputs.

Apply this diff:

 private Artifact mockArtifact(String groupId, String artifactId, String version) {
+    Objects.requireNonNull(groupId, "groupId must not be null");
+    Objects.requireNonNull(artifactId, "artifactId must not be null");
+    Objects.requireNonNull(version, "version must not be null");
+
     Artifact artifact = Mockito.mock(Artifact.class);
     Mockito.when(artifact.getGroupId()).thenReturn(groupId);
     Mockito.when(artifact.getArtifactId()).thenReturn(artifactId);
     Mockito.when(artifact.getVersion()).thenReturn(version);
+    // Add more properties that might be needed for testing
+    Mockito.when(artifact.getScope()).thenReturn("compile");
+    Mockito.when(artifact.getType()).thenReturn("jar");
     return artifact;
 }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (2)

83-106: Consider making fields final where appropriate

The fields appear well-organized, but several of them could benefit from being marked as final since they are initialized only once and never modified:

  • MAPPING_FILE
  • yamlMapper
  • adapterCopyService
  • versionScheme
-    String                       MAPPING_FILE       = "adapter-mapping.yaml";
+    private static final String  MAPPING_FILE       = "adapter-mapping.yaml";

-    private ObjectMapper         yamlMapper         = new ObjectMapper(new YAMLFactory());
+    private final ObjectMapper   yamlMapper         = new ObjectMapper(new YAMLFactory());

-    AdapterCopyService           adapterCopyService = new AdapterCopyService();
+    private final AdapterCopyService adapterCopyService = new AdapterCopyService();

-    private GenericVersionScheme versionScheme      = new GenericVersionScheme();
+    private final GenericVersionScheme versionScheme = new GenericVersionScheme();

182-191: Consider caching compiled patterns for better performance

The Pattern.compile() operation is relatively expensive and is being called for each artifact match. Consider caching the compiled pattern in the matcher.

     private boolean regexpMatches(MavenDependencyMatcher matcher,
                                   org.apache.maven.artifact.Artifact artifact) {
         if (null == matcher || null == matcher.getRegexp()) {
             return false;
         }

-        String regexp = matcher.getRegexp();
         String dependencyId = getArtifactFullId(artifact);
-        return Pattern.compile(regexp).matcher(dependencyId).matches();
+        return matcher.getCompiledPattern().matcher(dependencyId).matches();
     }

This would require adding a new field to MavenDependencyMatcher:

private Pattern compiledPattern;

public Pattern getCompiledPattern() {
    if (compiledPattern == null && regexp != null) {
        compiledPattern = Pattern.compile(regexp);
    }
    return compiledPattern;
}
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (1)

44-46: Ensure consistent language usage in code comments

The comments for groupId, artifactId, and versionRange fields are in Chinese, while other comments are in English. For consistency and to enhance accessibility for all contributors, consider translating these comments into English.

Also applies to: 51-53, 58-64

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7870126 and 12d539b.

📒 Files selected for processing (5)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (3 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (1)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1)
Learnt from: gaosaroma
PR: koupleless/runtime#120
File: koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml:55-58
Timestamp: 2024-11-12T05:52:21.084Z
Learning: When suggesting changes to a regular expression for version matching, ensure to follow the user's specific request if they prefer a more precise match.
🪛 yamllint
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml

[error] 72-72: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (8)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (4)

1-2: LGTM! Clean YAML structure.


7-22: LGTM! Comprehensive Dubbo version coverage.

The mappings handle different Dubbo versions and group IDs correctly, with clear version boundaries.


43-54: LGTM! Well-structured Logback mappings.

The matchers are correctly ordered from specific to general patterns.


3-6: Consider adding version constraints for apollo-client.

The current regex matches any version of apollo-client. If different versions require different adapters, consider adding version constraints to prevent potential compatibility issues.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1)

45-45: Verify test configuration file existence

The test depends on adapter-mapping-test.yaml in the test resources.

✅ Verification successful

Test configuration file verified successfully

The adapter-mapping-test.yaml file exists at the correct location in the test resources directory and contains valid YAML syntax with proper adapter mappings configuration. The file includes multiple adapter mappings with version-specific matchers for various dependencies like Apollo, Dubbo, Log4j2, Logback, RocketMQ, and Spring components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the test configuration file exists and validate its content

# Check if the file exists in test resources
fd -t f "adapter-mapping-test.yaml" "src/test/resources"

# If found, validate YAML syntax and show content
if [ $? -eq 0 ]; then
    echo "Validating YAML syntax..."
    cat src/test/resources/adapter-mapping-test.yaml | python3 -c "import sys, yaml; yaml.safe_load(sys.stdin)"
fi

Length of output: 178


Script:

#!/bin/bash
# Let's first check if the test resources directory exists and locate the file
fd -t f "adapter-mapping-test.yaml"

# Let's also check the directory structure to understand where test resources might be located
fd -t d "test" --max-depth 4

Length of output: 524


Script:

#!/bin/bash
# Now that we found the file, let's check its content
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml

Length of output: 2633

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (2)

156-160: LGTM! Clean refactoring of dependency matching logic

The extraction of matching logic into a separate method improves code organization and readability. The enhanced logging will help with debugging.


193-203: LGTM! Well-structured version range matching

The version range matching logic is well-implemented with proper null checks and string comparisons.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (1)

88-94: Initialization of genericVersionRange handles empty version ranges appropriately

The initGenericVersionRange method correctly checks for an empty versionRange and initializes the genericVersionRange using the GenericVersionScheme. This ensures robustness in version range parsing.

Comment on lines 23 to 42
- matcher:
regexp: ".*spring-boot-starter-log4j2:3\\.(0|1).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.0
- matcher:
regexp: ".*spring-boot-starter-log4j2:3.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.2
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(1|2|3).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.1
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(4|5|6).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.4
- matcher:
regexp: ".*spring-boot-starter-log4j2.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.7
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review the order of Log4j2 matchers.

The catch-all pattern .*spring-boot-starter-log4j2.* at line 40 should be moved to the end of the Log4j2 section to prevent it from overriding more specific version matches.

  - matcher:
-     regexp: ".*spring-boot-starter-log4j2.*"
-   adapter:
-     artifactId: koupleless-adapter-log4j2-spring-starter-2.7
- - matcher:
      regexp: ".*spring-boot-starter-log4j2:3\\.(0|1).*"
    adapter:
      artifactId: koupleless-adapter-log4j2-spring-starter-3.0
  - matcher:
      regexp: ".*spring-boot-starter-log4j2:3.*"
    adapter:
      artifactId: koupleless-adapter-log4j2-spring-starter-3.2
  - matcher:
      regexp: ".*spring-boot-starter-log4j2:2\\.(1|2|3).*"
    adapter:
      artifactId: koupleless-adapter-log4j2-spring-starter-2.1
  - matcher:
      regexp: ".*spring-boot-starter-log4j2:2\\.(4|5|6).*"
    adapter:
      artifactId: koupleless-adapter-log4j2-spring-starter-2.4
+ - matcher:
+     regexp: ".*spring-boot-starter-log4j2.*"
+   adapter:
+     artifactId: koupleless-adapter-log4j2-spring-starter-2.7
📝 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.

Suggested change
- matcher:
regexp: ".*spring-boot-starter-log4j2:3\\.(0|1).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.0
- matcher:
regexp: ".*spring-boot-starter-log4j2:3.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.2
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(1|2|3).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.1
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(4|5|6).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.4
- matcher:
regexp: ".*spring-boot-starter-log4j2.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.7
- matcher:
regexp: ".*spring-boot-starter-log4j2:3\\.(0|1).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.0
- matcher:
regexp: ".*spring-boot-starter-log4j2:3.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-3.2
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(1|2|3).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.1
- matcher:
regexp: ".*spring-boot-starter-log4j2:2\\.(4|5|6).*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.4
- matcher:
regexp: ".*spring-boot-starter-log4j2.*"
adapter:
artifactId: koupleless-adapter-log4j2-spring-starter-2.7

Comment on lines +20 to +24
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
<version>1.9.18</version>
</dependency>
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Update maven-resolver-util to latest version 2.0.4

The current version 1.9.18 is outdated. Maven Central shows version 2.0.4 is available. Since this project uses modern Maven dependencies (maven-core 3.9.6), it's recommended to use the latest version for better compatibility and security.

  • Update maven-resolver-util version from 1.9.18 to 2.0.4 in koupleless-base-build-plugin/pom.xml
🔗 Analysis chain

Verify maven-resolver-util version selection

The addition of this dependency aligns well with the PR objective of adding version range support. Let's verify the version choice.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check latest version and compatibility of maven-resolver-util

# Check latest version on Maven Central
curl -s "https://search.maven.org/solrsearch/select?q=g:org.apache.maven.resolver+AND+a:maven-resolver-util&rows=1&wt=json" | jq -r '.response.docs[0].latestVersion'

# Check compatibility with existing Maven dependencies
rg -A 1 "maven-core|maven-aether-provider" pom.xml

Length of output: 426

Comment on lines 57 to 63
private KouplelessAdapterConfig loadConfig() throws IOException {
InputStream mappingConfigIS = this.getClass().getClassLoader()
.getResourceAsStream(MAPPING_FILE);

ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
return yamlMapper.readValue(mappingConfigIS, KouplelessAdapterConfig.class);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix potential resource leak in loadConfig()

The InputStream is not properly closed. Use try-with-resources to ensure proper resource cleanup.

Apply this diff:

 private KouplelessAdapterConfig loadConfig() throws IOException {
-    InputStream mappingConfigIS = this.getClass().getClassLoader()
-        .getResourceAsStream(MAPPING_FILE);
-
-    ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
-    return yamlMapper.readValue(mappingConfigIS, KouplelessAdapterConfig.class);
+    try (InputStream mappingConfigIS = this.getClass().getClassLoader()
+        .getResourceAsStream(MAPPING_FILE)) {
+        ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
+        return yamlMapper.readValue(mappingConfigIS, KouplelessAdapterConfig.class);
+    }
 }
📝 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.

Suggested change
private KouplelessAdapterConfig loadConfig() throws IOException {
InputStream mappingConfigIS = this.getClass().getClassLoader()
.getResourceAsStream(MAPPING_FILE);
ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
return yamlMapper.readValue(mappingConfigIS, KouplelessAdapterConfig.class);
}
private KouplelessAdapterConfig loadConfig() throws IOException {
try (InputStream mappingConfigIS = this.getClass().getClassLoader()
.getResourceAsStream(MAPPING_FILE)) {
ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
return yamlMapper.readValue(mappingConfigIS, KouplelessAdapterConfig.class);
}
}

Comment on lines 65 to 84
@Test
public void testMatcher() throws InvalidVersionSpecificationException {

List<Dependency> res = getMatcherAdaptor(
mockArtifact("org.springframework.boot", "spring-boot", "2.7.14"));
assertEquals(1, res.size());

res = getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "2.5.1"));
assertEquals(1, res.size());

res = getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "2.6.5"));
assertEquals(1, res.size());

res = getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "2.5.0"));
assertEquals(0, res.size());

res = getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "2.7.15"));
assertEquals(0, res.size());

}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance test coverage and documentation

The current test implementation could be improved in several ways:

  1. Add assertions to verify the actual content of matched dependencies, not just the count
  2. Include test cases for edge cases (null values, invalid versions)
  3. Document the test scenarios and expected outcomes
  4. Verify adapter mapping properties (groupId, artifactId, version)

Here's an example of how to enhance the test:

 @Test
 public void testMatcher() throws InvalidVersionSpecificationException {
+    // Test case 1: Version within range should match specific adapter
     List<Dependency> res = getMatcherAdaptor(
         mockArtifact("org.springframework.boot", "spring-boot", "2.7.14"));
     assertEquals(1, res.size());
+    Dependency matched = res.get(0);
+    assertEquals("expected.group", matched.getGroupId());
+    assertEquals("expected.artifact", matched.getArtifactId());
+    assertEquals("expected.version", matched.getVersion());
+
+    // Test case 2: Edge cases
+    assertThrows(InvalidVersionSpecificationException.class, () ->
+        getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "invalid")));
+    assertEquals(0, getMatcherAdaptor(null).size());

Additionally, consider splitting this into multiple focused test methods:

  • testValidVersionMatches()
  • testVersionOutOfRangeNoMatch()
  • testInvalidVersionHandling()

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +73 to +81
@Builder
public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
String versionRange) throws InvalidVersionSpecificationException {
this.regexp = regexp;
this.groupId = groupId;
this.artifactId = artifactId;
this.versionRange = versionRange;
this.genericVersionRange = initGenericVersionRange();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Refactor to handle checked exceptions with Lombok's @Builder

The constructor MavenDependencyMatcher is annotated with @Builder and throws InvalidVersionSpecificationException. Lombok's @Builder does not support checked exceptions, which can lead to compilation issues or make the builder unusable.

Consider removing the @Builder annotation or refactoring to handle the exception internally. Alternatively, you can modify the design to avoid throwing checked exceptions from the constructor.

Apply this diff to remove the @Builder annotation:

-    @Builder
     public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
                                   String versionRange) throws InvalidVersionSpecificationException {

Or handle the exception within the constructor:

     public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
-                                  String versionRange) throws InvalidVersionSpecificationException {
+                                  String versionRange) {
         this.regexp = regexp;
         this.groupId = groupId;
         this.artifactId = artifactId;
         this.versionRange = versionRange;
-        this.genericVersionRange = initGenericVersionRange();
+        try {
+            this.genericVersionRange = initGenericVersionRange();
+        } catch (InvalidVersionSpecificationException e) {
+            // Handle exception or rethrow as unchecked
+            throw new RuntimeException("Invalid version range specification", e);
+        }
     }
📝 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.

Suggested change
@Builder
public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
String versionRange) throws InvalidVersionSpecificationException {
this.regexp = regexp;
this.groupId = groupId;
this.artifactId = artifactId;
this.versionRange = versionRange;
this.genericVersionRange = initGenericVersionRange();
}
public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
String versionRange) throws InvalidVersionSpecificationException {
this.regexp = regexp;
this.groupId = groupId;
this.artifactId = artifactId;
this.versionRange = versionRange;
this.genericVersionRange = initGenericVersionRange();
}
```
Option 2 (Handling exception internally):
```suggestion
@Builder
public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
String versionRange) {
this.regexp = regexp;
this.groupId = groupId;
this.artifactId = artifactId;
this.versionRange = versionRange;
try {
this.genericVersionRange = initGenericVersionRange();
} catch (InvalidVersionSpecificationException e) {
// Handle exception or rethrow as unchecked
throw new RuntimeException("Invalid version range specification", e);
}
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (9)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml (3)

20-30: Optimize version range definitions for Spring AOP

The version range [5.3.27,5.3.27] can be simplified since it targets a single version. Also, consider if there are gaps in version coverage that need to be addressed.

  - matcher:
      groupId: org.springframework
      artifactId: spring-aop
-     versionRange: "[5.3.27,5.3.27]"
+     versionRange: "5.3.27"

32-36: Simplify version range for RocketMQ

The version range [4.4.0,4.4.0] can be simplified to a single version since it targets only 4.4.0.

  - matcher:
      groupId: org.apache.rocketmq
      artifactId: rocketmq-client
-     versionRange: "[4.4.0,4.4.0]"
+     versionRange: "4.4.0"

120-120: Add newline at end of file

Add a newline character at the end of the file to comply with YAML formatting standards.

🧰 Tools
🪛 yamllint (1.29.0-1)

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (3)

1-2: Add newline at end of file

Add a newline character at the end of the file to comply with YAML best practices.


31-36: Simplify RocketMQ version range syntax

For exact version matches like [4.4.0,4.4.0], consider using a simpler syntax to improve readability.

  - matcher:
      groupId: org.apache.rocketmq
      artifactId: rocketmq-client
-     versionRange: "[4.4.0,4.4.0]"
+     version: "4.4.0"
    adapter:
      artifactId: koupleless-adapter-rocketmq-4.4

1-120: Consider standardizing matcher styles

The configuration uses two different styles for matchers:

  1. Regular expressions (e.g., line 4)
  2. Structured matching with groupId/artifactId/version(Range)

Consider standardizing on the structured matching style for better maintainability and clarity.

🧰 Tools
🪛 yamllint (1.29.0-1)

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (3)

430-441: Reorder test methods for better readability

Test methods 13 and 14 are placed between methods 17 and 18. Consider reordering them to maintain a consistent numerical sequence, which would make the test class easier to navigate.

Also applies to: 452-461


506-515: Add null check for artifact parameter

The getMatcherAdaptor method should validate the input parameter to handle null artifacts gracefully.

 private List<Dependency> getMatcherAdaptor(Artifact artifact) throws InvalidVersionSpecificationException {
+    if (artifact == null) {
+        return Collections.emptyList();
+    }
     List<Dependency> adapterDependencies = new ArrayList<>();
     for (MavenDependencyAdapterMapping adapterMapping : adapterMappings) {

43-43: Add test case for invalid version format

Consider adding a test case that verifies the behavior when an invalid version format is provided. This would ensure proper error handling in the matcher implementation.

Example test to add:

@Test(expected = InvalidVersionSpecificationException.class)
public void testInvalidVersionFormat() throws InvalidVersionSpecificationException {
    getMatcherAdaptor(mockArtifact("org.springframework.boot", "spring-boot", "invalid.version"));
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 12d539b and c621727.

📒 Files selected for processing (4)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1 hunks)
🧰 Additional context used
📓 Learnings (1)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1)
Learnt from: gaosaroma
PR: koupleless/runtime#120
File: koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml:55-58
Timestamp: 2024-11-12T05:52:21.084Z
Learning: When suggesting changes to a regular expression for version matching, ensure to follow the user's specific request if they prefer a more precise match.
🪛 yamllint (1.29.0-1)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (8)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping.yaml (3)

44-78: LGTM! Comprehensive version coverage for Dubbo

The Dubbo adapter mappings provide good coverage across different major versions with well-defined ranges.


80-108: LGTM! Well-structured version ranges for Log4j2

The Log4j2 adapter mappings provide comprehensive coverage with clear version boundaries and no gaps.


8-12: Verify version coverage gap for Spring Boot

There appears to be a gap in version coverage between 2.7.14 and 3.0.0 for Spring Boot dependencies. Please verify if this gap is intentional or if it needs to be addressed.

Also applies to: 110-120

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (3)

43-78: LGTM! Well-structured Dubbo version ranges

The Dubbo adapter configuration is well-organized with:

  • Clear version boundaries
  • Non-overlapping ranges
  • Consistent adapter naming

79-108: LGTM! Well-structured Log4j2 version ranges

The Log4j2 adapter configuration demonstrates good practices:

  • Sequential version ranges
  • No overlapping ranges
  • Clear adapter version mapping

19-30: Verify spring-aop version range coverage

The current version ranges for spring-aop are very specific:

  • [6.0.8,6.0.9]
  • [5.3.27,5.3.27]

This might create gaps in version coverage. Verify if this is intentional or if broader ranges should be supported.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (1)

20-20: LGTM!

The import is necessary for the enhanced adapter mapping functionality and is properly utilized in the test assertions.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1)

57-63: Resource leak in loadConfig() method

The previous review comment about properly closing the InputStream is still valid.

Comment on lines 4 to 6
regexp: ".*spring-boot-starter-logging:3.*"
adapter:
artifactId: koupleless-adapter-logback-spring-starter-3.2
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Convert regex matcher to structured format for consistency

The regex-based matcher for spring-boot-starter-logging should be converted to the structured format used by other mappings for better maintainability and consistency.

  - matcher:
-     regexp: ".*spring-boot-starter-logging:3.*"
+     groupId: org.springframework.boot
+     artifactId: spring-boot-starter-logging
+     versionRange: "[3.0.0,4.0.0)"
    adapter:
      artifactId: koupleless-adapter-logback-spring-starter-3.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.

Suggested change
regexp: ".*spring-boot-starter-logging:3.*"
adapter:
artifactId: koupleless-adapter-logback-spring-starter-3.2
- matcher:
groupId: org.springframework.boot
artifactId: spring-boot-starter-logging
versionRange: "[3.0.0,4.0.0)"
adapter:
artifactId: koupleless-adapter-logback-spring-starter-3.2

Comment on lines 37 to 42
- matcher:
groupId: com.ctrip.framework.apollo
artifactId: apollo-client
versionRange: "(,)"
adapter:
artifactId: koupleless-adapter-apollo-1.6
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Specify version range for Apollo client

The current catch-all version range "(,)" might be too permissive. Consider specifying a version range that matches your testing and compatibility requirements.

  - matcher:
      groupId: com.ctrip.framework.apollo
      artifactId: apollo-client
-     versionRange: "(,)"
+     versionRange: "[1.6.0,2.0.0)"
    adapter:
      artifactId: koupleless-adapter-apollo-1.6
📝 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.

Suggested change
- matcher:
groupId: com.ctrip.framework.apollo
artifactId: apollo-client
versionRange: "(,)"
adapter:
artifactId: koupleless-adapter-apollo-1.6
- matcher:
groupId: com.ctrip.framework.apollo
artifactId: apollo-client
versionRange: "[1.6.0,2.0.0)"
adapter:
artifactId: koupleless-adapter-apollo-1.6

Comment on lines 3 to 18
- matcher:
regexp: ".*spring-boot-starter-logging:3.*"
adapter:
artifactId: koupleless-adapter-logback-spring-starter-3.2
- matcher:
groupId: org.springframework.boot
artifactId: spring-boot
versionRange: "[2.5.1,2.7.14]"
adapter:
artifactId: koupleless-adapter-spring-boot-logback-2.7.14
- matcher:
groupId: org.springframework.boot
artifactId: spring-boot-starter-logging
versionRange: "(,)"
adapter:
artifactId: koupleless-adapter-logback
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Review logging adapter matcher order

The catch-all version range "(,)" at line 16 could override more specific version ranges. Consider:

  1. Moving the catch-all matcher to the end of the logging section
  2. Specifying a more precise version range to prevent unintended matches
  - matcher:
      regexp: ".*spring-boot-starter-logging:3.*"
    adapter:
      artifactId: koupleless-adapter-logback-spring-starter-3.2
  - matcher:
      groupId: org.springframework.boot
      artifactId: spring-boot
      versionRange: "[2.5.1,2.7.14]"
    adapter:
      artifactId: koupleless-adapter-spring-boot-logback-2.7.14
- - matcher:
-     groupId: org.springframework.boot
-     artifactId: spring-boot-starter-logging
-     versionRange: "(,)"
-   adapter:
-     artifactId: koupleless-adapter-logback

Move this matcher to the end of the logging section.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 95 to 101
Assert.assertEquals(expected.getCommonDependencies().toString(), mojo.kouplelessAdapterConfig.getCommonDependencies().toString());

Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp(),
mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp());

Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString(),
mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString());
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve test assertions robustness

The current assertions have several potential issues:

  1. Using toString() for comparisons can be fragile and may not catch semantic differences
  2. The stream operations with findFirst().get() could throw NoSuchElementException if lists are empty
  3. Individual component comparisons might miss structural differences in the collections

Consider refactoring to:

-        Assert.assertEquals(expected.getCommonDependencies().toString(), mojo.kouplelessAdapterConfig.getCommonDependencies().toString());
-
-        Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp(),
-            mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp());
-
-        Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString(),
-                mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString());
+        // Compare common dependencies
+        Assert.assertEquals("Common dependencies size mismatch",
+            expected.getCommonDependencies().size(),
+            mojo.kouplelessAdapterConfig.getCommonDependencies().size());
+        for (int i = 0; i < expected.getCommonDependencies().size(); i++) {
+            Dependency expectedDep = expected.getCommonDependencies().get(i);
+            Dependency actualDep = mojo.kouplelessAdapterConfig.getCommonDependencies().get(i);
+            Assert.assertEquals("GroupId mismatch", expectedDep.getGroupId(), actualDep.getGroupId());
+            Assert.assertEquals("ArtifactId mismatch", expectedDep.getArtifactId(), actualDep.getArtifactId());
+            Assert.assertEquals("Version mismatch", expectedDep.getVersion(), actualDep.getVersion());
+        }
+
+        // Compare adapter mappings
+        Assert.assertEquals("Adapter mappings size mismatch",
+            expected.getAdapterMappings().size(),
+            mojo.kouplelessAdapterConfig.getAdapterMappings().size());
+        for (int i = 0; i < expected.getAdapterMappings().size(); i++) {
+            MavenDependencyAdapterMapping expectedMapping = expected.getAdapterMappings().get(i);
+            MavenDependencyAdapterMapping actualMapping = mojo.kouplelessAdapterConfig.getAdapterMappings().get(i);
+            
+            // Compare matchers
+            Assert.assertEquals("Matcher regexp mismatch",
+                expectedMapping.getMatcher().getRegexp(),
+                actualMapping.getMatcher().getRegexp());
+            
+            // Compare adapters
+            Assert.assertEquals("Adapter groupId mismatch",
+                expectedMapping.getAdapter().getGroupId(),
+                actualMapping.getAdapter().getGroupId());
+            Assert.assertEquals("Adapter artifactId mismatch",
+                expectedMapping.getAdapter().getArtifactId(),
+                actualMapping.getAdapter().getArtifactId());
+            Assert.assertEquals("Adapter version mismatch",
+                expectedMapping.getAdapter().getVersion(),
+                actualMapping.getAdapter().getVersion());
+        }

This refactoring:

  1. Adds proper size checks for collections
  2. Compares individual fields instead of using toString()
  3. Provides better error messages for failures
  4. Handles all elements in the collections, not just the first one
📝 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.

Suggested change
Assert.assertEquals(expected.getCommonDependencies().toString(), mojo.kouplelessAdapterConfig.getCommonDependencies().toString());
Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp(),
mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getMatcher).findFirst().get().getRegexp());
Assert.assertEquals(expected.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString(),
mojo.kouplelessAdapterConfig.getAdapterMappings().stream().map(MavenDependencyAdapterMapping::getAdapter).findFirst().get().toString());
// Compare common dependencies
Assert.assertEquals("Common dependencies size mismatch",
expected.getCommonDependencies().size(),
mojo.kouplelessAdapterConfig.getCommonDependencies().size());
for (int i = 0; i < expected.getCommonDependencies().size(); i++) {
Dependency expectedDep = expected.getCommonDependencies().get(i);
Dependency actualDep = mojo.kouplelessAdapterConfig.getCommonDependencies().get(i);
Assert.assertEquals("GroupId mismatch", expectedDep.getGroupId(), actualDep.getGroupId());
Assert.assertEquals("ArtifactId mismatch", expectedDep.getArtifactId(), actualDep.getArtifactId());
Assert.assertEquals("Version mismatch", expectedDep.getVersion(), actualDep.getVersion());
}
// Compare adapter mappings
Assert.assertEquals("Adapter mappings size mismatch",
expected.getAdapterMappings().size(),
mojo.kouplelessAdapterConfig.getAdapterMappings().size());
for (int i = 0; i < expected.getAdapterMappings().size(); i++) {
MavenDependencyAdapterMapping expectedMapping = expected.getAdapterMappings().get(i);
MavenDependencyAdapterMapping actualMapping = mojo.kouplelessAdapterConfig.getAdapterMappings().get(i);
// Compare matchers
Assert.assertEquals("Matcher regexp mismatch",
expectedMapping.getMatcher().getRegexp(),
actualMapping.getMatcher().getRegexp());
// Compare adapters
Assert.assertEquals("Adapter groupId mismatch",
expectedMapping.getAdapter().getGroupId(),
actualMapping.getAdapter().getGroupId());
Assert.assertEquals("Adapter artifactId mismatch",
expectedMapping.getAdapter().getArtifactId(),
actualMapping.getAdapter().getArtifactId());
Assert.assertEquals("Adapter version mismatch",
expectedMapping.getAdapter().getVersion(),
actualMapping.getAdapter().getVersion());
}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 14

🧹 Outside diff range and nitpick comments (37)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1)

8-8: Add newline at end of file

Add a newline character at the end of the file to follow YAML best practices.

🧰 Tools
🪛 yamllint (1.35.1)

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/pom.xml (1)

Line range hint 66-70: Consider removing jackson-dataformat-yaml if unused

Based on the AI summary, the project is moving from Jackson YAML to SnakeYAML. If jackson-dataformat-yaml is no longer used, consider removing this dependency to avoid potential version conflicts with SnakeYAML.

-            <dependency>
-                <groupId>com.fasterxml.jackson.dataformat</groupId>
-                <artifactId>jackson-dataformat-yaml</artifactId>
-                <version>2.13.5</version>
-            </dependency>
.github/workflows/koupleless_runtime_snapshot_adaptor_configs.yml (3)

16-28: Update GitHub Actions to latest versions.

The workflow uses older versions of actions that could be updated:

  • actions/checkout@v3actions/checkout@v4
  • actions/setup-java@v3actions/setup-java@v4
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up JDK 8
-        uses: actions/setup-java@v3
+        uses: actions/setup-java@v4

The secure handling of Maven credentials and GPG signing is well implemented.

🧰 Tools
🪛 actionlint (1.7.4)

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


29-33: Update checkout action version for adapter repo.

-        uses: actions/checkout@v3
+        uses: actions/checkout@v4

The repository and path configuration for the adapter checkout is well structured.

🧰 Tools
🪛 actionlint (1.7.4)

29-29: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


34-42: Improve documentation and command readability.

  1. Consider translating the Chinese comment for better international collaboration:
-          # 请在发布 koupleless-adapter-configs 之前,发布 jdk8 和 jdk17 所有的 koupleless-adapters
+          # Please release all koupleless-adapters for JDK8 and JDK17 before releasing koupleless-adapter-configs
  1. Consider formatting the Maven command for better readability:
-          mvn --batch-mode deploy -Psnapshot -pl koupleless-adapter-configs -am -amd -B -U
+          mvn deploy \
+              --batch-mode \
+              -Psnapshot \
+              -pl koupleless-adapter-configs \
+              -am -amd \
+              -B -U

The environment variables and secrets handling is well implemented.

.github/workflows/koupleless_runtime_release_2.1.x.yml (4)

Line range hint 18-108: Critical: Build and test steps are commented out

The entire build_and_test job has been commented out and the dependency (needs: build_and_test) has been removed from the release job. This means we're potentially releasing untested code. Either:

  1. Restore these essential quality checks, or
  2. Document why they were removed and where these checks are being performed instead

Line range hint 132-145: Consider improvements to module discovery logic

The module discovery implementation could be enhanced:

  1. The maxdepth limit of 2 might miss deeply nested modules
  2. Consider redirecting debug echo statements to a log file
- modules=$(find . -name pom.xml -maxdepth 2 -not -path "./pom.xml" -exec dirname {} \;)
- echo "$modules"
+ modules=$(find . -name pom.xml -not -path "./pom.xml" -exec dirname {} \;)
+ echo "$modules" >> module_discovery.log

166-170: Add deployment verification and rollback mechanism

The release process could benefit from additional safeguards:

  1. Verify successful deployment of each module
  2. Add rollback capability for failed deployments
 if [[ -n ${modules_in_release_version} ]]; then
   modules_in_release_version="${modules_in_release_version:0:-1}"
   echo "release for module ${modules_in_release_version}"
-  mvn --batch-mode deploy -Prelease -pl ${modules_in_release_version} -am -amd -B -U
+  if ! mvn --batch-mode deploy -Prelease -pl ${modules_in_release_version} -am -amd -B -U; then
+    echo "Deployment failed, initiating rollback..."
+    # Add rollback logic here
+    exit 1
+  fi
   echo "release completed for module ${modules_in_release_version}"
 fi

146-146: Fix trailing whitespace issues

Remove trailing whitespaces from the following lines:

  • Line 146
  • Line 155
  • Line 159
  • Line 165

Also applies to: 155-155, 159-159, 165-165

🧰 Tools
🪛 yamllint (1.35.1)

[error] 146-146: trailing spaces

(trailing-spaces)

.github/workflows/koupleless_runtime_release_adaptor_configs.yml (2)

16-28: Update GitHub Actions to latest versions.

The current actions are using older versions. Update them to the latest stable versions:

-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Set up JDK 8
-        uses: actions/setup-java@v3
+        uses: actions/setup-java@v4

Secure credential handling looks good! 👍
The workflow correctly uses GitHub secrets for sensitive data.

🧰 Tools
🪛 actionlint (1.7.4)

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


34-42: Consider these improvements to the release step:

  1. Translate the Chinese comment to English for better international collaboration
  2. Consider making the Maven command more explicit with comments explaining the flags
       - name: release adapter for jdk8
         run: |
-          # 请在发布 koupleless-adapter-configs 之前,发布 jdk8 和 jdk17 所有的 koupleless-adapters
+          # Please ensure all JDK8 and JDK17 koupleless-adapters are published before releasing koupleless-adapter-configs
           mvn --batch-mode deploy -Prelease -pl koupleless-adapter-configs -am -amd -B -U

The environment variables and Maven deployment configuration look secure and well-structured.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java (1)

54-61: Add null check for versionRange parameter

While the error handling is good, the method should validate the input parameter to prevent NullPointerException.

Consider adding a null check:

 public static VersionRange parseVersionRange(String versionRange) {
+    if (versionRange == null) {
+        throw new IllegalArgumentException("version range cannot be null");
+    }
     try {
         return versionScheme.parseVersionRange(versionRange);
     } catch (Exception e) {
         throw new RuntimeException("parse version range failed, version range: " + versionRange,
             e);
     }
 }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/AdapterConfig.java (4)

27-31: Enhance interface documentation

The interface documentation should include:

  1. A clear description of its purpose and role in adapter version range support
  2. The @since tag for version tracking
 /**
+ * Configuration interface for managing adapter mappings and their version ranges.
+ * This interface provides methods to match artifacts against adapter mapping rules
+ * and retrieve common dependencies required by the adapters.
+ *
  * @author lianglipeng.llp@alibaba-inc.com
  * @version $Id: AdapterConfig.java, v 0.1 2024年11月27日 11:40 立蓬 Exp $
+ * @since 0.1
  */

32-38: Enhance method documentation for version range handling

While the mapping cardinality is well documented, the method documentation should also include:

  1. Version range handling behavior
  2. Parameter validation expectations
  3. Exception handling scenarios
 /**
  * a mapping rule only map to an artifact; but an artifact can be mapped to multiple mapping rules
  * mapping -> artifact: 1 -> 1
  * artifact -> mapping: 1 -> N
  *
+ * @param resolvedArtifacts collection of artifacts to match against mapping rules
+ * @return map of matching rules to their corresponding artifacts
+ * @throws IllegalArgumentException if resolvedArtifacts is null
+ * @throws InvalidVersionSpecificationException if version range pattern is invalid
  */

40-40: Add documentation for getCommonDependencies method

The method lacks documentation explaining its purpose and usage.

+    /**
+     * Returns a list of common dependencies that should be applied to all adapters.
+     * These dependencies are typically shared across different adapter configurations.
+     *
+     * @return list of common dependencies
+     */
     List<Dependency> getCommonDependencies();

31-41: Consider thread safety requirements

As this interface will likely be used in a build plugin context where parallel processing might occur, implementations should ensure thread safety, especially for the matches method which processes collections.

Consider documenting thread safety requirements in the interface-level documentation to guide implementers.

.github/workflows/koupleless_runtime_release.yml (1)

140-140: Remove trailing whitespace

Several lines contain trailing whitespace. While this doesn't affect functionality, it's good practice to maintain clean formatting.

Remove trailing whitespace from lines 140, 146, 155, 159, and 165.

Also applies to: 146-146, 155-155, 159-159, 165-165

🧰 Tools
🪛 yamllint (1.35.1)

[error] 140-140: trailing spaces

(trailing-spaces)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (4)

87-90: Consider the implications of public field visibility

Several fields have been made public which could expose internal state and break encapsulation. Consider using protected visibility or providing getter methods instead.

-    public MavenProject project;
-    public MavenSession session;
-    public File baseDir;
-    public RepositorySystem repositorySystem;
+    protected MavenProject project;
+    protected MavenSession session;
+    protected File baseDir;
+    protected RepositorySystem repositorySystem;

Also applies to: 92-93, 96-96, 98-98, 100-104


171-178: Improve error handling in dependency download process

The validation checks are good, but the error handling could be more specific and informative.

-                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getVersion()),
-                    "dependency version is empty: " + dependency);
-                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getGroupId()),
-                    "dependency groupId is empty: " + dependency);
+                validateDependency(dependency);
                 getLog().debug("start downloading dependency: " + dependency);
                 Artifact artifact = downloadDependency(dependency);
                 getLog().debug("start add dependency to project root: " + dependency);

+    private void validateDependency(Dependency dependency) {
+        List<String> errors = new ArrayList<>();
+        if (StringUtils.isEmpty(dependency.getVersion())) {
+            errors.add("version is empty");
+        }
+        if (StringUtils.isEmpty(dependency.getGroupId())) {
+            errors.add("groupId is empty");
+        }
+        if (!errors.isEmpty()) {
+            throw new IllegalArgumentException("Invalid dependency " + dependency + ": " + String.join(", ", errors));
+        }
+    }

Line range hint 188-204: Enhance error handling in downloadDependency method

The current error handling is too generic. Consider handling specific exceptions and providing more detailed error messages.

     public Artifact downloadDependency(Dependency dependency) {
         DefaultArtifact patchArtifact = new DefaultArtifact(
             dependency.getGroupId() + ":" + dependency.getArtifactId() + ":"
                                                             + dependency.getVersion());
 
         try {
             ArtifactRequest artifactRequest = new ArtifactRequest().setArtifact(patchArtifact)
                 .setRepositories(project.getRemoteProjectRepositories());
 
             ArtifactResult artifactResult = repositorySystem
                 .resolveArtifact(session.getRepositorySession(), artifactRequest);
 
             Preconditions.checkState(artifactResult.isResolved(), "artifact not resolved.");
             return artifactResult.getArtifact();
-        } catch (Throwable t) {
-            getLog().error(t);
-            throw new RuntimeException(t);
+        } catch (org.eclipse.aether.resolution.ArtifactResolutionException e) {
+            getLog().error("Failed to resolve artifact: " + patchArtifact, e);
+            throw new RuntimeException("Failed to resolve artifact: " + patchArtifact, e);
+        } catch (Exception e) {
+            getLog().error("Unexpected error while downloading dependency: " + patchArtifact, e);
+            throw new RuntimeException("Unexpected error while downloading dependency: " + patchArtifact, e);
         }
     }

Line range hint 111-120: Add error handling for properties loading

The properties loading could fail silently if the resource is not found or if there are IO issues.

     void initKouplelessAdapterConfig() throws Exception {
         if (kouplelessAdapterConfig == null) {
             kouplelessAdapterConfig = new CompositeKouplelessAdapterConfig(this);
         }
 
         Properties properties = new Properties();
-        properties.load(getClass().getClassLoader().getResourceAsStream("project.properties"));
-        defaultGroupId = properties.getProperty("project.groupId");
-        defaultVersion = properties.getProperty("project.version");
+        try (InputStream is = getClass().getClassLoader().getResourceAsStream("project.properties")) {
+            if (is == null) {
+                throw new IllegalStateException("Could not find project.properties in classpath");
+            }
+            properties.load(is);
+            defaultGroupId = properties.getProperty("project.groupId");
+            defaultVersion = properties.getProperty("project.version");
+            if (defaultGroupId == null || defaultVersion == null) {
+                throw new IllegalStateException("Required properties 'project.groupId' or 'project.version' not found in project.properties");
+            }
+        } catch (IOException e) {
+            throw new IllegalStateException("Failed to load project.properties", e);
+        }
     }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml (3)

80-120: Ensure consistent version range patterns

The log4j2 and logback adapters use different version range patterns:

  • Some use exact ranges (e.g., [2.1.0,2.4.0))
  • Others use open-ended ranges (e.g., [3.2.0,))

Consider:

  1. Documenting the rationale for different patterns
  2. Using consistent patterns where possible
  3. Specifying upper bounds for open-ended ranges to prevent future compatibility issues
🧰 Tools
🪛 yamllint (1.35.1)

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)


19-30: Consider more flexible version ranges for spring-aop

Current ranges are very specific:

  • [6.0.8,6.0.9]
  • [5.3.27,5.3.27]

This tight coupling might make maintenance challenging. Consider using wider ranges if the adapter is compatible with more versions.


120-120: Add newline at end of file

Add a newline character at the end of the file to comply with YAML best practices.

🧰 Tools
🪛 yamllint (1.35.1)

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java (3)

22-22: Remove commented code instead of leaving it in place.

The migration from Jackson to SnakeYAML is clear, but we should remove the commented-out code rather than leaving it in the source. This improves code readability and prevents confusion about which implementation is current.

-//import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
-    //private ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());

Also applies to: 35-35


50-51: Remove commented code for the old implementation.

Remove the commented-out Jackson implementation line for better code clarity.

-        //KouplelessAdapterConfig config = yamlMapper.readValue(is, KouplelessAdapterConfig.class);

Line range hint 47-112: Consider refactoring the test method for better maintainability.

The test method is quite long and tests multiple different scenarios. Consider:

  1. Breaking it down into smaller, focused test methods grouped by adapter type (apollo, dubbo, log4j2, etc.)
  2. Using parameterized tests to reduce code duplication
  3. Moving test data to a separate test resource file

Example refactoring:

@Test
public void testApolloAdapterMapping() {
    KouplelessAdapterConfig config = loadConfig();
    Assert.assertEquals("koupleless-adapter-apollo-1.6",
        getMappingArtifact(config, "com.ctrip.framework.apollo:apollo-client:1.6.0:jar"));
}

@Test
public void testDubboAdapterMapping() {
    KouplelessAdapterConfig config = loadConfig();
    Assert.assertEquals("koupleless-adapter-dubbo-2.6",
        getMappingArtifact(config, "com.alibaba:dubbo:2.6.1:jar"));
    Assert.assertEquals("koupleless-adapter-dubbo-2.7",
        getMappingArtifact(config, "dubbo-spring-boot-starter:2.7.3:jar"));
    // ... other dubbo assertions
}

private KouplelessAdapterConfig loadConfig() {
    try (InputStream is = this.getClass().getClassLoader()
        .getResourceAsStream("adapter-mapping.yaml")) {
        Yaml yaml = new Yaml();
        KouplelessAdapterConfig config = yaml.loadAs(is, KouplelessAdapterConfig.class);
        if (config == null) {
            throw new IllegalStateException("Failed to load adapter configuration");
        }
        return config;
    } catch (Exception e) {
        throw new IllegalStateException("Failed to load test configuration", e);
    }
}
.github/workflows/koupleless_runtime_snapshot.yml (1)

165-169: Enhance release execution with better error handling and logging

The current release execution could benefit from improved error handling and logging.

Consider these improvements:

 if [[ -n ${modules_in_snapshot_version} ]]; then
   modules_in_snapshot_version="${modules_in_snapshot_version:0:-1}"
   echo "release for module ${modules_in_snapshot_version}"
-  mvn --batch-mode deploy -Psnapshot -pl ${modules_in_snapshot_version} -am -amd -B -U
+  if ! mvn --batch-mode deploy -Psnapshot -pl ${modules_in_snapshot_version} -am -amd -B -U; then
+    echo "Error: Maven deployment failed"
+    exit 1
+  fi
   echo "release completed for module ${modules_in_snapshot_version}"
+else
+  echo "No modules found matching the criteria for release"
 fi

Consider adding a summary report at the end of the workflow to show:

  • Total modules processed
  • Modules skipped (with reasons)
  • Modules successfully released
  • Any errors encountered
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (3)

23-23: Remove commented out import.

Clean up unused imports to maintain code cleanliness.

-//import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

46-53: Improve field declarations.

The field declarations could be improved for better encapsulation and readability:

  1. Fields should be private
  2. Constants should be static final
  3. Field names should follow Java naming conventions
-    String                                    MAPPING_FILE            = "adapter-mapping-test.yaml";
-    private KouplelessBaseBuildPrePackageMojo mojo                    = new KouplelessBaseBuildPrePackageMojo();
-    KouplelessAdapterConfig                   kouplelessAdapterConfig = loadConfig();
-    Collection<MavenDependencyAdapterMapping> adapterMappings         = CollectionUtils
-        .emptyIfNull(kouplelessAdapterConfig.getAdapterMappings());
+    private static final String MAPPING_FILE = "adapter-mapping-test.yaml";
+    private final KouplelessBaseBuildPrePackageMojo mojo = new KouplelessBaseBuildPrePackageMojo();
+    private final KouplelessAdapterConfig kouplelessAdapterConfig;
+    private final Collection<MavenDependencyAdapterMapping> adapterMappings;

88-105: Uncomment and improve utility methods.

The utility methods are commented out and could be improved:

  1. Add proper documentation
  2. Enhance error handling
  3. Make methods package-private instead of private for reuse in other test classes
-    //private List<Dependency> getMatcherAdaptor(Artifact artifact) throws InvalidVersionSpecificationException {
+    /**
+     * Get matching adapter dependencies for the given artifact.
+     *
+     * @param artifact the artifact to match against
+     * @return list of matching adapter dependencies
+     * @throws InvalidVersionSpecificationException if version is invalid
+     * @throws IllegalArgumentException if artifact is null
+     */
+    List<Dependency> getMatcherAdaptor(Artifact artifact) throws InvalidVersionSpecificationException {
+        if (artifact == null) {
+            throw new IllegalArgumentException("Artifact cannot be null");
+        }
         List<Dependency> adapterDependencies = new ArrayList<>();
         for (MavenDependencyAdapterMapping adapterMapping : adapterMappings) {
             MavenDependencyMatcher matcher = adapterMapping.getMatcher();
             if (mojo.kouplelessAdapterConfig.matches(matcher, artifact)) {
                 adapterDependencies.add(adapterMapping.getAdapter());
             }
         }
         return adapterDependencies;
     }

-    //private Artifact mockArtifact(String groupId, String artifactId, String version) {
+    /**
+     * Create a mock artifact with the given coordinates.
+     *
+     * @param groupId the group ID
+     * @param artifactId the artifact ID
+     * @param version the version
+     * @return mocked artifact
+     */
+    Artifact mockArtifact(String groupId, String artifactId, String version) {
         Artifact artifact = Mockito.mock(Artifact.class);
         Mockito.when(artifact.getGroupId()).thenReturn(groupId);
         Mockito.when(artifact.getArtifactId()).thenReturn(artifactId);
         Mockito.when(artifact.getVersion()).thenReturn(version);
         return artifact;
     }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java (1)

49-62: Declare fields as private to enforce encapsulation

Currently, the fields version, commonDependencies, and adapterMappings are package-private. It is a good practice to declare these fields as private to enforce encapsulation and protect the class's internal state.

Apply this diff to update the access modifiers:

- String                              version;                               // 依赖包的版本。
+ private String                       version;                               // 依赖包的版本。

...

- List<Dependency>                    commonDependencies = new ArrayList<>();
+ private List<Dependency>             commonDependencies = new ArrayList<>();

...

- List<MavenDependencyAdapterMapping> adapterMappings    = new ArrayList<>();
+ private List<MavenDependencyAdapterMapping> adapterMappings = new ArrayList<>();
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (2)

67-68: Ensure consistent use of Lombok annotations for versionRange

The versionRange field has a custom setter method that handles exceptions, but only the @Getter annotation is used. This might cause confusion or unintentional behavior since Lombok does not generate a setter in this case.

Consider explicitly preventing Lombok from generating a setter to avoid any conflicts or misunderstandings.

Suggested Change:

 @Getter
+@Setter(AccessLevel.NONE)
 private String versionRange;

44-44: Reconsider @Setter on deprecated regexp field

The regexp field is marked with @Deprecated but still has both @Getter and @Setter annotations. If the intention is to phase out this field, allowing it to be modified might lead to unintended usage.

Consider removing the @Setter annotation to make the field read-only and encourage migration to the new fields.

Suggested Change:

 @Getter
-@Setter
+@Setter(AccessLevel.NONE)
 @Deprecated
 private String regexp;
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java (3)

22-22: Replace deprecated Guava methods with standard Java collections

The import of com.google.common.collect.Maps is unnecessary. Since Java 7, you can use standard collections like new HashMap<>() instead of Maps.newHashMap(). This reduces dependencies and aligns with modern Java practices.

Apply this diff to replace the import:

-import com.google.common.collect.Maps;
+import java.util.HashMap;

Then, update the code to replace Maps.newHashMap() with new HashMap<>() throughout the class.


161-164: Improve the logging message for clarity

In the log message, consider rephrasing "will not config it" to "will not configure it" for better readability.

Apply this diff to correct the message:

- "koupleless-base-build-plugin: custom-adapter-mapping-config %s not found, will not config it"
+ "koupleless-base-build-plugin: custom-adapter-mapping-config %s not found, will not configure it"

200-203: Include exception details in warning logs

When catching exceptions in downloadAdapterConfigsJar, consider logging the exception details to aid in debugging. Including the exception message and stack trace can help identify the root cause of the failure.

Apply this diff to include exception details:

- mojo.getLog()
-     .warn("Failed to resolve koupleless-adapter-configs, use default config only.");
+ mojo.getLog()
+     .warn("Failed to resolve koupleless-adapter-configs, use default config only.", e);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between c621727 and 26c4a87.

📒 Files selected for processing (19)
  • .github/workflows/koupleless_runtime_release.yml (1 hunks)
  • .github/workflows/koupleless_runtime_release_2.1.x.yml (2 hunks)
  • .github/workflows/koupleless_runtime_release_adaptor_configs.yml (1 hunks)
  • .github/workflows/koupleless_runtime_snapshot.yml (1 hunks)
  • .github/workflows/koupleless_runtime_snapshot_2.1.x.yml (1 hunks)
  • .github/workflows/koupleless_runtime_snapshot_adaptor_configs.yml (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (5 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/AdapterConfig.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java (3 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java (3 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1 hunks)
  • koupleless-ext/koupleless-build-plugin/pom.xml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/pom.xml
🧰 Additional context used
🪛 yamllint (1.35.1)
.github/workflows/koupleless_runtime_release.yml

[error] 140-140: trailing spaces

(trailing-spaces)


[error] 146-146: trailing spaces

(trailing-spaces)


[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)


[error] 165-165: trailing spaces

(trailing-spaces)

.github/workflows/koupleless_runtime_snapshot.yml

[error] 154-154: trailing spaces

(trailing-spaces)


[error] 158-158: trailing spaces

(trailing-spaces)


[error] 164-164: trailing spaces

(trailing-spaces)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml

[error] 120-120: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/koupleless_runtime_release_2.1.x.yml

[error] 146-146: trailing spaces

(trailing-spaces)


[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)


[error] 165-165: trailing spaces

(trailing-spaces)

.github/workflows/koupleless_runtime_snapshot_2.1.x.yml

[error] 141-141: trailing spaces

(trailing-spaces)


[error] 150-150: trailing spaces

(trailing-spaces)


[error] 154-154: trailing spaces

(trailing-spaces)


[error] 160-160: trailing spaces

(trailing-spaces)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

🪛 actionlint (1.7.4)
.github/workflows/koupleless_runtime_release_adaptor_configs.yml

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


29-29: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.github/workflows/koupleless_runtime_snapshot_adaptor_configs.yml

16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


29-29: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (19)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml (1)

4-6: Specify version range for Apollo client

The current catch-all version range "(,)" might be too permissive. Consider specifying a version range that matches your testing and compatibility requirements.

  - matcher:
      groupId: com.ctrip.framework.apollo
      artifactId: apollo-client
-     versionRange: "(,)"
+     versionRange: "[1.6.0,2.0.0)"
    adapter:
      artifactId: koupleless-adapter-apollo-1.6
koupleless-ext/koupleless-build-plugin/pom.xml (1)

71-75: Verify the necessity of explicit SnakeYAML dependency

The jackson-dataformat-yaml dependency already includes SnakeYAML as a transitive dependency. Having both dependencies could lead to version conflicts.

✅ Verification successful

Both YAML libraries are actively used for different purposes

The code analysis reveals that:

  • SnakeYAML is used directly in production code for parsing configuration files (ark.yml and adapter-mapping.yaml)
  • Jackson YAML usage appears to be commented out in tests, indicating a transition from Jackson to SnakeYAML

The explicit SnakeYAML dependency is necessary as it's used directly in the codebase for configuration parsing. The presence of both libraries is intentional and serves different purposes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for SnakeYAML usage and verify if both YAML libraries are needed

# Check for direct SnakeYAML usage
echo "Checking for direct SnakeYAML usage..."
rg -l "org\.yaml\.snakeyaml"

# Check for Jackson YAML usage
echo "Checking for Jackson YAML usage..."
rg -l "jackson\.dataformat\.yaml"

Length of output: 1514


Script:

#!/bin/bash
# Let's examine the actual usage of both libraries in the key files to understand the transition

# Check SnakeYAML usage in ArkConfigHolder and CompositeKouplelessAdapterConfig
echo "=== Checking SnakeYAML usage in main code ==="
ast-grep --pattern 'import org.yaml.snakeyaml.$$$' koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/ArkConfigHolder.java
echo "\n=== Content of ArkConfigHolder.java ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/ArkConfigHolder.java

echo "\n=== Content of CompositeKouplelessAdapterConfig.java ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java

# Check Jackson YAML usage in test files
echo "\n=== Checking Jackson YAML usage in test files ==="
rg "import.*jackson\.dataformat\.yaml" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java

Length of output: 15964

.github/workflows/koupleless_runtime_snapshot_adaptor_configs.yml (2)

1-10: LGTM! Well-structured workflow configuration.

The workflow name is descriptive, and manual triggering is appropriate for controlled releases.


11-14: Consider adding test dependency for safer releases.

The commented out needs: build_and_test suggests this job should wait for tests to complete. Consider uncommenting this line or adding appropriate test dependencies to ensure releases are only created after successful testing.

.github/workflows/koupleless_runtime_release_adaptor_configs.yml (2)

4-9: LGTM! Well-structured workflow configuration.

The workflow name is descriptive and the manual trigger is appropriate for release workflows.


12-14: Consider adding prerequisite checks before release.

The commented needs: build_and_test suggests that build and test verification should run before releasing. Consider implementing these prerequisite checks to ensure release quality.

Run this script to check for existing build and test workflows:

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java (2)

20-22: LGTM! Well-structured version parsing setup

The imports and static field initialization are properly organized. Using a static final instance of GenericVersionScheme is appropriate as it's thread-safe and improves performance by avoiding repeated instantiation.

Also applies to: 37-38


63-69: Add null check and verify version parsing implementation

  1. Similar to parseVersionRange, add null validation to prevent NullPointerException.
  2. Let's verify that the implementation supports all version range formats mentioned in PR objectives.

Add null check:

 public static Version parseVersion(String version) {
+    if (version == null) {
+        throw new IllegalArgumentException("version cannot be null");
+    }
     try {
         return versionScheme.parseVersion(version);
     } catch (Exception e) {
         throw new RuntimeException("parse version failed, version: " + version, e);
     }
 }
✅ Verification successful

Let me check the implementation of version parsing in the found files to verify the concern.


Based on the code analysis, I can now generate the final response:

Add null check for consistency with existing patterns

The null check suggestion is valid as it maintains consistency with the codebase's error handling patterns. However, the version parsing implementation using GenericVersionScheme is correctly implemented and supports all required version range formats, as evidenced by:

  1. The GenericVersionScheme is properly initialized as a static final field
  2. The implementation is used consistently across the codebase in KouplelessAdapterConfig and MavenDependencyMatcher
  3. The error handling wraps exceptions with meaningful context

The suggested null check addition is good practice but not critical since:

  • The method is only called internally from KouplelessAdapterConfig where versions come from Maven artifacts
  • The RuntimeException with context message would still catch null issues
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the GenericVersionScheme supports all required version range formats

# Create a test file to verify version range parsing
cat << 'EOF' > /tmp/VersionRangeTest.java
import org.eclipse.aether.util.version.GenericVersionScheme;
import org.eclipse.aether.version.VersionRange;

class VersionRangeTest {
    public static void main(String[] args) throws Exception {
        GenericVersionScheme scheme = new GenericVersionScheme();
        String[] ranges = {
            "[1.0,2.0)", // inclusive to exclusive
            "[1.0,2.0]", // inclusive to inclusive
            "(,1.0]",    // less than or equal
            "[2.0,)"     // greater than or equal
        };
        for (String range : ranges) {
            try {
                VersionRange vr = scheme.parseVersionRange(range);
                System.out.println("Successfully parsed: " + range);
            } catch (Exception e) {
                System.err.println("Failed to parse: " + range + " - " + e.getMessage());
            }
        }
    }
}
EOF

# Search for any existing tests that verify version range parsing
echo "Searching for existing version range tests..."
rg -l "parseVersionRange|GenericVersionScheme" --type java

Length of output: 639


Script:

#!/bin/bash
# Check implementation details in the found files
echo "=== ParseUtils.java ==="
rg -A 10 "parseVersion|parseVersionRange|GenericVersionScheme" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java

echo -e "\n=== KouplelessAdapterConfig.java ==="
rg -A 10 "parseVersion|parseVersionRange|GenericVersionScheme" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java

echo -e "\n=== MavenDependencyMatcher.java ==="
rg -A 10 "parseVersion|parseVersionRange|GenericVersionScheme" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java

Length of output: 4013

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/AdapterConfig.java (1)

19-25: Verify the necessity of InvalidVersionSpecificationException import

The InvalidVersionSpecificationException is imported but not used in the interface. If it's needed by implementations, consider moving it to those specific implementation classes.

✅ Verification successful

The InvalidVersionSpecificationException import is necessary

The exception is used in the implementation classes and methods that interact with the AdapterConfig interface:

  • KouplelessBaseBuildPrePackageMojo.getDependenciesByMatching() throws this exception while using the matches() method
  • KouplelessAdapterConfig (implementation) imports and uses it
  • MavenDependencyMatcher uses it in version range handling

Since the exception propagates through the interface's implementation chain, it's appropriate to keep the import in the interface file.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if InvalidVersionSpecificationException is used in implementing classes
ast-grep --pattern 'class $_ implements AdapterConfig {
  $$$
  throws InvalidVersionSpecificationException
  $$$
}'

Length of output: 118


Script:

#!/bin/bash
# Let's try a different approach to find implementations and usages

# Find all implementations of AdapterConfig
echo "=== AdapterConfig implementations ==="
rg "class.*implements.*AdapterConfig" -l

# Find any usage of InvalidVersionSpecificationException
echo -e "\n=== InvalidVersionSpecificationException usages ==="
rg "InvalidVersionSpecificationException" --type java -C 2

# Find all method signatures in implementing classes that might throw this exception
echo -e "\n=== Methods that might throw the exception ==="
ast-grep --pattern 'throws $$$InvalidVersionSpecificationException$$$'

Length of output: 12004

.github/workflows/koupleless_runtime_release.yml (1)

147-170: 🛠️ Refactor suggestion

Improve version filtering and release process

Several areas need improvement:

  1. YAML parsing is fragile
  2. No error handling for Maven deployment
  3. Module list building could be simplified

Consider these improvements:

- adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
+ # Use yq for proper YAML parsing
+ if ! adapter_version=$(yq eval '.version' "$module/conf/adapter-mapping.yaml" 2>/dev/null); then
+   echo "Warning: Could not extract adapter version from $module/conf/adapter-mapping.yaml"
+   continue
+ fi

- modules_in_release_version="${modules_in_release_version}${module},"
+ modules_array+=("$module")

Then at the end:

- if [[ -n ${modules_in_release_version} ]]; then
-   modules_in_release_version="${modules_in_release_version:0:-1}"
+ if (( ${#modules_array[@]} > 0 )); then
+   modules_list=$(IFS=,; echo "${modules_array[*]}")
+   echo "Releasing modules: $modules_list"
+   # Add error handling for Maven deployment
+   if ! mvn --batch-mode deploy -Prelease -pl "$modules_list" -am -amd -B -U; then
+     echo "Error: Maven deployment failed"
+     exit 1
+   fi

Add validation for the adapter version format:

🧰 Tools
🪛 yamllint (1.35.1)

[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)


[error] 165-165: trailing spaces

(trailing-spaces)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (1)

149-160: ⚠️ Potential issue

Add error handling for InvalidVersionSpecificationException

The method throws InvalidVersionSpecificationException without handling it, which could lead to unexpected behavior upstream.

-    List<Dependency> getDependenciesByMatching(Collection<org.apache.maven.artifact.Artifact> resolvedArtifacts) throws InvalidVersionSpecificationException {
+    List<Dependency> getDependenciesByMatching(Collection<org.apache.maven.artifact.Artifact> resolvedArtifacts) {
         Map<MavenDependencyAdapterMapping, org.apache.maven.artifact.Artifact> matchedArtifact = kouplelessAdapterConfig
             .matches(resolvedArtifacts);
+        try {
             for (Entry<MavenDependencyAdapterMapping, org.apache.maven.artifact.Artifact> entry : matchedArtifact
                 .entrySet()) {
                 MavenDependencyMatcher matcher = entry.getKey().getMatcher();
                 getLog().info("koupleless adapter matched artifact: " + entry.getValue()
                               + " with matcher: " + matcher);
             }
             return matchedArtifact.keySet().stream().map(MavenDependencyAdapterMapping::getAdapter)
                 .collect(Collectors.toList());
+        } catch (InvalidVersionSpecificationException e) {
+            getLog().error("Invalid version specification in dependency matching", e);
+            return new ArrayList<>();
+        }
     }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml (3)

1-2: LGTM: Version and structure look good

The version follows semantic versioning, and the top-level structure is well-organized.


31-36: Verify RocketMQ version compatibility

The configuration specifies an exact version match [4.4.0,4.4.0] for RocketMQ. Please verify if the adapter is truly incompatible with other 4.4.x versions.


43-78: LGTM: Well-structured Dubbo adapter mappings

The Dubbo adapter mappings are well-organized with:

  • Clear version boundaries
  • Non-overlapping ranges
  • Consistent naming pattern
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java (1)

52-53: Verify YAML parsing compatibility after migration.

The switch from Jackson to SnakeYAML might affect how certain YAML features are parsed. Let's verify the compatibility:

✅ Verification successful

Migration to SnakeYAML is compatible with existing YAML files

After examining the YAML files and test class, the switch from Jackson to SnakeYAML is safe because:

  1. The YAML files only contain simple structures (maps and lists) with basic scalar types
  2. No advanced YAML features (anchors, aliases, custom tags, etc.) are used
  3. All test assertions pass with the new SnakeYAML implementation
  4. The data model (KouplelessAdapterConfig) uses standard Java beans that both libraries can handle
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential YAML parsing issues after migration

# Find all YAML test resources
echo "Checking for YAML test files:"
fd -e yaml -e yml

# Check for potentially unsupported YAML features
echo -e "\nChecking for complex YAML features that might need verification:"
rg -l '(\!\!|\{\%|\{\{|>|\||\*|\&|<<|---|\.\.\.)' -g '*.{yaml,yml}'

Length of output: 1143


Script:

#!/bin/bash
# Let's examine the content of the YAML files to check their structure

echo "=== Content of adapter-mapping-test.yaml ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-test.yaml

echo -e "\n=== Content of adapter-mapping-ext.yml ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/adapter-mapping-ext.yml

echo -e "\n=== Content of adapter-mapping-default.yaml ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/resources/adapter-mapping-default.yaml

# Let's also check the test class for any other YAML parsing expectations
echo -e "\n=== Content of TestAdapterFile.java ==="
cat koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java

Length of output: 10303

.github/workflows/koupleless_runtime_snapshot_2.1.x.yml (1)

Line range hint 13-13: Verify the removal of build and test job

The build_and_test job has been commented out and the release_for_jdk17 job runs independently. This could potentially lead to releasing untested code. Consider either:

  1. Re-enabling the test job and making it a prerequisite for release
  2. Adding explicit test steps within the release job

Also applies to: 121-121

✅ Verification successful

Tests are skipped but this is expected for snapshot releases

After verification, I found that:

  1. The build_and_test job is commented out, but all maven commands in the release job use -DskipTests flag
  2. This is a snapshot release workflow, where skipping tests is a common practice since:
    • Snapshots are development versions
    • Tests are typically run in the main branch and PR workflows
    • The corresponding release workflow likely includes tests

The current setup follows standard Maven snapshot deployment practices where rapid iterations are prioritized over full testing cycles.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any test jobs in other workflow files
rg -l 'build.*test' .github/workflows/

Length of output: 492


Script:

#!/bin/bash
# Check the content of build and test jobs in the workflow files
for file in .github/workflows/koupleless_runtime_snapshot_2.1.x.yml .github/workflows/koupleless_runtime_release_2.1.x.yml; do
    echo "=== $file ==="
    rg -A 10 'build.*test:' "$file"
done

# Also check if there are any test steps in the release job
echo "=== Checking test steps in release job ==="
rg -A 10 'release_for_jdk17:' .github/workflows/koupleless_runtime_snapshot_2.1.x.yml

Length of output: 1609


Script:

#!/bin/bash
# Check if there are any test steps in the maven commands within the release job
rg -A 20 'mvn' .github/workflows/koupleless_runtime_snapshot_2.1.x.yml

# Also check if there are any test configurations in the pom files
echo "=== Checking test configurations in pom.xml ==="
fd -e xml -x rg -l 'maven-surefire-plugin|maven-failsafe-plugin' {}

Length of output: 2248

🧰 Tools
🪛 actionlint (1.7.4)

127-127: shellcheck reported issue in this script: SC2086:info:6:44: Double quote to prevent globbing and word splitting

(shellcheck)


127-127: shellcheck reported issue in this script: SC2206:warning:11:34: Quote to prevent word splitting/globbing, or split robustly with mapfile or read -a

(shellcheck)


127-127: shellcheck reported issue in this script: SC2086:info:25:37: Double quote to prevent globbing and word splitting

(shellcheck)


127-127: shellcheck reported issue in this script: SC2086:info:37:42: Double quote to prevent globbing and word splitting

(shellcheck)

🪛 yamllint (1.35.1)

[error] 141-141: trailing spaces

(trailing-spaces)


[error] 150-150: trailing spaces

(trailing-spaces)


[error] 154-154: trailing spaces

(trailing-spaces)


[error] 160-160: trailing spaces

(trailing-spaces)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1)

55-64: ⚠️ Potential issue

Improve resource handling and initialization.

Several improvements needed:

  1. Resource leak in loadConfig()
  2. Missing null check for resource stream
  3. Constructor should initialize fields properly
-    public MatcherUtilsTest() throws IOException {
+    public MatcherUtilsTest() throws IOException {
+        this.kouplelessAdapterConfig = loadConfig();
+        this.adapterMappings = CollectionUtils.emptyIfNull(kouplelessAdapterConfig.getAdapterMappings());
     }

     private KouplelessAdapterConfig loadConfig() throws IOException {
-        InputStream mappingConfigIS = this.getClass().getClassLoader()
-            .getResourceAsStream(MAPPING_FILE);
-
-        Yaml yaml = new Yaml();
-        return yaml.loadAs(mappingConfigIS, KouplelessAdapterConfig.class);
+        try (InputStream mappingConfigIS = this.getClass().getClassLoader()
+            .getResourceAsStream(MAPPING_FILE)) {
+            if (mappingConfigIS == null) {
+                throw new IOException("Could not find resource: " + MAPPING_FILE);
+            }
+            Yaml yaml = new Yaml();
+            return yaml.loadAs(mappingConfigIS, KouplelessAdapterConfig.class);
+        }
     }

Likely invalid or redundant comment.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java (2)

73-81: 🛠️ Refactor suggestion

Refactor constructor to handle checked exceptions with Lombok's @Builder

The constructor MavenDependencyMatcher is annotated with @Builder and throws InvalidVersionSpecificationException. Lombok's @Builder does not support checked exceptions, which can lead to compilation issues or make the builder unusable.

Consider one of the following options:

  • Option 1: Remove the @Builder annotation if it's not essential.
  • Option 2: Handle the exception within the constructor and rethrow it as an unchecked exception.

Example Refactor for Option 2:

 @Builder
 public MavenDependencyMatcher(String regexp, String groupId, String artifactId,
-                              String versionRange) throws InvalidVersionSpecificationException {
+                              String versionRange) {
     this.regexp = regexp;
     this.groupId = groupId;
     this.artifactId = artifactId;
     this.versionRange = versionRange;
-    this.genericVersionRange = initGenericVersionRange();
+    try {
+        this.genericVersionRange = initGenericVersionRange();
+    } catch (InvalidVersionSpecificationException e) {
+        throw new RuntimeException("Invalid version range specification", e);
+    }
 }

83-86: 🛠️ Refactor suggestion

Avoid throwing checked exceptions from setter methods

The setter method setVersionRange throws InvalidVersionSpecificationException, which is a checked exception. It is unconventional for setter methods to throw checked exceptions, and it may cause unexpected issues for consumers of the class.

Consider handling the exception within the method or rethrowing it as an unchecked exception to maintain the usability of the setter.

Refactored Method Example:

 public void setVersionRange(String versionRange) throws InvalidVersionSpecificationException {
     this.versionRange = versionRange;
-    this.genericVersionRange = initGenericVersionRange();
+    try {
+        this.genericVersionRange = initGenericVersionRange();
+    } catch (InvalidVersionSpecificationException e) {
+        // Handle exception or convert to unchecked
+        throw new RuntimeException("Invalid version range specification", e);
+    }
 }

Comment on lines +147 to +164
# 过滤出需要发布的 adapter,过滤条件:adapter 版本与 pom.xml 中的版本一致
adapter_release_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
modules_in_release_version=""
for module in "${modules_in_right_jdk_array[@]}"; do
# 如果没有 adapter-mapping.yaml,则跳过(koupleless-adapter-configs 没有 adapter-mapping.yaml)
if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
continue
fi

# 读取模块中的 adapter-mapping.yaml 来确定 adapter 版本
adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
echo "${module} adapter version: ${adapter_version}"

# 如果是目标 adapter 版本,则记录
if [[ "${adapter_version}" == "${adapter_release_version}" ]]; then
modules_in_release_version="${modules_in_release_version}${module},"
fi
done
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve YAML parsing robustness

The current implementation uses grep/sed to parse YAML files, which is fragile and prone to errors. Consider:

  1. Using a proper YAML parser (yq/python-yaml)
  2. Adding error handling for malformed YAML files
  3. Validating the version format before comparison

Example improvement:

# Install yq for proper YAML parsing
if ! command -v yq &> /dev/null; then
    wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
    chmod +x /usr/local/bin/yq
fi

# Parse version using yq
adapter_version=$(yq eval '.version' "$module/conf/adapter-mapping.yaml" || echo "")
if [[ -z "$adapter_version" ]]; then
    echo "Warning: Failed to parse version from $module/conf/adapter-mapping.yaml"
    continue
fi
🧰 Tools
🪛 yamllint (1.35.1)

[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)

Comment on lines 29 to 33
uses: actions/checkout@v3
with:
repository: 'koupleless/adapter'
path: 'adapter'

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update checkout action version for adapter repository.

Update the checkout action to the latest version:

-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
📝 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.

Suggested change
uses: actions/checkout@v3
with:
repository: 'koupleless/adapter'
path: 'adapter'
uses: actions/checkout@v4
with:
repository: 'koupleless/adapter'
path: 'adapter'
🧰 Tools
🪛 actionlint (1.7.4)

29-29: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment on lines +135 to +145
modules_in_right_jdk_array=()
for module in "${modules[@]}"; do
# 读取模块中的 pom.xml 来确定 JDK 版本
jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
echo "${module} JDK version: ${jdk_version}"
# 如果是目标 jdk 版本,则执行 release 操作


# 如果是目标 jdk 版本,则记录
if [[ "${jdk_version}" == "1.8" ]]; then
modules_in_right_jdk="${modules_in_right_jdk}${module},"
modules_in_right_jdk_array+=(${module})
fi
done
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance module discovery robustness

The current JDK version extraction logic could be more resilient:

  1. It assumes a specific pom.xml format
  2. Lacks error handling for malformed or missing version tags
  3. No validation of extracted version format

Consider this more robust implementation:

- jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
+ # Extract and validate JDK version
+ if ! jdk_version=$(xmllint --xpath "string(//java.version)" $module/pom.xml 2>/dev/null); then
+   echo "Warning: Could not extract JDK version from $module/pom.xml"
+   continue
+ fi
+ # Validate version format
+ if [[ ! $jdk_version =~ ^1\.[0-9]+$|^[0-9]+(\.[0-9]+)*$ ]]; then
+   echo "Warning: Invalid JDK version format in $module: $jdk_version"
+   continue
+ fi

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 yamllint (1.35.1)

[error] 140-140: trailing spaces

(trailing-spaces)

Comment on lines +37 to +42
- matcher:
groupId: com.ctrip.framework.apollo
artifactId: apollo-client
versionRange: "(,)"
adapter:
artifactId: koupleless-adapter-apollo-1.6
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Review unlimited version range for Apollo

The catch-all version range "(,)" for Apollo client might be too permissive. Consider:

  1. Specifying a minimum supported version
  2. Setting an upper bound to prevent compatibility issues with future versions

Comment on lines +14 to +18
groupId: org.springframework.boot
artifactId: spring-boot-starter-logging
versionRange: "(,)"
adapter:
artifactId: koupleless-adapter-logback
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

⚠️ Potential issue

Remove catch-all version range for spring-boot-starter-logging

The catch-all version range "(,)" is indeed problematic as it overlaps with other specific version ranges. The codebase shows a well-structured version-specific mapping:

  • ".*spring-boot-starter-logging:3.*" → koupleless-adapter-logback-spring-starter-3.2
  • "[3.0.0,3.2.0)" → koupleless-adapter-logback-spring-starter-3.0
  • "[3.2.0,)" → koupleless-adapter-logback-spring-starter-3.2

The test file TestAdapterFile.java confirms these mappings work correctly for versions 1.1, 3.0, 3.1, and 3.2. The catch-all range should be removed as it's redundant and could cause ambiguous adapter selection.

🔗 Analysis chain

Review catch-all version range

The catch-all version range "(,)" for spring-boot-starter-logging overlaps with other specific version ranges. This might cause ambiguous adapter selection.

Consider removing this catch-all range and explicitly define version ranges for all supported versions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other spring-boot-starter-logging entries that might conflict
rg "spring-boot-starter-logging" -A 4 -B 2

Length of output: 8259

Comment on lines +134 to +144
modules_in_right_jdk_array=()
for module in "${modules[@]}"; do
# 读取模块中的 pom.xml 来确定 JDK 版本
jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
echo "${module} JDK version: ${jdk_version}"
# 如果是目标 jdk 版本,则执行 release 操作


# 如果是目标 jdk 版本,则记录
if [[ "${jdk_version}" == "1.8" ]]; then
modules_in_right_jdk="${modules_in_right_jdk}${module},"
modules_in_right_jdk_array+=(${module})
fi
done
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for module version detection

The current implementation might fail silently if:

  • The java.version tag is missing in pom.xml
  • The version format is unexpected
  • The pom.xml file is malformed

Consider adding these improvements:

 modules_in_right_jdk_array=()
 for module in "${modules[@]}"; do
-  jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
+  if [[ ! -f "$module/pom.xml" ]]; then
+    echo "Warning: pom.xml not found in $module"
+    continue
+  fi
+  
+  jdk_version=$(grep -m 1 '<java.version>' "$module/pom.xml" | sed 's/<[^>]*>//g' | xargs)
+  if [[ -z "$jdk_version" ]]; then
+    echo "Warning: java.version not found in $module/pom.xml"
+    continue
+  fi
+
+  # Validate version format
+  if [[ ! "$jdk_version" =~ ^[0-9]+\.[0-9]+$ ]]; then
+    echo "Warning: Invalid java.version format in $module/pom.xml: $jdk_version"
+    continue
+  fi
   
   echo "${module} JDK version: ${jdk_version}"
📝 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.

Suggested change
modules_in_right_jdk_array=()
for module in "${modules[@]}"; do
# 读取模块中的 pom.xml 来确定 JDK 版本
jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
echo "${module} JDK version: ${jdk_version}"
# 如果是目标 jdk 版本,则执行 release 操作
# 如果是目标 jdk 版本,则记录
if [[ "${jdk_version}" == "1.8" ]]; then
modules_in_right_jdk="${modules_in_right_jdk}${module},"
modules_in_right_jdk_array+=(${module})
fi
done
modules_in_right_jdk_array=()
for module in "${modules[@]}"; do
if [[ ! -f "$module/pom.xml" ]]; then
echo "Warning: pom.xml not found in $module"
continue
fi
jdk_version=$(grep -m 1 '<java.version>' "$module/pom.xml" | sed 's/<[^>]*>//g' | xargs)
if [[ -z "$jdk_version" ]]; then
echo "Warning: java.version not found in $module/pom.xml"
continue
fi
# Validate version format
if [[ ! "$jdk_version" =~ ^[0-9]+\.[0-9]+$ ]]; then
echo "Warning: Invalid java.version format in $module/pom.xml: $jdk_version"
continue
fi
echo "${module} JDK version: ${jdk_version}"
# 如果是目标 jdk 版本,则记录
if [[ "${jdk_version}" == "1.8" ]]; then
modules_in_right_jdk_array+=(${module})
fi
done

Comment on lines +146 to 164
# 过滤出需要发布的 adapter,过滤条件:adapter 版本与 pom.xml 中的版本一致
adapter_snapshot_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
modules_in_snapshot_version=""
for module in "${modules_in_right_jdk_array[@]}"; do
# 如果没有 adapter-mapping.yaml,则跳过( koupleless-adapter-configs 没有 adapter-mapping.yaml)
if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
continue
fi

# 读取模块中的 adapter-mapping.yaml 来确定 adapter 版本
adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
echo "${module} adapter version: ${adapter_version}"

# 如果是目标 adapter 版本,则记录
if [[ "${adapter_version}" == "${adapter_snapshot_version}" ]]; then
modules_in_snapshot_version="${modules_in_snapshot_version}${module},"
fi
done

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve version extraction and validation logic

The current version extraction logic has several potential issues:

  1. The grep commands for version extraction are fragile
  2. No validation of extracted versions
  3. Trailing spaces in the code

Consider these improvements:

-adapter_snapshot_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
+adapter_snapshot_version=$(xmllint --xpath "string(//revision)" pom.xml 2>/dev/null)
+if [[ -z "$adapter_snapshot_version" ]]; then
+  echo "Error: Failed to extract snapshot version from pom.xml"
+  exit 1
+fi

 modules_in_snapshot_version=""
 for module in "${modules_in_right_jdk_array[@]}"; do
   if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
     continue
   fi
 
-  adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
+  # Use yq for YAML parsing if available
+  if command -v yq >/dev/null 2>&1; then
+    adapter_version=$(yq eval '.version' "$module/conf/adapter-mapping.yaml")
+  else
+    adapter_version=$(grep 'version:' "$module/conf/adapter-mapping.yaml" | sed -e 's/.*version:\s*\(.*\)/\1/' | tr -d ' ')
+  fi
+
+  if [[ -z "$adapter_version" ]]; then
+    echo "Warning: Failed to extract adapter version from $module/conf/adapter-mapping.yaml"
+    continue
+  fi

Remove trailing spaces from lines 154, 158, and 164.

📝 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.

Suggested change
# 过滤出需要发布的 adapter,过滤条件:adapter 版本与 pom.xml 中的版本一致
adapter_snapshot_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
modules_in_snapshot_version=""
for module in "${modules_in_right_jdk_array[@]}"; do
# 如果没有 adapter-mapping.yaml,则跳过( koupleless-adapter-configs 没有 adapter-mapping.yaml)
if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
continue
fi
# 读取模块中的 adapter-mapping.yaml 来确定 adapter 版本
adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
echo "${module} adapter version: ${adapter_version}"
# 如果是目标 adapter 版本,则记录
if [[ "${adapter_version}" == "${adapter_snapshot_version}" ]]; then
modules_in_snapshot_version="${modules_in_snapshot_version}${module},"
fi
done
# 过滤出需要发布的 adapter,过滤条件:adapter 版本与 pom.xml 中的版本一致
adapter_snapshot_version=$(xmllint --xpath "string(//revision)" pom.xml 2>/dev/null)
if [[ -z "$adapter_snapshot_version" ]]; then
echo "Error: Failed to extract snapshot version from pom.xml"
exit 1
fi
modules_in_snapshot_version=""
for module in "${modules_in_right_jdk_array[@]}"; do
# 如果没有 adapter-mapping.yaml,则跳过( koupleless-adapter-configs 没有 adapter-mapping.yaml)
if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
continue
fi
# 读取模块中的 adapter-mapping.yaml 来确定 adapter 版本
# Use yq for YAML parsing if available
if command -v yq >/dev/null 2>&1; then
adapter_version=$(yq eval '.version' "$module/conf/adapter-mapping.yaml")
else
adapter_version=$(grep 'version:' "$module/conf/adapter-mapping.yaml" | sed -e 's/.*version:\s*\(.*\)/\1/' | tr -d ' ')
fi
if [[ -z "$adapter_version" ]]; then
echo "Warning: Failed to extract adapter version from $module/conf/adapter-mapping.yaml"
continue
fi
echo "${module} adapter version: ${adapter_version}"
# 如果是目标 adapter 版本,则记录
if [[ "${adapter_version}" == "${adapter_snapshot_version}" ]]; then
modules_in_snapshot_version="${modules_in_snapshot_version}${module},"
fi
done
🧰 Tools
🪛 yamllint (1.35.1)

[error] 154-154: trailing spaces

(trailing-spaces)


[error] 158-158: trailing spaces

(trailing-spaces)


[error] 164-164: trailing spaces

(trailing-spaces)

Comment on lines 75 to 86
//@Test
//public void testMatcher6() throws InvalidVersionSpecificationException {
// List<Dependency> res = getMatcherAdaptor(
// mockArtifact("com.ctrip.framework.apollo", "apollo-client", "1.0.0"));
// assertEquals(1, res.size());
// assertEquals(res.get(0).getArtifactId(), "koupleless-adapter-apollo-1.6");
//
// res = getMatcherAdaptor(
// mockArtifact("com.ctrip.framework.apollo", "apollo-client", "2.3.0"));
// assertEquals(1, res.size());
// assertEquals(res.get(0).getArtifactId(), "koupleless-adapter-apollo-1.6");
//}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Uncomment and enhance test coverage.

The test method is commented out, which prevents proper validation of the version range functionality. Additionally, the test coverage should be expanded to:

  1. Test all version range syntax patterns mentioned in PR objectives: [x,y], (x,y), [x,y), (x,y]
  2. Add edge cases and invalid version tests
  3. Verify adapter properties more thoroughly
-    //@Test
-    //public void testMatcher6() throws InvalidVersionSpecificationException {
+    @Test
+    public void testMatcher6() throws InvalidVersionSpecificationException {
+        // Test inclusive range
+        List<Dependency> res = getMatcherAdaptor(
+            mockArtifact("com.ctrip.framework.apollo", "apollo-client", "1.0.0"));
+        assertEquals("Unexpected number of matching dependencies", 1, res.size());
+        assertEquals("Unexpected adapter artifact", "koupleless-adapter-apollo-1.6", 
+            res.get(0).getArtifactId());
+
+        // Test exclusive range
+        res = getMatcherAdaptor(
+            mockArtifact("com.ctrip.framework.apollo", "apollo-client", "2.3.0"));
+        assertEquals("Unexpected number of matching dependencies", 1, res.size());
+        assertEquals("Unexpected adapter artifact", "koupleless-adapter-apollo-1.6", 
+            res.get(0).getArtifactId());
+
+        // Test invalid version
+        try {
+            getMatcherAdaptor(
+                mockArtifact("com.ctrip.framework.apollo", "apollo-client", "invalid"));
+            fail("Expected InvalidVersionSpecificationException");
+        } catch (InvalidVersionSpecificationException e) {
+            // Expected
+        }
     }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +76 to +78
if (StringUtils.isEmpty(adapter.getVersion())) {
adapter.setVersion(version);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ensure 'version' is not null before setting adapter version

When setting the adapter's version, the version field might be null, leading to potential issues. It's important to check if version is not empty before assigning it to adapter.

Apply this diff to add a null check:

 if (StringUtils.isEmpty(adapter.getVersion())) {
+    if (StringUtils.isNotEmpty(version)) {
         adapter.setVersion(version);
+    }
 }
📝 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.

Suggested change
if (StringUtils.isEmpty(adapter.getVersion())) {
adapter.setVersion(version);
}
if (StringUtils.isEmpty(adapter.getVersion())) {
if (StringUtils.isNotEmpty(version)) {
adapter.setVersion(version);
}
}

Comment on lines +235 to +244
VersionRangeRequest rangeRequest = new VersionRangeRequest()
.setArtifact(new org.eclipse.aether.artifact.DefaultArtifact(
REMOTE_ADAPTER_CONFIGS + ":(,)"))
.setRepositories(mojo.project.getRemoteProjectRepositories());

VersionRangeResult rangeResult = mojo.repositorySystem
.resolveVersionRange(mojo.session.getRepositorySession(), rangeRequest);
Version latestVersion = rangeResult.getHighestVersion();
version = latestVersion.toString();
} catch (VersionRangeResolutionException e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Verify the correctness of the version range syntax in parseRemoteConfigVersion

In the method parseRemoteConfigVersion, the version range is specified as REMOTE_ADAPTER_CONFIGS + ":(,)", which may not correctly match all versions as intended. Please ensure that the version range syntax is valid and retrieves the correct versions from the repository. Consider using a standard syntax like :[0,) to specify an open-ended range starting from version 0.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (21)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/mockBaseDir/conf/ark/adapter-mapping.yaml (1)

8-8: Add newline at end of file

Add a newline character at the end of the file to follow YAML best practices.

   artifactId: koupleless-adapter-apollo-1.6
+
🧰 Tools
🪛 yamllint (1.35.1)

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/utils/ReflectionUtils.java (2)

48-60: Add JavaDoc documentation for the getField method.

The method needs proper documentation to describe:

  • Purpose and behavior
  • Parameter descriptions
  • Return value description
  • Exception handling behavior

Apply this diff to add documentation:

+    /**
+     * Get field value of specified object, will try to operate on super class until success
+     *
+     * @param fieldName name of the field to get
+     * @param o target object to get field from
+     * @param <T> expected type of the field value
+     * @return field value cast to type T, or null if field not found
+     */
     public static <T> T getField(String fieldName, Object o) {

55-57: Consider logging failed attempts to aid debugging.

Silent exception handling makes it difficult to debug issues when fields aren't found.

Consider adding debug logging:

             } catch (Exception e) {
+                // Consider adding debug logging here
                 klass = klass.getSuperclass();
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1)

37-47: Enhance class structure and field declarations

Consider the following improvements:

  1. Declare fields as final since they're initialized only once
  2. Use Path or File instead of String for file paths
  3. Remove empty constructor as it adds no value
-    String                                    MAPPING_FILE            = "mockBaseDir/conf/ark/adapter-mapping-test.yaml";
-    private KouplelessBaseBuildPrePackageMojo mojo                    = new KouplelessBaseBuildPrePackageMojo();
-    KouplelessAdapterConfig                   kouplelessAdapterConfig = loadConfig();
-    Collection<MavenDependencyAdapterMapping> adapterMappings         = CollectionUtils
+    private static final Path MAPPING_FILE = Path.of("mockBaseDir/conf/ark/adapter-mapping-test.yaml");
+    private final KouplelessBaseBuildPrePackageMojo mojo = new KouplelessBaseBuildPrePackageMojo();
+    private final KouplelessAdapterConfig kouplelessAdapterConfig = loadConfig();
+    private final Collection<MavenDependencyAdapterMapping> adapterMappings = CollectionUtils
         .emptyIfNull(kouplelessAdapterConfig.getAdapterMappings());

-    public MatcherUtilsTest() throws IOException {
-    }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (4)

63-63: Add documentation for the outputDirectory field

Consider adding a Javadoc comment explaining the purpose of this field and its usage in the tests.

+    /** Directory used for test output files during dependency resolution testing */
     private File outputDirectory = null;

67-72: Enhance test coverage for initialization logic

The current test only verifies default values but doesn't test the actual initialization logic of kouplelessAdapterConfig. Consider adding assertions for:

  • Configuration loading behavior
  • Error handling scenarios
  • Edge cases with different configuration values

84-84: Remove or implement the commented code

The commented line suggests incomplete implementation. Either implement the mock setup or remove the comment if it's no longer needed.


Line range hint 77-133: Improve test readability and structure

The test method is complex and could benefit from better organization:

  1. Extract setup blocks into helper methods
  2. Add comments explaining the purpose of each setup block
  3. Enhance assertions to verify more than just file existence

Here's a suggested refactoring:

     @Test
     public void testAddDependencyDynamically() throws Exception {
         KouplelessBaseBuildPrePackageMojo mojo = new KouplelessBaseBuildPrePackageMojo();
-        mojo.project = mock(MavenProject.class);
-        // init maven project
-        Set<org.apache.maven.artifact.Artifact> artifacts = new HashSet<>();
-        org.apache.maven.artifact.Artifact artifact = mock(
-            org.apache.maven.artifact.Artifact.class);
-        doReturn("A").when(artifact).getGroupId();
-        doReturn("C").when(artifact).getBaseVersion();
-        artifacts.add(artifact);
-        doReturn(artifacts).when(mojo.project).getArtifacts();
-        // set resolvedArtifacts in project
-        Field field = MavenProject.class.getDeclaredField("resolvedArtifacts");
-        field.setAccessible(true);
-        field.set(mojo.project, artifacts);
+        
+        // Setup test artifacts and project
+        org.apache.maven.artifact.Artifact artifact = setupTestArtifact();
+        setupMavenProject(mojo, artifact);
+        
+        // Setup adapter configuration
+        setupAdapterConfig(mojo, artifact);
+        
+        // Setup repository system
+        setupRepositorySystem(mojo);
+        
+        // Setup Maven session
+        setupMavenSession(mojo);
+        
+        // Setup output directory
+        setupOutputDirectory(mojo);

         mojo.execute();

-        {
-            Assert.assertTrue(Paths
-                .get(mojo.outputDirectory.getAbsolutePath(), "classes", "com", "example", "demo")
-                .toFile().exists());
-        }
+        // Verify results
+        verifyExecutionResults(mojo);
     }
+    
+    private org.apache.maven.artifact.Artifact setupTestArtifact() {
+        org.apache.maven.artifact.Artifact artifact = mock(org.apache.maven.artifact.Artifact.class);
+        doReturn("A").when(artifact).getGroupId();
+        doReturn("C").when(artifact).getBaseVersion();
+        return artifact;
+    }
+    
+    private void setupMavenProject(KouplelessBaseBuildPrePackageMojo mojo, org.apache.maven.artifact.Artifact artifact) throws Exception {
+        mojo.project = mock(MavenProject.class);
+        Set<org.apache.maven.artifact.Artifact> artifacts = new HashSet<>();
+        artifacts.add(artifact);
+        doReturn(artifacts).when(mojo.project).getArtifacts();
+        
+        Field field = MavenProject.class.getDeclaredField("resolvedArtifacts");
+        field.setAccessible(true);
+        field.set(mojo.project, artifacts);
+    }
+    
+    private void verifyExecutionResults(KouplelessBaseBuildPrePackageMojo mojo) {
+        File outputDir = Paths.get(mojo.outputDirectory.getAbsolutePath(), "classes", "com", "example", "demo").toFile();
+        Assert.assertTrue("Output directory should exist", outputDir.exists());
+        Assert.assertTrue("Output directory should be readable", outputDir.canRead());
+        // Add more specific assertions about the expected output
+    }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (4)

82-94: Consider maintaining encapsulation for class fields

Several fields have been made public which could break encapsulation. Consider keeping them private and providing accessor methods if needed.

-    public MavenProject                        project;
+    private MavenProject                        project;

-    public MavenSession                        session;
+    private MavenSession                        session;

-    public File                                baseDir;
+    private File                                baseDir;

-    public RepositorySystem                    repositorySystem;
+    private RepositorySystem                    repositorySystem;

98-102: Document the purpose and format of new configuration parameters

The new parameters kouplelessAdapterConfigVersion and customAdaptorMapping lack documentation explaining their purpose and expected format.

Add Javadoc comments explaining:

  • The format and purpose of kouplelessAdapterConfigVersion
  • The expected structure of customAdaptorMapping
  • Example values for both parameters

Line range hint 134-142: Replace reflection with API methods to access resolved artifacts

Using reflection to access private fields is fragile and may break with different Maven versions.

Consider using Maven's public APIs to access resolved artifacts:

-        Field field = MavenProject.class.getDeclaredField("resolvedArtifacts");
-        field.setAccessible(true);
-        Set<org.apache.maven.artifact.Artifact> resolvedArtifacts = (Set<org.apache.maven.artifact.Artifact>) field
-            .get(project);
+        Set<org.apache.maven.artifact.Artifact> resolvedArtifacts = project.getArtifacts();

173-177: Enhance error messages in precondition checks

The error messages could be more descriptive to help diagnose issues.

-                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getVersion()),
-                    "dependency version is empty: " + dependency);
-                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getGroupId()),
-                    "dependency groupId is empty: " + dependency);
+                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getVersion()),
+                    "Dependency version cannot be empty. Dependency details: [groupId=%s, artifactId=%s]",
+                    dependency.getGroupId(), dependency.getArtifactId());
+                Preconditions.checkArgument(StringUtils.isNotEmpty(dependency.getGroupId()),
+                    "Dependency groupId cannot be empty. Dependency details: [artifactId=%s, version=%s]",
+                    dependency.getArtifactId(), dependency.getVersion());
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java (2)

49-49: Consider adding version validation.

While the field declarations look good, consider adding validation for the version field to ensure it follows semantic versioning format.

+    @Builder.Default
     String                              version;                               // 依赖包的版本。
+
+    private void validateVersion() {
+        if (StringUtils.isNotEmpty(version)) {
+            try {
+                new GenericVersionScheme().parseVersion(version);
+            } catch (InvalidVersionSpecificationException e) {
+                throw new IllegalArgumentException("Invalid version format: " + version, e);
+            }
+        }
+    }

Also applies to: 54-61


64-85: Consider using concurrent-safe collections.

The method operates on collections that could be modified concurrently. Consider using thread-safe collections or documenting thread-safety requirements.

-    Map<MavenDependencyAdapterMapping, Artifact> adapterMatches = new HashMap<>();
+    Map<MavenDependencyAdapterMapping, Artifact> adapterMatches = new ConcurrentHashMap<>();
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfigTest.java (6)

51-54: Consider enhancing class-level documentation.

While the class has proper author and version documentation, it would be beneficial to add a brief description of what this test class verifies, especially given its role in the new version range feature.


112-113: Document the expected number of configurations.

The assertion expects exactly 18 remote configurations. This magic number should be documented to explain why this specific number is expected.


72-99: Consider extracting mock setup into helper methods.

The mock setup for version resolution is complex and nested. Consider extracting this into helper methods like mockVersionResolution() and mockMavenSession() to improve readability and reusability.

Example helper method:

private void mockVersionResolution(KouplelessBaseBuildPrePackageMojo mojo) {
    RepositorySystem repositorySystem = mock(RepositorySystem.class);
    VersionRangeResult rangeResult = mock(VersionRangeResult.class);
    // ... rest of the mock setup
    mojo.repositorySystem = repositorySystem;
}

180-182: Document the assertion expectation.

The assertion expects exactly 3 matches. Add a comment explaining why 3 matches are expected (one from each config type: custom, remote, and default).


185-191: Consider adding parameter validation.

The helper method could be more robust by adding null checks for the input parameters.

 private Dependency mockDependency(String groupId, String artifactId, String version) {
+    Objects.requireNonNull(groupId, "groupId must not be null");
+    Objects.requireNonNull(artifactId, "artifactId must not be null");
+    Objects.requireNonNull(version, "version must not be null");
     Dependency dependency = new Dependency();
     dependency.setGroupId(groupId);
     dependency.setArtifactId(artifactId);
     dependency.setVersion(version);
     return dependency;
 }

55-192: Consider enhancing test coverage for version ranges.

While the test class provides good coverage of the basic functionality, consider adding the following test scenarios to ensure robust version range support:

  1. Test cases for different version range notations ([1.0,2.0), [1.0,2.0], (,1.0], [2.0,))
  2. Edge cases for version resolution
  3. Error cases for invalid version ranges
  4. Integration test for the complete version resolution flow

This will help ensure the reliability of the new version range feature.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfigTest.java (1)

75-85: Improve helper method robustness and documentation

The mock helper method could be enhanced for better maintainability and reliability:

  1. Add input validation
  2. Add Javadoc documentation
  3. Consider using a builder pattern

Here's the suggested improvement:

/**
 * Creates a mock Maven artifact with the specified properties.
 *
 * @param groupId    The group ID of the artifact (required)
 * @param artifactId The artifact ID (required)
 * @param version    The version string (required)
 * @param classifier The classifier (optional)
 * @param type      The artifact type (optional)
 * @return A mock Artifact instance
 * @throws IllegalArgumentException if required parameters are null or empty
 */
private Artifact mockArtifact(String groupId, String artifactId, String version,
                            String classifier, String type) {
    if (groupId == null || groupId.trim().isEmpty()) {
        throw new IllegalArgumentException("groupId is required");
    }
    if (artifactId == null || artifactId.trim().isEmpty()) {
        throw new IllegalArgumentException("artifactId is required");
    }
    if (version == null || version.trim().isEmpty()) {
        throw new IllegalArgumentException("version is required");
    }

    Artifact artifact = mock(Artifact.class);
    doReturn(groupId.trim()).when(artifact).getGroupId();
    doReturn(artifactId.trim()).when(artifact).getArtifactId();
    doReturn(version.trim()).when(artifact).getBaseVersion();
    doReturn(version.trim()).when(artifact).getVersion();
    doReturn(classifier).when(artifact).getClassifier();
    doReturn(type).when(artifact).getType();
    return artifact;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 26c4a87 and 0452ba3.

⛔ Files ignored due to path filters (1)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/koupleless-adapter-configs-1.2.3.jar is excluded by !**/*.jar
📒 Files selected for processing (10)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (5 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java (2 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (5 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java (0 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfigTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfigTest.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/utils/ReflectionUtils.java (1 hunks)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/mockBaseDir/conf/ark/adapter-mapping.yaml (1 hunks)
💤 Files with no reviewable changes (1)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/TestAdapterFile.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfig.java
🧰 Additional context used
🪛 yamllint (1.35.1)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/mockBaseDir/conf/ark/adapter-mapping.yaml

[error] 8-8: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (8)
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/resources/mockBaseDir/conf/ark/adapter-mapping.yaml (1)

6-6: Clarify version range syntax documentation

The version range syntax "(,)" appears to mean "match any version" but differs from the documented patterns in the PR description. Consider using a more explicit syntax that aligns with the documented formats:

  • [1.0,2.0) - from 1.0 (inclusive) to 2.0 (exclusive)
  • [1.0,2.0] - from 1.0 to 2.0 (inclusive)
  • (,1.0] - less than or equal to 1.0
  • [2.0,) - greater than or equal to 2.0

If "(,)" is intended to be a wildcard matcher, please document this special case.

✅ Verification successful

Version range syntax "(,)" is a valid wildcard pattern

Based on the search results from the default adapter mappings, the syntax "(,)" is consistently used as a wildcard pattern alongside other specific version ranges like [2.5.1,2.7.14], [3.2.0,), etc. The pattern appears twice in the default mappings, indicating it's an intentional and supported syntax for matching any version.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other version range patterns in the codebase for consistency
rg -g '*.{yaml,yml,xml}' 'versionRange:' -A 1

Length of output: 5711

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java (1)

49-55: ⚠️ Potential issue

Fix resource handling and improve error handling in loadConfig

The current implementation has several issues:

  1. Resource leak: InputStream is not properly closed
  2. Missing null check for resource stream
  3. No type safety in YAML loading

Apply this diff:

 private KouplelessAdapterConfig loadConfig() throws IOException {
-    InputStream mappingConfigIS = this.getClass().getClassLoader()
-        .getResourceAsStream(MAPPING_FILE);
-
-    Yaml yaml = new Yaml();
-    return yaml.loadAs(mappingConfigIS, KouplelessAdapterConfig.class);
+    try (InputStream mappingConfigIS = this.getClass().getClassLoader()
+        .getResourceAsStream(MAPPING_FILE)) {
+        if (mappingConfigIS == null) {
+            throw new IOException("Configuration file not found: " + MAPPING_FILE);
+        }
+        Yaml yaml = new Yaml();
+        return yaml.loadAs(mappingConfigIS, KouplelessAdapterConfig.class);
+    }
 }
koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojoTest.java (1)

Line range hint 19-52: LGTM: Import changes are appropriate

The new imports support the refactored code structure and are well-organized.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/KouplelessBaseBuildPrePackageMojo.java (1)

147-162: Handle InvalidVersionSpecificationException in getDependenciesByMatching

The method throws InvalidVersionSpecificationException without handling it, which could lead to unexpected behavior upstream.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfig.java (3)

20-35: LGTM! Clean implementation of class structure.

The class is well-organized with appropriate imports and Lombok annotations for reducing boilerplate code.

Also applies to: 44-48


76-78: Ensure 'version' is not null before setting adapter version

When setting the adapter's version, the version field might be null, leading to potential issues.


107-110: Handle potential PatternSyntaxException when compiling regex

If matcher.getRegexp() contains an invalid regular expression, Pattern.compile(regexp) may throw a PatternSyntaxException.

koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/KouplelessAdapterConfigTest.java (1)

67-70: Verify version range implementation and usage

The test introduces version range matching with the pattern [1.0.0,], but we should verify:

  1. The implementation handles all version range patterns mentioned in PR objectives
  2. The integration with Maven's version handling is correct
  3. The feature is used consistently across the codebase
✅ Verification successful

Let me gather more specific information about the version range implementation.


Let me check one final aspect about the version scheme implementation.


Version range implementation is properly integrated and validated

The implementation is well-structured and secure:

  • Uses Maven's GenericVersionScheme for version range parsing
  • Properly handles version range validation through ParseUtils
  • Includes error handling for invalid version specifications
  • Integrates with Maven's version resolution system
  • Test coverage includes version range validation scenarios
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify version range implementation and usage

# Check for version range pattern usage
echo "Checking version range patterns..."
rg -l '\[.*,.*\]|\(.*,.*\)|\[.*,.*\)|\(.*,.*\]' --type xml

# Check for version range related classes and tests
echo "Checking version range related files..."
rg -l 'versionRange|VersionRange' --type java

# Check for Maven version handling integration
echo "Checking Maven version handling..."
ast-grep --pattern 'class $_ implements VersionRange {
  $$$
}'

Length of output: 1554


Script:

#!/bin/bash
# Check the actual implementation of version range handling
echo "Checking version range implementation in MavenDependencyMatcher..."
rg -A 10 "versionRange" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/model/MavenDependencyMatcher.java

echo "Checking version range tests..."
rg -A 10 "versionRange" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/MatcherUtilsTest.java

echo "Checking ParseUtils implementation..."
rg -A 10 "versionRange" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java

Length of output: 2713


Script:

#!/bin/bash
# Check version scheme initialization and usage
echo "Checking version scheme initialization..."
rg -B 5 -A 2 "versionScheme" koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/main/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtils.java

# Check for any version range validation tests
echo "Checking version range validation tests..."
rg -A 10 "test.*version.*range" -i koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/

Length of output: 3884

try {
Field f = klass.getDeclaredField(fieldName);
f.setAccessible(true);
return (T) f.get(o);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add type safety check before casting.

The unchecked cast to T could lead to ClassCastException at runtime.

Apply this diff to add type safety:

-                return (T) f.get(o);
+                Object value = f.get(o);
+                try {
+                    return value != null ? (T) value : null;
+                } catch (ClassCastException e) {
+                    throw new IllegalArgumentException("Field '" + fieldName + "' is not of expected type", e);
+                }
📝 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.

Suggested change
return (T) f.get(o);
Object value = f.get(o);
try {
return value != null ? (T) value : null;
} catch (ClassCastException e) {
throw new IllegalArgumentException("Field '" + fieldName + "' is not of expected type", e);
}

Comment on lines +57 to +66
/**
* test for adaptor: koupleless-adapter-apollo-1.6
* matcher:
* groupId: com.ctrip.framework.apollo
* artifactId: apollo-client
* versionRange: "(,)"
* adapter:
* artifactId: koupleless-adapter-apollo-1.6
*/

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement test methods for version range matching

The class only contains documentation for test cases but lacks actual test implementations. Based on the PR objectives, we need test coverage for various version range patterns:

  • [x,y] (inclusive range)
  • (x,y) (exclusive range)
  • [x,y) (inclusive-exclusive range)
  • (x,y] (exclusive-inclusive range)
  • (,) (unbounded range)

Would you like me to help generate comprehensive test methods covering all these version range patterns? The implementation would include:

  1. Test methods for each version range pattern
  2. Edge cases and boundary testing
  3. Invalid version handling
  4. Proper assertions for adapter properties

Comment on lines 110 to +111
if (kouplelessAdapterConfig == null) {
InputStream mappingConfigIS = this.getClass().getClassLoader()
.getResourceAsStream(MAPPING_FILE);

kouplelessAdapterConfig = yamlMapper.readValue(mappingConfigIS,
KouplelessAdapterConfig.class);
kouplelessAdapterConfig = new CompositeKouplelessAdapterConfig(this);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for properties file loading

The initialization of properties could fail silently if the resource file is not found or properties are missing.

     void initKouplelessAdapterConfig() throws Exception {
         if (kouplelessAdapterConfig == null) {
             kouplelessAdapterConfig = new CompositeKouplelessAdapterConfig(this);
         }

         Properties properties = new Properties();
-        properties.load(getClass().getClassLoader().getResourceAsStream("project.properties"));
+        InputStream propertiesStream = getClass().getClassLoader().getResourceAsStream("project.properties");
+        if (propertiesStream == null) {
+            throw new IllegalStateException("Required project.properties file not found in classpath");
+        }
+        properties.load(propertiesStream);
+        
+        defaultGroupId = properties.getProperty("project.groupId");
+        defaultVersion = properties.getProperty("project.version");
+        
+        if (defaultGroupId == null || defaultVersion == null) {
+            throw new IllegalStateException("Required properties project.groupId and project.version must be defined");
+        }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +118 to +121
return StringUtils.equals(matcher.getGroupId(), artifact.getGroupId())
&& StringUtils.equals(matcher.getArtifactId(), artifact.getArtifactId()) && matcher
.getGenericVersionRange().containsVersion(parseVersion(artifact.getVersion()));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for version parsing.

The version parsing could fail silently. Consider adding explicit error handling for invalid version formats.

-        return StringUtils.equals(matcher.getGroupId(), artifact.getGroupId())
-               && StringUtils.equals(matcher.getArtifactId(), artifact.getArtifactId()) && matcher
-                   .getGenericVersionRange().containsVersion(parseVersion(artifact.getVersion()));
+        try {
+            return StringUtils.equals(matcher.getGroupId(), artifact.getGroupId())
+                   && StringUtils.equals(matcher.getArtifactId(), artifact.getArtifactId())
+                   && matcher.getGenericVersionRange().containsVersion(parseVersion(artifact.getVersion()));
+        } catch (IllegalArgumentException e) {
+            log.warn("Failed to parse version for artifact {}: {}", artifact, e.getMessage());
+            return false;
+        }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +107 to +110
String regexp = matcher.getRegexp();
String dependencyId = getArtifactFullId(artifact);
return Pattern.compile(regexp).matcher(dependencyId).matches();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Cache compiled patterns for better performance.

Compiling regular expressions is an expensive operation. Consider caching the compiled Pattern objects.

+    private static final Map<String, Pattern> PATTERN_CACHE = new ConcurrentHashMap<>();
+
     private boolean regexpMatches(MavenDependencyMatcher matcher,
                                   org.apache.maven.artifact.Artifact artifact) {
         if (null == matcher || null == matcher.getRegexp()) {
             return false;
         }
 
         String regexp = matcher.getRegexp();
         String dependencyId = getArtifactFullId(artifact);
-        return Pattern.compile(regexp).matcher(dependencyId).matches();
+        Pattern pattern = PATTERN_CACHE.computeIfAbsent(regexp, Pattern::compile);
+        return pattern.matcher(dependencyId).matches();
     }
📝 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.

Suggested change
String regexp = matcher.getRegexp();
String dependencyId = getArtifactFullId(artifact);
return Pattern.compile(regexp).matcher(dependencyId).matches();
}
private static final Map<String, Pattern> PATTERN_CACHE = new ConcurrentHashMap<>();
private boolean regexpMatches(MavenDependencyMatcher matcher,
org.apache.maven.artifact.Artifact artifact) {
if (null == matcher || null == matcher.getRegexp()) {
return false;
}
String regexp = matcher.getRegexp();
String dependencyId = getArtifactFullId(artifact);
Pattern pattern = PATTERN_CACHE.computeIfAbsent(regexp, Pattern::compile);
return pattern.matcher(dependencyId).matches();
}

Comment on lines +129 to +152
KouplelessAdapterConfig customConfig = mock(KouplelessAdapterConfig.class);
doReturn(asList(mockDependency("com.alipay.sofa", "customConfig", "1.0.0"),
mockDependency("com.alipay.sofa", "repeated", "1.0.0"))).when(customConfig)
.getCommonDependencies();
setField("customConfig", config, customConfig);

List<KouplelessAdapterConfig> remoteConfigs = getField("remoteConfigs", config);
KouplelessAdapterConfig remoteConfig = mock(KouplelessAdapterConfig.class);
remoteConfigs.add(remoteConfig);
doReturn(asList(mockDependency("com.alipay.sofa", "remoteConfig", "1.0.0"),
mockDependency("com.alipay.sofa", "repeated", "2.0.0"))).when(remoteConfig)
.getCommonDependencies();

KouplelessAdapterConfig defaultConfig = mock(KouplelessAdapterConfig.class);
doReturn(asList(mockDependency("com.alipay.sofa", "defaultConfig", "1.0.0"),
mockDependency("com.alipay.sofa", "repeated", "3.0.0"))).when(defaultConfig)
.getCommonDependencies();
setField("defaultConfig", config, defaultConfig);

List<Dependency> commonDependencies = config.getCommonDependencies();
assertEquals(4, commonDependencies.size());
assertEquals("1.0.0", commonDependencies.stream()
.filter(d -> d.getArtifactId().equals("repeated")).findFirst().get().getVersion());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Based on the evidence gathered, I can now provide the final response:

Additional test cases needed for version range functionality

While basic version range support exists, the current test coverage is incomplete. The following test scenarios are missing:

  • Version range parsing edge cases in ParseUtils.parseVersionRange() (e.g., invalid ranges, malformed syntax)
  • Version conflict resolution when multiple adapters specify overlapping version ranges
  • Version range resolution with complex constraints (e.g., [1.0,2.0), (,1.0],[1.2,))
  • Error handling for version range resolution failures

Suggested location for new tests:

  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/utils/ParseUtilsTest.java
  • koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/com/alipay/sofa/koupleless/base/build/plugin/model/CompositeKouplelessAdapterConfigTest.java
🔗 Analysis chain

Add test cases for version conflict resolution.

Given that this PR introduces version range support, it would be valuable to add specific test cases that verify:

  1. Version range parsing
  2. Version conflict resolution when ranges overlap
  3. Invalid version range handling

Let me check the content of these test files to see if they already cover version range testing or if we need additional test cases.


Let me check the implementation of version range parsing and conflict resolution to better understand what's already covered.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any version range related tests in the codebase
rg -l "versionRange|version range" --type java

Length of output: 835


Script:

#!/bin/bash
# Check the content of test files for version range related tests
rg "versionRange|version range" -B 2 -A 5 --type java koupleless-ext/koupleless-build-plugin/koupleless-base-build-plugin/src/test/java/

Length of output: 6669


Script:

#!/bin/bash
# Check implementation of version range parsing and conflict resolution
ast-grep --pattern 'class MavenDependencyMatcher {
  $$$
}'

rg "parseVersionRange|resolveVersion" -B 2 -A 5 --type java

Length of output: 10035

Comment on lines +38 to +73
public void testMatches() throws InvalidVersionSpecificationException {
KouplelessAdapterConfig config = new KouplelessAdapterConfig();

// init dependency
Dependency dependency = new Dependency();
dependency.setArtifactId("YYY");
dependency.setGroupId("XXX");
dependency.setVersion("1.0.0");

// init artifacts
List<Artifact> artifacts = new ArrayList<>();
Artifact regexpArtifact = mockArtifact("groupId", "regexpArtifactId", "1.0.0", "classifier",
"type");
Artifact versionRangeArtifact = mockArtifact("groupId", "versionRangeArtifactId", "1.0.0",
null, null);
artifacts.add(regexpArtifact);
artifacts.add(versionRangeArtifact);

// match null
assertEquals(0, config.matches(artifacts).size());

// match with regexp
MavenDependencyAdapterMapping regexpMapping = MavenDependencyAdapterMapping.builder()
.matcher(MavenDependencyMatcher.builder().regexp(".*regexpArtifactId:1.*").build())
.adapter(dependency).build();
config.setAdapterMappings(Collections.singletonList(regexpMapping));
assertEquals(1, config.matches(artifacts).size());

// match with versionRange
MavenDependencyAdapterMapping versionRangeMapping = MavenDependencyAdapterMapping.builder()
.matcher(MavenDependencyMatcher.builder().groupId("groupId")
.artifactId("versionRangeArtifactId").versionRange("[1.0.0,]").build())
.adapter(dependency).build();
config.setAdapterMappings(Collections.singletonList(versionRangeMapping));
assertEquals(1, config.matches(artifacts).size());
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance test coverage and maintainability

While the test covers basic functionality, consider these improvements:

  1. Split into separate test methods for better isolation:

    • testMatchesWithNoMapping()
    • testMatchesWithRegexp()
    • testMatchesWithVersionRange()
  2. Add assertions to verify the matched content:

    • Check properties of matched artifacts
    • Verify adapter configuration
  3. Add negative test cases:

    • Non-matching version ranges
    • Invalid regular expressions
    • Null/empty inputs
  4. Use constants for test data:

    • Version strings
    • Artifact IDs
    • Regular expressions

Here's an example of how to restructure:

private static final String TEST_GROUP_ID = "groupId";
private static final String TEST_VERSION = "1.0.0";

@Test
public void testMatchesWithNoMapping() {
    KouplelessAdapterConfig config = new KouplelessAdapterConfig();
    List<Artifact> artifacts = createTestArtifacts();
    assertEquals(0, config.matches(artifacts).size());
}

@Test
public void testMatchesWithRegexp() {
    KouplelessAdapterConfig config = new KouplelessAdapterConfig();
    List<Artifact> artifacts = createTestArtifacts();
    
    MavenDependencyAdapterMapping mapping = createRegexpMapping();
    config.setAdapterMappings(Collections.singletonList(mapping));
    
    List<Artifact> matches = config.matches(artifacts);
    assertEquals(1, matches.size());
    assertMatchedArtifact(matches.get(0), "regexpArtifactId");
}

private void assertMatchedArtifact(Artifact artifact, String expectedArtifactId) {
    assertEquals(TEST_GROUP_ID, artifact.getGroupId());
    assertEquals(expectedArtifactId, artifact.getArtifactId());
    assertEquals(TEST_VERSION, artifact.getVersion());
}

*/
package com.alipay.sofa.koupleless.base.build.plugin.model;

import edu.emory.mathcs.backport.java.util.Collections;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace deprecated Collections backport import

The edu.emory.mathcs.backport.java.util.Collections is deprecated and meant for older Java versions. Replace it with the standard Java Collections:

-import edu.emory.mathcs.backport.java.util.Collections;
+import java.util.Collections;
📝 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.

Suggested change
import edu.emory.mathcs.backport.java.util.Collections;
import java.util.Collections;

Copy link

codecov bot commented Dec 1, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 72.68%. Comparing base (7870126) to head (3e29dcf).
Report is 10 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main     #211      +/-   ##
============================================
- Coverage     75.58%   72.68%   -2.91%     
  Complexity      189      189              
============================================
  Files            90      101      +11     
  Lines          2380     2621     +241     
  Branches        259      282      +23     
============================================
+ Hits           1799     1905     +106     
- Misses          449      575     +126     
- Partials        132      141       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@gaosaroma gaosaroma changed the title add versionRange for adaptor <feat> add versionRange for adaptor; support to customize adapter-mapping; support to install a few adapter Dec 2, 2024
Copy link
Contributor

@lvjing2 lvjing2 left a comment

Choose a reason for hiding this comment

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

尽量不增加 action,其他 ok 的

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
.github/workflows/koupleless_runtime_release_2.1.x.yml (2)

Line range hint 134-146: Improve XML parsing robustness and simplify array usage

The current implementation has two concerns:

  1. Using grep/sed for XML parsing is fragile
  2. Maintaining both string and array versions of the module list is redundant

Consider this improved implementation:

- modules_in_right_jdk=""
- modules_in_right_jdk_array=()
+ modules_in_right_jdk=()
  for module in "${modules[@]}"; do
-   jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
+   # Use xmllint for robust XML parsing
+   jdk_version=$(xmllint --xpath "string(//java.version/text())" $module/pom.xml)
    echo "${module} JDK version: ${jdk_version}"
    
    if [[ "${jdk_version}" == "17" ]]; then
-     modules_in_right_jdk="${modules_in_right_jdk}${module},"
-     modules_in_right_jdk_array+=(${module})
+     modules_in_right_jdk+=(${module})
    fi
  done
🧰 Tools
🪛 yamllint (1.35.1)

[error] 146-146: trailing spaces

(trailing-spaces)


[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)


[error] 165-165: trailing spaces

(trailing-spaces)


[error] 172-172: trailing spaces

(trailing-spaces)


146-146: Remove trailing whitespace

There are trailing spaces on lines 146, 155, 159, 165, and 172.

Consider using an editor configuration or git pre-commit hook to automatically trim trailing whitespace.

Also applies to: 155-155, 159-159, 165-165, 172-172

🧰 Tools
🪛 yamllint (1.35.1)

[error] 146-146: trailing spaces

(trailing-spaces)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0452ba3 and 3e29dcf.

📒 Files selected for processing (2)
  • .github/workflows/koupleless_runtime_release_2.1.x.yml (2 hunks)
  • .github/workflows/koupleless_runtime_snapshot_2.1.x.yml (1 hunks)
🧰 Additional context used
🪛 yamllint (1.35.1)
.github/workflows/koupleless_runtime_release_2.1.x.yml

[error] 146-146: trailing spaces

(trailing-spaces)


[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)


[error] 165-165: trailing spaces

(trailing-spaces)


[error] 172-172: trailing spaces

(trailing-spaces)

.github/workflows/koupleless_runtime_snapshot_2.1.x.yml

[error] 141-141: trailing spaces

(trailing-spaces)


[error] 150-150: trailing spaces

(trailing-spaces)


[error] 154-154: trailing spaces

(trailing-spaces)


[error] 160-160: trailing spaces

(trailing-spaces)


[error] 167-167: trailing spaces

(trailing-spaces)

🔇 Additional comments (4)
.github/workflows/koupleless_runtime_release_2.1.x.yml (1)

147-164: ⚠️ Potential issue

Improve version extraction and comparison robustness

The current implementation uses grep/sed for parsing both XML and YAML files, which is fragile and prone to errors.

As previously suggested, consider using proper parsers:

- adapter_release_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
+ adapter_release_version=$(xmllint --xpath "string(//revision/text())" pom.xml)

  for module in "${modules_in_right_jdk_array[@]}"; do
    if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
      continue
    fi

-   adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
+   # Use yq for YAML parsing
+   adapter_version=$(yq eval '.version' "$module/conf/adapter-mapping.yaml")
    if [[ -z "$adapter_version" ]]; then
      echo "Warning: Failed to parse version from $module/conf/adapter-mapping.yaml"
      continue
    fi
🧰 Tools
🪛 yamllint (1.35.1)

[error] 155-155: trailing spaces

(trailing-spaces)


[error] 159-159: trailing spaces

(trailing-spaces)

.github/workflows/koupleless_runtime_snapshot_2.1.x.yml (3)

130-140: ⚠️ Potential issue

Improve robustness of JDK version extraction

The current approach using grep for XML parsing is fragile and could lead to incorrect version extraction.

Apply this diff to improve reliability:

 modules_in_right_jdk_array=()
 for module in "${modules[@]}"; do
-  # 读取模块中的 pom.xml 来确定 JDK 版本
-  jdk_version=$(grep -m 1 '<java.version>' $module/pom.xml | sed 's/<[^>]*>//g' | xargs)
+  # Read module's pom.xml to determine JDK version
+  pom_file="$module/pom.xml"
+  if [[ ! -f "$pom_file" ]]; then
+    echo "Warning: $pom_file not found, skipping module"
+    continue
+  fi
+  jdk_version=$(xmllint --xpath "string(//*[local-name()='java.version']/text())" "$pom_file" 2>/dev/null)
+  if [[ -z "$jdk_version" ]]; then
+    echo "Warning: Failed to extract JDK version from $pom_file"
+    continue
+  fi
   echo "${module} JDK version: ${jdk_version}"

   # 如果是目标 jdk 版本,则记录
   if [[ "${jdk_version}" == "17" ]]; then
-    modules_in_right_jdk_array+=(${module})
+    modules_in_right_jdk_array+=("$module")
   fi
 done

142-165: ⚠️ Potential issue

Improve version matching and module selection reliability

The current implementation has several issues:

  1. String concatenation for module list is error-prone
  2. YAML parsing with grep is unreliable
  3. Missing version format validation
  4. Contains trailing spaces

Apply this diff to improve the implementation:

-# 过滤出需要发布的 adapter,过滤条件:adapter 版本与 pom.xml 中的版本一致
-adapter_snapshot_version=$(grep '<revision>' pom.xml | sed -e 's/.*<revision>\(.*\)<\/revision>.*/\1/' | tr -d ' ')
-modules_in_snapshot_version=""
+# Filter adapters to be released based on version match with pom.xml
+adapter_snapshot_version=$(xmllint --xpath "string(//*[local-name()='revision']/text())" pom.xml 2>/dev/null)
+if [[ -z "$adapter_snapshot_version" ]]; then
+  echo "Error: Failed to extract snapshot version from pom.xml"
+  exit 1
+fi
+
+declare -a modules_to_release
 
 for module in "${modules_in_right_jdk_array[@]}"; do
-  # 如果没有 adapter-mapping.yaml,则跳过( koupleless-adapter-configs 没有 adapter-mapping.yaml)
-  if [[ ! -f $module/conf/adapter-mapping.yaml ]]; then
+  yaml_file="$module/conf/adapter-mapping.yaml"
+  if [[ ! -f "$yaml_file" ]]; then
+    echo "Info: $yaml_file not found, skipping module (expected for koupleless-adapter-configs)"
     continue
   fi
 
-  # 读取模块中的 adapter-mapping.yaml 来确定 adapter 版本
-  adapter_version=$(grep 'version:' $module/conf/adapter-mapping.yaml | sed -e 's/.*version:\(.*\)/\1/' | tr -d ' ')
+  # Use yq for proper YAML parsing
+  if ! adapter_version=$(yq e '.version' "$yaml_file" 2>/dev/null); then
+    echo "Error: Failed to parse version from $yaml_file"
+    continue
+  fi
   echo "${module} adapter version: ${adapter_version}"
 
-  # 如果是目标 adapter 版本,则记录
+  # Validate version format
+  if [[ ! $adapter_version =~ ^[0-9]+\.[0-9]+\.[0-9]+(-SNAPSHOT)?$ ]]; then
+    echo "Error: Invalid version format in $yaml_file: $adapter_version"
+    continue
+  fi
+
   if [[ "${adapter_version}" == "${adapter_snapshot_version}" ]]; then
-    modules_in_snapshot_version="${modules_in_snapshot_version}${module},"
+    modules_to_release+=("$module")
   fi
 done
 
-if [[ -n ${modules_in_snapshot_version} ]]; then
-  modules_in_snapshot_version="${modules_in_snapshot_version:0:-1}"
-  echo "release for module ${modules_in_snapshot_version}"
-  mvn --batch-mode deploy -Psnapshot -pl ${modules_in_snapshot_version} -am -amd -B -U
-  echo "release completed for module ${modules_in_snapshot_version}"
+if (( ${#modules_to_release[@]} > 0 )); then
+  modules_list=$(IFS=,; echo "${modules_to_release[*]}")
+  echo "Releasing modules: ${modules_list}"
+  mvn --batch-mode deploy -Psnapshot -pl "${modules_list}" -am -amd -B -U
+  echo "Release completed for modules: ${modules_list}"
 fi
🧰 Tools
🪛 yamllint (1.35.1)

[error] 150-150: trailing spaces

(trailing-spaces)


[error] 154-154: trailing spaces

(trailing-spaces)


[error] 160-160: trailing spaces

(trailing-spaces)


168-169: Verify deployment order dependencies

The comment indicates that koupleless-adapter-configs must be deployed after all JDK8 and JDK17 adapters. However, this workflow only handles JDK17 adapters, and there's no verification that JDK8 adapters have been deployed.

Run this script to verify the deployment order:

Consider adding a verification step or dependency on the JDK8 workflow to ensure proper ordering.

Comment on lines +165 to +174

if [[ -n ${modules_in_release_version} ]]; then
modules_in_release_version="${modules_in_release_version:0:-1}"
echo "release for module ${modules_in_release_version}"
mvn --batch-mode deploy -Prelease -pl ${modules_in_release_version} -am -amd -B -U
echo "release completed for module ${modules_in_release_version}"
fi

# 请在发布 koupleless-adapter-configs 之前,发布 jdk8 和 jdk17 所有的 koupleless-adapters
mvn --batch-mode deploy -Prelease -pl koupleless-adapter-configs -am -amd -B -U
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance release process robustness and dependency management

The release process has several areas for improvement:

  1. The release order dependency (JDK8 and JDK17 adapters before koupleless-adapter-configs) is documented but not enforced
  2. No error handling for Maven deployment failures

Consider these improvements:

- if [[ -n ${modules_in_release_version} ]]; then
-   modules_in_release_version="${modules_in_release_version:0:-1}"
-   echo "release for module ${modules_in_release_version}"
-   mvn --batch-mode deploy -Prelease -pl ${modules_in_release_version} -am -amd -B -U
+ # Function to handle Maven deployment
+ deploy_modules() {
+   local modules="$1"
+   local description="$2"
+   echo "Releasing ${description}: ${modules}"
+   if ! mvn --batch-mode deploy -Prelease -pl "${modules}" -am -amd -B -U; then
+     echo "Error: Failed to release ${description}"
+     exit 1
+   fi
+ }
+ 
+ # Release adapters first
+ if [[ -n ${modules_in_release_version[@]} ]]; then
+   modules_string=$(IFS=,; echo "${modules_in_release_version[*]}")
+   deploy_modules "${modules_string}" "adapters"
+ else
+   echo "Warning: No adapters found for release"
+   exit 1
+ fi
 
- # 请在发布 koupleless-adapter-configs 之前,发布 jdk8 和 jdk17 所有的 koupleless-adapters
- mvn --batch-mode deploy -Prelease -pl koupleless-adapter-configs -am -amd -B -U
+ # Release configs after adapters
+ deploy_modules "koupleless-adapter-configs" "adapter configs"
📝 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.

Suggested change
if [[ -n ${modules_in_release_version} ]]; then
modules_in_release_version="${modules_in_release_version:0:-1}"
echo "release for module ${modules_in_release_version}"
mvn --batch-mode deploy -Prelease -pl ${modules_in_release_version} -am -amd -B -U
echo "release completed for module ${modules_in_release_version}"
fi
# 请在发布 koupleless-adapter-configs 之前,发布 jdk8 和 jdk17 所有的 koupleless-adapters
mvn --batch-mode deploy -Prelease -pl koupleless-adapter-configs -am -amd -B -U
# Function to handle Maven deployment
deploy_modules() {
local modules="$1"
local description="$2"
echo "Releasing ${description}: ${modules}"
if ! mvn --batch-mode deploy -Prelease -pl "${modules}" -am -amd -B -U; then
echo "Error: Failed to release ${description}"
exit 1
fi
}
# Release adapters first
if [[ -n ${modules_in_release_version[@]} ]]; then
modules_string=$(IFS=,; echo "${modules_in_release_version[*]}")
deploy_modules "${modules_string}" "adapters"
else
echo "Warning: No adapters found for release"
exit 1
fi
# Release configs after adapters
deploy_modules "koupleless-adapter-configs" "adapter configs"
🧰 Tools
🪛 yamllint (1.35.1)

[error] 165-165: trailing spaces

(trailing-spaces)


[error] 172-172: trailing spaces

(trailing-spaces)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants