]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-21121 Add GitLab provisioning ITs for groups and groups membership
authorAurelien Poscia <aurelien.poscia@sonarsource.com>
Fri, 22 Dec 2023 07:39:03 +0000 (08:39 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 18 Jan 2024 20:03:23 +0000 (20:03 +0000)
17 files changed:
.cirrus.yml
server/sonar-alm-client/src/main/java/org/sonar/alm/client/gitlab/GsonId.java
server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GsonIdTest.java [new file with mode: 0644]
server/sonar-webserver-common/src/it/java/org/sonar/server/common/gitlab/config/GitlabConfigurationServiceIT.java
server/sonar-webserver-common/src/main/java/org/sonar/server/common/gitlab/config/GitlabConfigurationService.java
sonar-ws/src/main/java/org/sonarqube/ws/client/BaseService.java
sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/HttpConnector.java
sonar-ws/src/main/java/org/sonarqube/ws/client/RequestWithPayload.java
sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java
sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfiguration.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationService.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/package-info.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunService.java [new file with mode: 0644]
sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/package-info.java [new file with mode: 0644]
sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationServiceTest.java [new file with mode: 0644]
sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunServiceTest.java [new file with mode: 0644]

index 9caad464b91388a4665ef361ce92afe79ccd04aa..55f863729fe97d0f636bbcccde4196176c8c57f5 100644 (file)
@@ -106,8 +106,7 @@ gitlab_task_template: &IS_GITLAB_TASK_NEEDED >-
     'private/it-branch/it-tests/src/test/java/com/sonarsource/branch/it/suite/pr/gitlab/**/*.java',
     'private/core-extension-gitlab-vulnerability-report/src/main/**/*.java')
 
-gitlab_provisioning_task_template: &GITLAB_PROVISIONING_TASK_TEMPLATE
-  only_if: >-
+gitlab_provisioning_task_template: &IS_GITLAB_PROVISIONING_TASK_NEEDED >-
     $CIRRUS_BRANCH == $BRANCH_MAIN || $CIRRUS_BRANCH =~ $BRANCH_PATTERN_MAINTENANCE || $CIRRUS_BRANCH == $BRANCH_NIGHTLY ||
     changesInclude('private/core-extension-gitlab-provisioning/**/*.java')
 
@@ -623,9 +622,9 @@ qa_github_provisioning_task:
 qa_gitlab_provisioning_task:
   <<: *DEFAULT_TEMPLATE
   <<: *BUILD_DEPENDANT_TASK_TEMPLATE
-  <<: *GITLAB_PROVISIONING_TASK_TEMPLATE
   <<: *JAR_CACHE_TEMPLATE
   <<: *GRADLE_CACHE_TEMPLATE
+  only_if: *IS_GITLAB_PROVISIONING_TASK_NEEDED
   env:
     QA_CATEGORY: GITLAB_PROVISIONING
   matrix:
index 62e86a23c30f9c4bcf32f79fa7e3e6fb511d7c10..4291e6b20b71a70806d758a1f807d871b001a74f 100644 (file)
@@ -21,8 +21,12 @@ package org.sonar.alm.client.gitlab;
 
 import com.google.gson.Gson;
 import com.google.gson.annotations.SerializedName;
+import com.google.gson.reflect.TypeToken;
+import java.util.Collection;
 
 public class GsonId {
+  private static final TypeToken<Collection<GsonId>> COLLECTION_TYPE_TOKEN = new TypeToken<>() {
+  };
 
   @SerializedName("id")
   private final long id;
@@ -45,4 +49,9 @@ public class GsonId {
     return gson.fromJson(json, GsonId.class);
   }
 
+  public static Collection<GsonId> parseCollection(String json) {
+    Gson gson = new Gson();
+    return gson.fromJson(json, COLLECTION_TYPE_TOKEN);
+  }
+
 }
diff --git a/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GsonIdTest.java b/server/sonar-alm-client/src/test/java/org/sonar/alm/client/gitlab/GsonIdTest.java
new file mode 100644 (file)
index 0000000..0377f51
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.alm.client.gitlab;
+
+import java.util.Collection;
+import org.junit.Test;
+
+import static java.util.stream.Collectors.toSet;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GsonIdTest {
+
+  @Test
+  public void parseOne_whenSingleId_deserializesCorrectly() {
+    GsonId gsonId = GsonId.parseOne("""
+      {
+        "blu": "blue",
+        "id": "123",
+        "bla": "bli"
+      }
+      """);
+
+    assertThat(gsonId.getId()).isEqualTo(123);
+  }
+
+  @Test
+  public void parseCollection_whenMultipleIds_deserializeCorrectly() {
+    Collection<GsonId> gsonId = GsonId.parseCollection("""
+      [
+      {
+        "blu": "blue",
+        "id": "123",
+        "bla": "bli"
+      },
+              
+      {
+        "id": "456",
+        "bla": "bli"
+      }
+      ]
+      """);
+
+    assertThat(gsonId.stream().map(GsonId::getId).collect(toSet())).containsExactlyInAnyOrder(123L, 456L);
+  }
+
+}
index 6086c2cdcdd0e47cc193e60105c35fffcfeca46c..e50fffe47e6001e123c8852fc892b3c14b15eaa8 100644 (file)
@@ -39,6 +39,7 @@ import org.sonar.db.user.ExternalGroupDto;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.management.ManagedInstanceService;
+import org.sonar.server.setting.ThreadLocalSettings;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@@ -82,6 +83,9 @@ public class GitlabConfigurationServiceIT {
   @Mock
   private GitlabGlobalSettingsValidator gitlabGlobalSettingsValidator;
 
+  @Mock
+  private ThreadLocalSettings threadLocalSettings;
+
   private GitlabConfigurationService gitlabConfigurationService;
 
   @Before
@@ -90,7 +94,8 @@ public class GitlabConfigurationServiceIT {
     gitlabConfigurationService = new GitlabConfigurationService(
       dbTester.getDbClient(),
       managedInstanceService,
-      gitlabGlobalSettingsValidator);
+      gitlabGlobalSettingsValidator,
+      threadLocalSettings);
   }
 
   @Test
index 0f2fbaf88fd491e7f5ef2d9733f2105de24ebb61..5df75318455c08ad782fee50efb46cc7adc269fc 100644 (file)
@@ -36,6 +36,7 @@ import org.sonar.server.common.UpdatedValue;
 import org.sonar.server.exceptions.BadRequestException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.management.ManagedInstanceService;
+import org.sonar.server.setting.ThreadLocalSettings;
 
 import static java.lang.String.format;
 import static org.apache.commons.lang.StringUtils.isNotBlank;
@@ -73,12 +74,14 @@ public class GitlabConfigurationService {
   private final DbClient dbClient;
   private final ManagedInstanceService managedInstanceService;
   private final GitlabGlobalSettingsValidator gitlabGlobalSettingsValidator;
+  private final ThreadLocalSettings threadLocalSettings;
 
   public GitlabConfigurationService(DbClient dbClient,
-    ManagedInstanceService managedInstanceService, GitlabGlobalSettingsValidator gitlabGlobalSettingsValidator) {
+    ManagedInstanceService managedInstanceService, GitlabGlobalSettingsValidator gitlabGlobalSettingsValidator, ThreadLocalSettings threadLocalSettings) {
     this.dbClient = dbClient;
     this.managedInstanceService = managedInstanceService;
     this.gitlabGlobalSettingsValidator = gitlabGlobalSettingsValidator;
+    this.threadLocalSettings = threadLocalSettings;
   }
 
   public GitlabConfiguration updateConfiguration(UpdateGitlabConfigurationRequest updateRequest) {
@@ -112,6 +115,7 @@ public class GitlabConfigurationService {
     value
       .map(definedValue -> new PropertyDto().setKey(propertyName).setValue(definedValue))
       .applyIfDefined(property -> dbClient.propertiesDao().saveProperty(dbSession, property));
+    threadLocalSettings.setProperty(propertyName, value.orElse(null));
   }
 
   private void deleteExternalGroupsWhenDisablingAutoProvisioning(
index 6ad3ac60fbe141b401812bb6007e6d7a589c3c47..f7817e66acfa02be9ea647e23ccb09937038da02 100644 (file)
@@ -31,6 +31,7 @@ import static org.sonarqube.ws.WsUtils.checkArgument;
 import static org.sonarqube.ws.WsUtils.isNullOrEmpty;
 
 public abstract class BaseService {
+  protected static final String APPLICATION_MERGE_PATCH_JSON = "application/merge-patch+json";
 
   private final WsConnector wsConnector;
   protected final String controller;
@@ -64,6 +65,10 @@ public abstract class BaseService {
     }
   }
 
+  protected String path() {
+    return controller;
+  }
+
   protected String path(String action) {
     return String.format("%s/%s", controller, action);
   }
index bd9a14eb95b56467b3c7ea09bee4210890e2ac41..4ca293f2dd599d7d2a7b32c2622b0bd87cb55fbc 100644 (file)
@@ -36,6 +36,8 @@ import org.sonarqube.ws.client.emails.EmailsService;
 import org.sonarqube.ws.client.favorites.FavoritesService;
 import org.sonarqube.ws.client.github.provisioning.permissions.GithubPermissionsService;
 import org.sonarqube.ws.client.githubprovisioning.GithubProvisioningService;
+import org.sonarqube.ws.client.gitlab.configuration.GitlabConfigurationService;
+import org.sonarqube.ws.client.gitlab.synchronization.run.GitlabSynchronizationRunService;
 import org.sonarqube.ws.client.governancereports.GovernanceReportsService;
 import org.sonarqube.ws.client.hotspots.HotspotsService;
 import org.sonarqube.ws.client.issues.IssuesService;
@@ -144,6 +146,9 @@ class DefaultWsClient implements WsClient {
   private final SonarLintServerPushService sonarLintPushService;
   private final GithubProvisioningService githubProvisioningService;
   private final GithubPermissionsService githubPermissionsService;
+  private final GitlabConfigurationService gitlabConfigurationService;
+
+  private final GitlabSynchronizationRunService gitlabSynchronizationRunService;
 
   DefaultWsClient(WsConnector wsConnector) {
     this.wsConnector = wsConnector;
@@ -204,6 +209,8 @@ class DefaultWsClient implements WsClient {
     this.regulatoryReportsService = new RegulatoryReportsService(wsConnector);
     this.githubProvisioningService = new GithubProvisioningService(wsConnector);
     this.githubPermissionsService = new GithubPermissionsService(wsConnector);
+    this.gitlabConfigurationService = new GitlabConfigurationService(wsConnector);
+    this.gitlabSynchronizationRunService = new GitlabSynchronizationRunService(wsConnector);
   }
 
   @Override
@@ -287,6 +294,16 @@ class DefaultWsClient implements WsClient {
     return githubPermissionsService;
   }
 
+  @Override
+  public GitlabConfigurationService gitlabConfigurationService() {
+    return gitlabConfigurationService;
+  }
+
+  @Override
+  public GitlabSynchronizationRunService gitlabSynchronizationRunService() {
+    return gitlabSynchronizationRunService;
+  }
+
   @Override
   public GovernanceReportsService governanceReports() {
     return governanceReportsService;
index e61a331126e726de597d999da8210789d1df4107..fcf4cd991d4df4293da6591987cbea8734b5a580 100644 (file)
@@ -57,7 +57,7 @@ public class HttpConnector implements WsConnector {
 
   public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30_000;
   public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60_000;
-  private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+  private static final String JSON = "application/json; charset=utf-8";
 
   /**
    * Base URL with trailing slash, for instance "https://localhost/sonarqube/".
@@ -134,7 +134,8 @@ public class HttpConnector implements WsConnector {
     RequestBody body;
     Map<String, Part> parts = request.getParts();
     if (request.hasBody()) {
-      body = RequestBody.create(JSON, request.getBody());
+      MediaType contentType = MediaType.parse(request.getContentType().orElse(JSON));
+      body = RequestBody.create(contentType, request.getBody());
     } else if (parts.isEmpty()) {
       // parameters are defined in the body (application/x-www-form-urlencoded)
       FormBody.Builder formBody = new FormBody.Builder();
index b78dcdd1c64898617e380af4ae20d886bbd2ad4b..a85b0bf077a2b1023003ebc67eee654b3598378d 100644 (file)
@@ -22,6 +22,7 @@ package org.sonarqube.ws.client;
 import java.io.File;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.function.Function;
 import okhttp3.Request;
 import okhttp3.RequestBody;
@@ -32,6 +33,7 @@ import okhttp3.RequestBody;
 public abstract class RequestWithPayload<T extends RequestWithPayload<T>> extends BaseRequest<RequestWithPayload<T>> {
 
   private String body;
+  private String contentType = null;
   private final Map<String, Part> parts = new LinkedHashMap<>();
 
   protected RequestWithPayload(String path) {
@@ -51,6 +53,15 @@ public abstract class RequestWithPayload<T extends RequestWithPayload<T>> extend
     return this.body != null;
   }
 
+  public T setContentType(String contentType) {
+    this.contentType = contentType;
+    return (T) this;
+  }
+
+  public Optional<String> getContentType() {
+    return Optional.ofNullable(contentType);
+  }
+
   public T setPart(String name, Part part) {
     this.parts.put(name, part);
     return (T) this;
index f805faebbeec776b1723a9d7808f792894964c45..aee175fb7a34f3825502ae3c97c9ea814e6ed995 100644 (file)
@@ -36,6 +36,8 @@ import org.sonarqube.ws.client.emails.EmailsService;
 import org.sonarqube.ws.client.favorites.FavoritesService;
 import org.sonarqube.ws.client.github.provisioning.permissions.GithubPermissionsService;
 import org.sonarqube.ws.client.githubprovisioning.GithubProvisioningService;
+import org.sonarqube.ws.client.gitlab.configuration.GitlabConfigurationService;
+import org.sonarqube.ws.client.gitlab.synchronization.run.GitlabSynchronizationRunService;
 import org.sonarqube.ws.client.governancereports.GovernanceReportsService;
 import org.sonarqube.ws.client.hotspots.HotspotsService;
 import org.sonarqube.ws.client.issues.IssuesService;
@@ -128,6 +130,10 @@ public interface WsClient {
 
   GithubPermissionsService githubPermissionsService();
 
+  GitlabConfigurationService gitlabConfigurationService();
+
+  GitlabSynchronizationRunService gitlabSynchronizationRunService();
+
   GovernanceReportsService governanceReports();
 
   HotspotsService hotspots();
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfiguration.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfiguration.java
new file mode 100644 (file)
index 0000000..9bc3fbe
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.ws.client.gitlab.configuration;
+
+public record GitlabConfiguration(boolean enabled, String applicationId, String url, String secret, boolean synchronizeGroups,
+                                  String provisioningType, boolean allowUsersToSignUp, String provisioningToken,
+                                  String singleProvisioningGroup) {
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationService.java
new file mode 100644 (file)
index 0000000..b0f5303
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.ws.client.gitlab.configuration;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.PatchRequest;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsConnector;
+import org.sonarqube.ws.client.WsResponse;
+
+public class GitlabConfigurationService extends BaseService {
+
+
+  public GitlabConfigurationService(WsConnector wsConnector) {
+    super(wsConnector, "api/v2/dop-translation/gitlab-configurations");
+  }
+
+  public String saveGitlabConfiguration(GitlabConfiguration gitlabConfiguration) {
+    String body = String.format("""
+        {
+          "enabled": "%s",
+          "applicationId": "%s",
+          "url": "%s",
+          "secret": "%s",
+          "synchronizeGroups": "%s",
+          "provisioningType": "%s",
+          "allowUsersToSignUp": "%s",
+          "provisioningToken": "%s",
+          "provisioningGroups": ["%s"]
+        }
+        """, gitlabConfiguration.enabled(), gitlabConfiguration.applicationId(), gitlabConfiguration.url(), gitlabConfiguration.secret(),
+      gitlabConfiguration.synchronizeGroups(), gitlabConfiguration.provisioningType(), gitlabConfiguration.allowUsersToSignUp(),
+      gitlabConfiguration.provisioningToken(), gitlabConfiguration.singleProvisioningGroup());
+    WsResponse response = call(
+      new PostRequest(path()).setBody(body)
+    );
+    return new Gson().fromJson(response.content(), JsonObject.class).get("id").getAsString();
+  }
+
+  public void enableAutoProvisioning(String configId) {
+    setProvisioningMode(configId, "AUTO_PROVISIONING");
+  }
+
+  public void disableAutoProvisioning(String configId) {
+    setProvisioningMode(configId, "JIT");
+  }
+
+  private void setProvisioningMode(String configId, String provisioningMode) {
+    String body = String.format("""
+      { 
+        "provisioningType": "%s"
+      }
+      """, provisioningMode);
+    call(
+      new PatchRequest(path(configId)).setBody(body).setContentType(APPLICATION_MERGE_PATCH_JSON)
+    );
+  }
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/package-info.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/configuration/package-info.java
new file mode 100644 (file)
index 0000000..4e9f84e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonarqube.ws.client.gitlab.configuration;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunService.java
new file mode 100644 (file)
index 0000000..007dd8d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.ws.client.gitlab.synchronization.run;
+
+import org.sonarqube.ws.client.BaseService;
+import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsConnector;
+
+public class GitlabSynchronizationRunService extends BaseService {
+
+  public GitlabSynchronizationRunService(WsConnector wsConnector) {
+    super(wsConnector, "api/v2/dop-translation/gitlab-synchronization-runs");
+  }
+
+  public void triggerRun() {
+    call(
+      new PostRequest(path())
+    );
+  }
+
+}
diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/package-info.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/gitlab/synchronization/run/package-info.java
new file mode 100644 (file)
index 0000000..45a93e0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonarqube.ws.client.gitlab.synchronization.run;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/configuration/GitlabConfigurationServiceTest.java
new file mode 100644 (file)
index 0000000..847029c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.ws.client.gitlab.configuration;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GitlabConfigurationServiceTest {
+
+  @Mock(answer = RETURNS_DEEP_STUBS)
+  private WsConnector wsConnector;
+
+  @InjectMocks
+  private GitlabConfigurationService gitlabConfigurationService;
+
+  @Test
+  public void saveGitlabConfiguration_shouldNotFail() {
+    when(wsConnector.call(any()).failIfNotSuccessful().content()).thenReturn("{\"id\": \"configId\"}");
+    assertThatNoException().isThrownBy(() -> gitlabConfigurationService.saveGitlabConfiguration(new GitlabConfiguration(true, "appId", "url", "secret",
+      true, "JIT", false, "token", "group")));
+  }
+
+  @Test
+  public void enableAutoProvisioning_shouldNotFail() {
+    assertThatNoException().isThrownBy(() -> gitlabConfigurationService.enableAutoProvisioning("configId"));
+  }
+
+  @Test
+  public void disableAutoProvisioning_shouldNotFail() {
+    assertThatNoException().isThrownBy(() -> gitlabConfigurationService.disableAutoProvisioning("configId"));
+  }
+
+
+}
diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/gitlab/synchronization/run/GitlabSynchronizationRunServiceTest.java
new file mode 100644 (file)
index 0000000..b976349
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonarqube.ws.client.gitlab.synchronization.run;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.sonarqube.ws.client.WsConnector;
+
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+
+@RunWith(MockitoJUnitRunner.class)
+public class GitlabSynchronizationRunServiceTest {
+
+  @Mock(answer = RETURNS_DEEP_STUBS)
+  private WsConnector wsConnector;
+
+  @InjectMocks
+  private GitlabSynchronizationRunService gitlabSynchronizationRunService;
+
+  @Test
+  public void triggerRun_whenTriggered_shouldNotFail() {
+    assertThatNoException().isThrownBy(() ->gitlabSynchronizationRunService.triggerRun());
+  }
+
+}