diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 1951157..f122d22 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Set up JDK 21 uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 @@ -65,7 +65,7 @@ jobs: ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.ORG_GRADLE_PROJECT_SONATYPEPASSWORD }} steps: - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Set up JDK 21 uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 diff --git a/README.md b/README.md index 2308136..8134ae8 100644 --- a/README.md +++ b/README.md @@ -38,20 +38,20 @@ To install the library, add the following lines to your build config file. io.qdrant client - 1.18.2 + 1.18.3 ``` #### SBT ```sbt -libraryDependencies += "io.qdrant" % "client" % "1.18.2" +libraryDependencies += "io.qdrant" % "client" % "1.18.3" ``` #### Gradle ```gradle -implementation 'io.qdrant:client:1.18.2' +implementation 'io.qdrant:client:1.18.3' ``` > [!NOTE] diff --git a/example/build.gradle b/example/build.gradle index 4a1a172..1952c13 100644 --- a/example/build.gradle +++ b/example/build.gradle @@ -13,7 +13,7 @@ repositories { dependencies { // Qdrant Java client - implementation 'io.qdrant:client:1.18.2' + implementation 'io.qdrant:client:1.18.3' // gRPC dependencies - use the same version as Qdrant client implementation 'io.grpc:grpc-netty-shaded:1.65.1' diff --git a/gradle.properties b/gradle.properties index 82672dd..dc0b8fe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,4 +5,4 @@ qdrantProtosVersion=v1.18.0 qdrantVersion=v1.18.0 # The version of the client to generate -packageVersion=1.18.2 +packageVersion=1.18.3 diff --git a/src/main/java/io/qdrant/client/QdrantGrpcClient.java b/src/main/java/io/qdrant/client/QdrantGrpcClient.java index 67a23d7..5db3425 100644 --- a/src/main/java/io/qdrant/client/QdrantGrpcClient.java +++ b/src/main/java/io/qdrant/client/QdrantGrpcClient.java @@ -273,16 +273,16 @@ public Builder withHeaders(Map headers) { * @return a new instance of {@link QdrantGrpcClient} */ public QdrantGrpcClient build() { - if (checkCompatibility) { - String clientVersion = Builder.class.getPackage().getImplementationVersion(); - checkVersionsCompatibility(clientVersion); - } - CallCredentials credentials = this.callCredentials; if (credentials == null && (apiKey != null || headers != null)) { credentials = new MetadataCredentials(apiKey, headers); } + if (checkCompatibility) { + String clientVersion = Builder.class.getPackage().getImplementationVersion(); + checkVersionsCompatibility(clientVersion, credentials); + } + return new QdrantGrpcClient(channel, shutdownChannelOnClose, credentials, timeout); } @@ -301,11 +301,12 @@ private static ManagedChannel createChannel( return channelBuilder.build(); } - private void checkVersionsCompatibility(String clientVersion) { + private void checkVersionsCompatibility( + String clientVersion, @Nullable CallCredentials credentials) { try { String serverVersion = QdrantGrpc.newBlockingStub(this.channel) - .withCallCredentials(this.callCredentials) + .withCallCredentials(credentials) .healthCheck(QdrantOuterClass.HealthCheckRequest.getDefaultInstance()) .getVersion(); if (!VersionsCompatibilityChecker.isCompatible(clientVersion, serverVersion)) { diff --git a/src/test/java/io/qdrant/client/QdrantGrpcClientCompatibilityTest.java b/src/test/java/io/qdrant/client/QdrantGrpcClientCompatibilityTest.java new file mode 100644 index 0000000..e54fe92 --- /dev/null +++ b/src/test/java/io/qdrant/client/QdrantGrpcClientCompatibilityTest.java @@ -0,0 +1,55 @@ +package io.qdrant.client; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import io.grpc.CallCredentials; +import io.grpc.ManagedChannel; +import io.qdrant.client.grpc.QdrantGrpc; +import io.qdrant.client.grpc.QdrantOuterClass; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.MockedStatic; + +/** + * Unit tests for the version compatibility check performed by {@link + * QdrantGrpcClient.Builder#build()}. + */ +class QdrantGrpcClientCompatibilityTest { + + @Test + void compatibility_check_uses_api_key_credentials_from_with_api_key() { + ManagedChannel channel = mock(ManagedChannel.class); + QdrantGrpc.QdrantBlockingStub stub = mock(QdrantGrpc.QdrantBlockingStub.class); + QdrantOuterClass.HealthCheckReply reply = + QdrantOuterClass.HealthCheckReply.newBuilder() + .setTitle("qdrant") + .setVersion("1.0.0") + .build(); + + try (MockedStatic grpc = mockStatic(QdrantGrpc.class)) { + grpc.when(() -> QdrantGrpc.newBlockingStub(any())).thenReturn(stub); + when(stub.withCallCredentials(any())).thenReturn(stub); + when(stub.healthCheck(any())).thenReturn(reply); + + QdrantGrpcClient client = + QdrantGrpcClient.newBuilder(channel, false, true).withApiKey("my-api-key").build(); + client.close(); + + ArgumentCaptor credentialsCaptor = + ArgumentCaptor.forClass(CallCredentials.class); + verify(stub).withCallCredentials(credentialsCaptor.capture()); + + CallCredentials usedCredentials = credentialsCaptor.getValue(); + assertNotNull( + usedCredentials, + "Version compatibility check must run with the API key credentials, not null"); + assertInstanceOf(MetadataCredentials.class, usedCredentials); + } + } +}