mirror of
https://github.com/mc1arke/sonarqube-community-branch-plugin.git
synced 2024-11-28 08:58:55 +02:00
#674: Add support for Sonarqube 9.7
Sonarqube has removed the use of the same external component key and differing database IDs for different branches on the same projects and now use different IDs in all cases. The pull request web service endpoints have also been removed from community edition. To allow the plugin to work with the new version of Sonarqube, the component key generation for branches has been modified to save branch DTOs whenever a new branch is created, and to remove the conditions around re-using the same branch if the target branch details matched an existing branch. The Pull Request endpoint actions have been copied from the old community edition sources, and tidied up to use a cleaner abstraction model. As the front-end only shows branch features if the implementation of `BranchFeatureExtension` returns the name 'branch-support', the `CommunityBranchFeatureExtension` has been altered to follow this requirement, and an additional `MonoRepoFeature` has been implemented to allow the mono-repo switches to be shown against the front-end. Includes the migration of any altered unit tests to JUnit 5.
This commit is contained in:
parent
874b9f23d9
commit
a1f28e5df2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -40,7 +40,7 @@ repositories {
|
||||
}
|
||||
}
|
||||
|
||||
def sonarqubeVersion = '9.1.0.47736'
|
||||
def sonarqubeVersion = '9.7.0.61563'
|
||||
def sonarqubeLibDir = "${projectDir}/sonarqube-lib"
|
||||
def sonarLibraries = "${sonarqubeLibDir}/sonarqube-${sonarqubeVersion}/lib"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -52,8 +52,9 @@ public final class CommunityBranchAgent {
|
||||
|
||||
if (component == Component.CE) {
|
||||
redefineEdition(instrumentation, "org.sonar.core.platform.PlatformEditionProvider", redefineOptionalEditionGetMethod());
|
||||
redefineEdition(instrumentation, "org.sonar.server.almsettings.MultipleAlmFeature", redefineIsEnabledFlag());
|
||||
} else if (component == Component.WEB) {
|
||||
redefineEdition(instrumentation, "org.sonar.server.almsettings.MultipleAlmFeatureProvider", redefineConstructorEditionProviderField(EditionProvider.Edition.ENTERPRISE));
|
||||
redefineEdition(instrumentation, "org.sonar.server.almsettings.MultipleAlmFeature", redefineIsEnabledFlag());
|
||||
redefineEdition(instrumentation, "org.sonar.server.newcodeperiod.ws.SetAction", redefineConstructorEditionProviderField(EditionProvider.Edition.DEVELOPER));
|
||||
redefineEdition(instrumentation, "org.sonar.server.newcodeperiod.ws.UnsetAction", redefineConstructorEditionProviderField(EditionProvider.Edition.DEVELOPER));
|
||||
}
|
||||
@ -101,6 +102,13 @@ public final class CommunityBranchAgent {
|
||||
};
|
||||
}
|
||||
|
||||
private static Redefiner redefineIsEnabledFlag() {
|
||||
return ctClass -> {
|
||||
CtMethod ctMethod = ctClass.getDeclaredMethod("isEnabled");
|
||||
ctMethod.setBody("return true;");
|
||||
};
|
||||
}
|
||||
|
||||
private static Redefiner redefineConstructorEditionProviderField(EditionProvider.Edition edition) {
|
||||
return ctClass -> {
|
||||
CtConstructor ctConstructor = ctClass.getDeclaredConstructors()[0];
|
||||
|
@ -43,17 +43,22 @@ import com.github.mc1arke.sonarqube.plugin.scanner.autoconfiguration.GitlabCiAut
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.autoconfiguration.JenkinsAutoConfigurer;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.MonoRepoFeature;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.AzureDevopsValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.BitbucketValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.GithubValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.GitlabValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.DeleteBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetAzureBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetBitbucketBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetBitbucketCloudBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetGithubBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.SetGitlabBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action.ValidateBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.DeleteBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.SetAzureBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.SetBitbucketBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.SetBitbucketCloudBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.SetGithubBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.SetGitlabBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action.ValidateBindingAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.PullRequestWs;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action.DeleteAction;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action.ListAction;
|
||||
|
||||
import org.sonar.api.CoreProperties;
|
||||
import org.sonar.api.Plugin;
|
||||
import org.sonar.api.PropertyType;
|
||||
@ -88,6 +93,9 @@ public class CommunityBranchPlugin implements Plugin, CoreExtension {
|
||||
SetBitbucketCloudBindingAction.class,
|
||||
SetGitlabBindingAction.class,
|
||||
ValidateBindingAction.class,
|
||||
DeleteAction.class,
|
||||
ListAction.class,
|
||||
PullRequestWs.class,
|
||||
|
||||
GithubValidator.class,
|
||||
DefaultGraphqlProvider.class,
|
||||
@ -147,7 +155,8 @@ public class CommunityBranchPlugin implements Plugin, CoreExtension {
|
||||
.name("Images base URL")
|
||||
.description("Base URL used to load the images for the PR comments (please use this only if images are not displayed properly).")
|
||||
.type(PropertyType.STRING)
|
||||
.build());
|
||||
.build(),
|
||||
MonoRepoFeature.class);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,11 +18,8 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.ce;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sonar.ce.task.projectanalysis.analysis.Branch;
|
||||
import org.sonar.core.component.ComponentKeys;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.ComponentDto;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
@ -80,24 +77,6 @@ public class CommunityBranch implements Branch {
|
||||
return pullRequestKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generateKey(String projectKey, String fileOrDirPath) {
|
||||
String effectiveKey;
|
||||
if (null == fileOrDirPath) {
|
||||
effectiveKey = projectKey;
|
||||
} else {
|
||||
effectiveKey = ComponentKeys.createEffectiveKey(projectKey, StringUtils.trimToNull(fileOrDirPath));
|
||||
}
|
||||
|
||||
if (main) {
|
||||
return effectiveKey;
|
||||
} else if (BranchType.PULL_REQUEST == branchType) {
|
||||
return ComponentDto.generatePullRequestKey(effectiveKey, pullRequestKey);
|
||||
} else {
|
||||
return ComponentDto.generateBranchKey(effectiveKey, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTargetBranchName() {
|
||||
return targetBranchName;
|
||||
|
@ -71,16 +71,16 @@ public abstract class DiscussionAwarePullRequestDecorator<C, P, U, D, N> impleme
|
||||
U user = getCurrentUser(client);
|
||||
List<PostAnalysisIssueVisitor.ComponentIssue> openSonarqubeIssues = analysis.getScmReportableIssues();
|
||||
|
||||
List<Triple<D, N, Optional<ProjectIssueIdentifier>>> currentProjectSonarqueComments = findOpenSonarqubeComments(client,
|
||||
List<Triple<D, N, Optional<ProjectIssueIdentifier>>> currentProjectSonarqubeComments = findOpenSonarqubeComments(client,
|
||||
pullRequest,
|
||||
user)
|
||||
.stream()
|
||||
.filter(comment -> isCommentFromCurrentProject(comment, analysis.getAnalysisProjectKey()))
|
||||
.filter(comment -> !projectAlmSettingDto.getMonorepo() || isCommentFromCurrentProject(comment, analysis.getAnalysisProjectKey()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> commentKeysForOpenComments = closeOldDiscussionsAndExtractRemainingKeys(client,
|
||||
user,
|
||||
currentProjectSonarqueComments,
|
||||
currentProjectSonarqubeComments,
|
||||
openSonarqubeIssues,
|
||||
pullRequest);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Michael Clarke
|
||||
* Copyright (C) 2019-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -27,6 +27,11 @@ import org.sonar.server.branch.BranchFeatureExtension;
|
||||
*/
|
||||
public class CommunityBranchFeatureExtension implements BranchFeatureExtension {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "branch-support";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,7 +18,15 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sonar.api.config.Configuration;
|
||||
import org.sonar.core.config.PurgeConstants;
|
||||
import org.sonar.core.util.UuidFactory;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
@ -28,11 +36,7 @@ import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.ComponentDto;
|
||||
import org.sonar.server.ce.queue.BranchSupport;
|
||||
import org.sonar.server.ce.queue.BranchSupportDelegate;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.sonar.server.setting.ProjectConfigurationLoader;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
@ -42,12 +46,15 @@ public class CommunityBranchSupportDelegate implements BranchSupportDelegate {
|
||||
private final UuidFactory uuidFactory;
|
||||
private final DbClient dbClient;
|
||||
private final Clock clock;
|
||||
private final ProjectConfigurationLoader projectConfigurationLoader;
|
||||
|
||||
public CommunityBranchSupportDelegate(UuidFactory uuidFactory, DbClient dbClient, Clock clock) {
|
||||
public CommunityBranchSupportDelegate(UuidFactory uuidFactory, DbClient dbClient, Clock clock,
|
||||
ProjectConfigurationLoader projectConfigurationLoader) {
|
||||
super();
|
||||
this.uuidFactory = uuidFactory;
|
||||
this.dbClient = dbClient;
|
||||
this.clock = clock;
|
||||
this.projectConfigurationLoader = projectConfigurationLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -61,9 +68,7 @@ public class CommunityBranchSupportDelegate implements BranchSupportDelegate {
|
||||
CeTaskCharacteristicDto.BRANCH_TYPE_KEY,
|
||||
CeTaskCharacteristicDto.PULL_REQUEST));
|
||||
} else {
|
||||
return new CommunityComponentKey(projectKey,
|
||||
ComponentDto.generatePullRequestKey(projectKey, pullRequest), null,
|
||||
pullRequest);
|
||||
return new CommunityComponentKey(projectKey, null, pullRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +76,7 @@ public class CommunityBranchSupportDelegate implements BranchSupportDelegate {
|
||||
|
||||
try {
|
||||
BranchType.valueOf(branchTypeParam);
|
||||
return new CommunityComponentKey(projectKey, ComponentDto.generateBranchKey(projectKey, branch), branch, null);
|
||||
return new CommunityComponentKey(projectKey, branch, null);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new IllegalArgumentException(String.format("Unsupported branch type '%s'", branchTypeParam), ex);
|
||||
}
|
||||
@ -85,25 +90,37 @@ public class CommunityBranchSupportDelegate implements BranchSupportDelegate {
|
||||
throw new IllegalStateException("Component Key and Main Component Key do not match");
|
||||
}
|
||||
|
||||
Optional<String> branchOptional = componentKey.getBranchName();
|
||||
if (branchOptional.isPresent() && branchOptional.get().equals(mainComponentBranchDto.getKey())) {
|
||||
return mainComponentDto;
|
||||
}
|
||||
|
||||
String branchUuid = uuidFactory.create();
|
||||
|
||||
// borrowed from https://github.com/SonarSource/sonarqube/blob/e80c0f3d1e5cd459f88b7e0c41a2d9a7519e260f/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/component/BranchPersisterImpl.java
|
||||
ComponentDto branchDto = mainComponentDto.copy();
|
||||
branchDto.setUuid(branchUuid);
|
||||
branchDto.setProjectUuid(branchUuid);
|
||||
branchDto.setRootUuid(branchUuid);
|
||||
branchDto.setUuidPath(ComponentDto.UUID_PATH_OF_ROOT);
|
||||
branchDto.setModuleUuidPath(ComponentDto.UUID_PATH_SEPARATOR + branchUuid + ComponentDto.UUID_PATH_SEPARATOR);
|
||||
branchDto.setMainBranchProjectUuid(mainComponentDto.uuid());
|
||||
branchDto.setDbKey(componentKey.getDbKey());
|
||||
branchDto.setCreatedAt(new Date(clock.millis()));
|
||||
dbClient.componentDao().insert(dbSession, branchDto);
|
||||
return branchDto;
|
||||
ComponentDto componentDto = mainComponentDto.copy()
|
||||
.setUuid(branchUuid)
|
||||
.setRootUuid(branchUuid)
|
||||
.setBranchUuid(branchUuid)
|
||||
.setUuidPath(ComponentDto.UUID_PATH_OF_ROOT)
|
||||
.setModuleUuidPath(ComponentDto.UUID_PATH_SEPARATOR + branchUuid + ComponentDto.UUID_PATH_SEPARATOR)
|
||||
.setMainBranchProjectUuid(mainComponentDto.uuid())
|
||||
.setCreatedAt(new Date(clock.millis()));
|
||||
dbClient.componentDao().insert(dbSession, componentDto);
|
||||
|
||||
BranchDto branchDto = new BranchDto()
|
||||
.setProjectUuid(mainComponentDto.uuid())
|
||||
.setUuid(branchUuid);
|
||||
componentKey.getPullRequestKey().ifPresent(pullRequestKey -> branchDto.setBranchType(BranchType.PULL_REQUEST)
|
||||
.setExcludeFromPurge(false)
|
||||
.setKey(pullRequestKey));
|
||||
componentKey.getBranchName().ifPresent(branchName -> branchDto.setBranchType(BranchType.BRANCH)
|
||||
.setExcludeFromPurge(isBranchExcludedFromPurge(projectConfigurationLoader.loadProjectConfiguration(dbSession, mainComponentDto), branchName))
|
||||
.setKey(branchName));
|
||||
dbClient.branchDao().insert(dbSession, branchDto);
|
||||
|
||||
return componentDto;
|
||||
}
|
||||
|
||||
private static boolean isBranchExcludedFromPurge(Configuration projectConfiguration, String branchName) {
|
||||
return Arrays.stream(projectConfiguration.getStringArray(PurgeConstants.BRANCHES_TO_KEEP_WHEN_INACTIVE))
|
||||
.map(Pattern::compile)
|
||||
.map(Pattern::asMatchPredicate)
|
||||
.anyMatch(p -> p.test(branchName));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -28,13 +28,11 @@ import java.util.Optional;
|
||||
/*package*/ class CommunityComponentKey extends BranchSupport.ComponentKey {
|
||||
|
||||
private final String key;
|
||||
private final String dbKey;
|
||||
private final String branchName;
|
||||
private final String pullRequestKey;
|
||||
|
||||
/*package*/ CommunityComponentKey(String key, String dbKey, String branchName, String pullRequestKey) {
|
||||
/*package*/ CommunityComponentKey(String key, String branchName, String pullRequestKey) {
|
||||
this.key = key;
|
||||
this.dbKey = dbKey;
|
||||
this.branchName = branchName;
|
||||
this.pullRequestKey = pullRequestKey;
|
||||
}
|
||||
@ -44,25 +42,14 @@ import java.util.Optional;
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbKey() {
|
||||
return dbKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getBranchName() {
|
||||
return Optional.ofNullable(branchName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> getPullRequestKey() {
|
||||
return Optional.ofNullable(pullRequestKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommunityComponentKey getMainBranchComponentKey() {
|
||||
if (key.equals(dbKey)) {
|
||||
return this;
|
||||
}
|
||||
return new CommunityComponentKey(key, key, null, null);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server;
|
||||
|
||||
import org.sonar.api.ce.ComputeEngineSide;
|
||||
import org.sonar.api.server.ServerSide;
|
||||
import org.sonar.server.feature.SonarQubeFeature;
|
||||
|
||||
@ServerSide
|
||||
@ComputeEngineSide
|
||||
public class MonoRepoFeature implements SonarQubeFeature {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "monorepo";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
@FunctionalInterface
|
||||
interface ProtoBufWriter {
|
||||
|
||||
void write(Message message, Request request, Response response);
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
@ -32,14 +32,14 @@ public class DeleteBindingAction extends ProjectWsAction {
|
||||
private final DbClient dbClient;
|
||||
|
||||
public DeleteBindingAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
|
||||
super("delete_binding", dbClient, componentFinder, userSession, true);
|
||||
super("delete_binding", dbClient, componentFinder, userSession);
|
||||
this.dbClient = dbClient;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void configureAction(WebService.NewAction action) {
|
||||
//no-op
|
||||
action.setPost(true);
|
||||
}
|
||||
|
||||
@Override
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
@ -29,8 +29,6 @@ import org.sonar.server.almsettings.ws.AlmSettingsWsAction;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class ProjectWsAction implements AlmSettingsWsAction {
|
||||
|
||||
private static final String PROJECT_PARAMETER = "project";
|
||||
@ -39,27 +37,25 @@ public abstract class ProjectWsAction implements AlmSettingsWsAction {
|
||||
private final DbClient dbClient;
|
||||
private final ComponentFinder componentFinder;
|
||||
private final UserSession userSession;
|
||||
private final boolean projectParameterRequired;
|
||||
private final String permission;
|
||||
|
||||
protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, boolean projectParameterRequired) {
|
||||
this(actionName, dbClient, componentFinder, userSession, projectParameterRequired, UserRole.ADMIN);
|
||||
protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) {
|
||||
this(actionName, dbClient, componentFinder, userSession, UserRole.ADMIN);
|
||||
}
|
||||
|
||||
protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, boolean projectParameterRequired, String permission) {
|
||||
protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, String permission) {
|
||||
super();
|
||||
this.actionName = actionName;
|
||||
this.dbClient = dbClient;
|
||||
this.componentFinder = componentFinder;
|
||||
this.userSession = userSession;
|
||||
this.projectParameterRequired = projectParameterRequired;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void define(WebService.NewController context) {
|
||||
WebService.NewAction action = context.createAction(actionName).setHandler(this);
|
||||
action.createParam(PROJECT_PARAMETER).setRequired(projectParameterRequired);
|
||||
action.createParam(PROJECT_PARAMETER).setRequired(true);
|
||||
|
||||
configureAction(action);
|
||||
}
|
||||
@ -69,20 +65,11 @@ public abstract class ProjectWsAction implements AlmSettingsWsAction {
|
||||
|
||||
@Override
|
||||
public void handle(Request request, Response response) {
|
||||
Optional<String> projectKey = Optional.ofNullable(request.param(PROJECT_PARAMETER));
|
||||
String projectKey = request.mandatoryParam(PROJECT_PARAMETER);
|
||||
|
||||
try (DbSession dbSession = dbClient.openSession(false)) {
|
||||
ProjectDto project;
|
||||
if (projectKey.isPresent()) {
|
||||
project = componentFinder.getProjectByKey(dbSession, projectKey.get());
|
||||
userSession.checkProjectPermission(permission, project);
|
||||
} else {
|
||||
if (projectParameterRequired) {
|
||||
throw new IllegalArgumentException("The 'project' parameter is missing");
|
||||
} else {
|
||||
project = null;
|
||||
}
|
||||
}
|
||||
ProjectDto project = componentFinder.getProjectByKey(dbSession, projectKey);
|
||||
userSession.checkProjectPermission(permission, project);
|
||||
handleProjectRequest(project, request, response, dbSession);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -44,13 +44,13 @@ public class SetAzureBindingAction extends SetBindingAction {
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid,
|
||||
Request request) {
|
||||
boolean monoRepo, Request request) {
|
||||
return new ProjectAlmSettingDto()
|
||||
.setProjectUuid(projectUuid)
|
||||
.setAlmSettingUuid(settingsUuid)
|
||||
.setAlmRepo(request.mandatoryParam(REPOSITORY_NAME_PARAMETER))
|
||||
.setAlmSlug(request.mandatoryParam(PROJECT_NAME_PARAMETER))
|
||||
.setMonorepo(false);
|
||||
.setMonorepo(monoRepo);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
@ -35,23 +35,27 @@ import static java.lang.String.format;
|
||||
public abstract class SetBindingAction extends ProjectWsAction {
|
||||
|
||||
private static final String ALM_SETTING_PARAMETER = "almSetting";
|
||||
private static final String MONOREPO_PARAMETER = "monorepo";
|
||||
|
||||
protected SetBindingAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, String actionName) {
|
||||
super(actionName, dbClient, componentFinder, userSession, true);
|
||||
super(actionName, dbClient, componentFinder, userSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureAction(WebService.NewAction action) {
|
||||
action.createParam(ALM_SETTING_PARAMETER).setRequired(true);
|
||||
action.setPost(true)
|
||||
.createParam(ALM_SETTING_PARAMETER).setRequired(true);
|
||||
action.createParam(MONOREPO_PARAMETER).setRequired(true).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) {
|
||||
String almSetting = request.mandatoryParam(ALM_SETTING_PARAMETER);
|
||||
boolean monoRepo = request.mandatoryParamAsBoolean(MONOREPO_PARAMETER);
|
||||
|
||||
DbClient dbClient = getDbClient();
|
||||
AlmSettingDto almSettingDto = getAlmSetting(dbClient, dbSession, almSetting);
|
||||
dbClient.projectAlmSettingDao().insertOrUpdate(dbSession, createProjectAlmSettingDto(project.getUuid(), almSettingDto.getUuid(), request), almSettingDto.getUuid(), project.getName(), project.getKey());
|
||||
dbClient.projectAlmSettingDao().insertOrUpdate(dbSession, createProjectAlmSettingDto(project.getUuid(), almSettingDto.getUuid(), monoRepo, request), almSettingDto.getUuid(), project.getName(), project.getKey());
|
||||
dbSession.commit();
|
||||
|
||||
response.noContent();
|
||||
@ -63,6 +67,6 @@ public abstract class SetBindingAction extends ProjectWsAction {
|
||||
}
|
||||
|
||||
|
||||
protected abstract ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, Request request);
|
||||
protected abstract ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, boolean monoRepo, Request request);
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -43,13 +43,13 @@ public class SetBitbucketBindingAction extends SetBindingAction {
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid,
|
||||
Request request) {
|
||||
boolean monoRepo, Request request) {
|
||||
return new ProjectAlmSettingDto()
|
||||
.setProjectUuid(projectUuid)
|
||||
.setAlmSettingUuid(settingsUuid)
|
||||
.setAlmRepo(request.mandatoryParam(REPOSITORY_PARAMETER))
|
||||
.setAlmSlug(request.mandatoryParam(SLUG_PARAMETER))
|
||||
.setMonorepo(false);
|
||||
.setMonorepo(monoRepo);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -37,16 +37,17 @@ public class SetBitbucketCloudBindingAction extends SetBindingAction {
|
||||
protected void configureAction(WebService.NewAction action) {
|
||||
super.configureAction(action);
|
||||
action.createParam(REPOSITORY_PARAMETER).setRequired(true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid,
|
||||
Request request) {
|
||||
boolean monoRepo, Request request) {
|
||||
return new ProjectAlmSettingDto()
|
||||
.setProjectUuid(projectUuid)
|
||||
.setAlmSettingUuid(settingsUuid)
|
||||
.setAlmRepo(request.mandatoryParam(REPOSITORY_PARAMETER))
|
||||
.setMonorepo(false);
|
||||
.setMonorepo(monoRepo);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -42,13 +42,13 @@ public class SetGithubBindingAction extends SetBindingAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, Request request) {
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, boolean monoRepo, Request request) {
|
||||
return new ProjectAlmSettingDto()
|
||||
.setProjectUuid(projectUuid)
|
||||
.setAlmSettingUuid(settingsUuid)
|
||||
.setAlmRepo(request.mandatoryParam(REPOSITORY_PARAMETER))
|
||||
.setSummaryCommentEnabled(request.paramAsBoolean(SUMMARY_COMMENT_PARAMETER))
|
||||
.setMonorepo(false);
|
||||
.setMonorepo(monoRepo);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -40,12 +40,12 @@ public class SetGitlabBindingAction extends SetBindingAction {
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid,
|
||||
Request request) {
|
||||
boolean monoRepo, Request request) {
|
||||
return new ProjectAlmSettingDto()
|
||||
.setProjectUuid(projectUuid)
|
||||
.setAlmSettingUuid(settingsUuid)
|
||||
.setAlmRepo(request.param(REPOSITORY_PARAMETER))
|
||||
.setMonorepo(false);
|
||||
.setMonorepo(monoRepo);
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.InvalidConfigurationException;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.Validator;
|
||||
@ -41,7 +41,7 @@ public class ValidateBindingAction extends ProjectWsAction {
|
||||
private final List<Validator> validators;
|
||||
|
||||
public ValidateBindingAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, List<Validator> validators) {
|
||||
super("validate_binding", dbClient, componentFinder, userSession, true, UserRole.USER);
|
||||
super("validate_binding", dbClient, componentFinder, userSession, UserRole.USER);
|
||||
this.validators = validators;
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest;
|
||||
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action.PullRequestWsAction;
|
||||
|
||||
public class PullRequestWs implements WebService {
|
||||
|
||||
private final PullRequestWsAction[] actions;
|
||||
|
||||
public PullRequestWs(PullRequestWsAction... actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void define(Context context) {
|
||||
NewController controller = context.createController("api/project_pull_requests");
|
||||
for (PullRequestWsAction action : actions) {
|
||||
action.define(controller);
|
||||
}
|
||||
controller.done();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2022 SonarSource SA (mailto:info AT sonarsource DOT com), Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.api.web.UserRole;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.server.component.ComponentCleanerService;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.exceptions.NotFoundException;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
public class DeleteAction extends ProjectWsAction {
|
||||
|
||||
private static final String PULL_REQUEST_PARAMETER = "pullRequest";
|
||||
|
||||
private final UserSession userSession;
|
||||
private final ComponentCleanerService componentCleanerService;
|
||||
|
||||
public DeleteAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ComponentCleanerService componentCleanerService) {
|
||||
super("delete", dbClient, componentFinder);
|
||||
this.userSession = userSession;
|
||||
this.componentCleanerService = componentCleanerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureAction(WebService.NewAction action) {
|
||||
action.setPost(true)
|
||||
.createParam(PULL_REQUEST_PARAMETER)
|
||||
.setRequired(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) {
|
||||
userSession.checkLoggedIn()
|
||||
.checkProjectPermission(UserRole.ADMIN, project);
|
||||
|
||||
String pullRequestId = request.mandatoryParam(PULL_REQUEST_PARAMETER);
|
||||
|
||||
BranchDto pullRequest = getDbClient().branchDao().selectByPullRequestKey(dbSession, project.getUuid(), pullRequestId)
|
||||
.filter(branch -> branch.getBranchType() == BranchType.PULL_REQUEST)
|
||||
.orElseThrow(() -> new NotFoundException(String.format("Pull request '%s' is not found for project '%s'", pullRequestId, project.getKey())));
|
||||
|
||||
componentCleanerService.deleteBranch(dbSession, pullRequest);
|
||||
response.noContent();
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2022 SonarSource SA (mailto:info AT sonarsource DOT com), Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.sonar.api.measures.CoreMetrics;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.api.utils.DateUtils;
|
||||
import org.sonar.api.web.UserRole;
|
||||
import org.sonar.core.util.stream.MoreCollectors;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
import org.sonar.db.component.BranchDao;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.SnapshotDto;
|
||||
import org.sonar.db.measure.LiveMeasureDto;
|
||||
import org.sonar.db.permission.GlobalPermission;
|
||||
import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.db.protobuf.DbProjectBranches;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.issue.index.IssueIndex;
|
||||
import org.sonar.server.issue.index.PrStatistics;
|
||||
import org.sonar.server.user.UserSession;
|
||||
import org.sonar.server.ws.WsUtils;
|
||||
import org.sonarqube.ws.ProjectPullRequests;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
public class ListAction extends ProjectWsAction {
|
||||
|
||||
private final UserSession userSession;
|
||||
private final IssueIndex issueIndex;
|
||||
private final ProtoBufWriter protoBufWriter;
|
||||
|
||||
@Autowired
|
||||
public ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, IssueIndex issueIndex) {
|
||||
this(dbClient, componentFinder, userSession, issueIndex, WsUtils::writeProtobuf);
|
||||
}
|
||||
|
||||
ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, IssueIndex issueIndex, ProtoBufWriter protoBufWriter) {
|
||||
super("list", dbClient, componentFinder);
|
||||
this.userSession = userSession;
|
||||
this.issueIndex = issueIndex;
|
||||
this.protoBufWriter = protoBufWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureAction(WebService.NewAction action) {
|
||||
//no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession) {
|
||||
checkPermission(project, userSession);
|
||||
|
||||
BranchDao branchDao = getDbClient().branchDao();
|
||||
List<BranchDto> pullRequests = branchDao.selectByProject(dbSession, project).stream()
|
||||
.filter(b -> b.getBranchType() == BranchType.PULL_REQUEST)
|
||||
.collect(Collectors.toList());
|
||||
List<String> pullRequestUuids = pullRequests.stream().map(BranchDto::getUuid).collect(Collectors.toList());
|
||||
|
||||
Map<String, BranchDto> mergeBranchesByUuid = branchDao
|
||||
.selectByUuids(dbSession, pullRequests.stream()
|
||||
.map(BranchDto::getMergeBranchUuid)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList()))
|
||||
.stream().collect(MoreCollectors.uniqueIndex(BranchDto::getUuid));
|
||||
|
||||
Map<String, PrStatistics> branchStatisticsByBranchUuid = issueIndex.searchBranchStatistics(project.getUuid(), pullRequestUuids).stream()
|
||||
.collect(MoreCollectors.uniqueIndex(PrStatistics::getBranchUuid, Function.identity()));
|
||||
Map<String, LiveMeasureDto> qualityGateMeasuresByComponentUuids = getDbClient().liveMeasureDao()
|
||||
.selectByComponentUuidsAndMetricKeys(dbSession, pullRequestUuids, List.of(CoreMetrics.ALERT_STATUS_KEY)).stream()
|
||||
.collect(MoreCollectors.uniqueIndex(LiveMeasureDto::getComponentUuid));
|
||||
Map<String, String> analysisDateByBranchUuid = getDbClient().snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, pullRequestUuids).stream()
|
||||
.collect(MoreCollectors.uniqueIndex(SnapshotDto::getComponentUuid, s -> DateUtils.formatDateTime(s.getCreatedAt())));
|
||||
|
||||
ProjectPullRequests.ListWsResponse.Builder protobufResponse = ProjectPullRequests.ListWsResponse.newBuilder();
|
||||
pullRequests
|
||||
.forEach(b -> addPullRequest(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), branchStatisticsByBranchUuid.get(b.getUuid()),
|
||||
analysisDateByBranchUuid.get(b.getUuid())));
|
||||
protoBufWriter.write(protobufResponse.build(), request, response);
|
||||
}
|
||||
|
||||
private static void checkPermission(ProjectDto project, UserSession userSession) {
|
||||
if (userSession.hasProjectPermission(UserRole.USER, project) ||
|
||||
userSession.hasProjectPermission(UserRole.SCAN, project) ||
|
||||
userSession.hasPermission(GlobalPermission.SCAN)) {
|
||||
return;
|
||||
}
|
||||
throw insufficientPrivilegesException();
|
||||
}
|
||||
|
||||
private static void addPullRequest(ProjectPullRequests.ListWsResponse.Builder response, BranchDto branch, Map<String, BranchDto> mergeBranchesByUuid,
|
||||
@Nullable LiveMeasureDto qualityGateMeasure, PrStatistics prStatistics, @Nullable String analysisDate) {
|
||||
Optional<BranchDto> mergeBranch = Optional.ofNullable(mergeBranchesByUuid.get(branch.getMergeBranchUuid()));
|
||||
|
||||
ProjectPullRequests.PullRequest.Builder builder = ProjectPullRequests.PullRequest.newBuilder();
|
||||
builder.setKey(branch.getKey());
|
||||
|
||||
DbProjectBranches.PullRequestData pullRequestData = Objects.requireNonNull(branch.getPullRequestData(), "Pull request data should be available for branch type PULL_REQUEST");
|
||||
builder.setBranch(pullRequestData.getBranch());
|
||||
Optional.ofNullable(Strings.emptyToNull(pullRequestData.getUrl())).ifPresent(builder::setUrl);
|
||||
Optional.ofNullable(Strings.emptyToNull(pullRequestData.getTitle())).ifPresent(builder::setTitle);
|
||||
|
||||
if (mergeBranch.isPresent()) {
|
||||
String mergeBranchKey = mergeBranch.get().getKey();
|
||||
builder.setBase(mergeBranchKey);
|
||||
} else {
|
||||
builder.setIsOrphan(true);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(pullRequestData.getTarget())) {
|
||||
builder.setTarget(pullRequestData.getTarget());
|
||||
} else {
|
||||
mergeBranch.ifPresent(branchDto -> builder.setTarget(branchDto.getKey()));
|
||||
}
|
||||
|
||||
Optional.ofNullable(analysisDate).ifPresent(builder::setAnalysisDate);
|
||||
setQualityGate(builder, qualityGateMeasure, prStatistics);
|
||||
response.addPullRequests(builder);
|
||||
}
|
||||
|
||||
private static void setQualityGate(ProjectPullRequests.PullRequest.Builder builder, @Nullable LiveMeasureDto qualityGateMeasure, @Nullable PrStatistics prStatistics) {
|
||||
ProjectPullRequests.Status.Builder statusBuilder = ProjectPullRequests.Status.newBuilder();
|
||||
if (qualityGateMeasure != null) {
|
||||
Optional.ofNullable(qualityGateMeasure.getDataAsString()).ifPresent(statusBuilder::setQualityGateStatus);
|
||||
}
|
||||
statusBuilder.setBugs(prStatistics == null ? 0L : prStatistics.getBugs());
|
||||
statusBuilder.setVulnerabilities(prStatistics == null ? 0L : prStatistics.getVulnerabilities());
|
||||
statusBuilder.setCodeSmells(prStatistics == null ? 0L : prStatistics.getCodeSmells());
|
||||
builder.setStatus(statusBuilder);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
|
||||
public abstract class ProjectWsAction implements PullRequestWsAction {
|
||||
|
||||
private static final String PROJECT_PARAMETER = "project";
|
||||
|
||||
private final String actionName;
|
||||
private final DbClient dbClient;
|
||||
private final ComponentFinder componentFinder;
|
||||
|
||||
protected ProjectWsAction(String actionName, DbClient dbClient, ComponentFinder componentFinder) {
|
||||
super();
|
||||
this.actionName = actionName;
|
||||
this.dbClient = dbClient;
|
||||
this.componentFinder = componentFinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void define(WebService.NewController context) {
|
||||
WebService.NewAction action = context.createAction(actionName).setHandler(this);
|
||||
action.createParam(PROJECT_PARAMETER).setRequired(true);
|
||||
|
||||
configureAction(action);
|
||||
}
|
||||
|
||||
protected abstract void configureAction(WebService.NewAction action);
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(Request request, Response response) {
|
||||
String projectKey = request.mandatoryParam(PROJECT_PARAMETER);
|
||||
|
||||
try (DbSession dbSession = dbClient.openSession(false)) {
|
||||
ProjectDto project = componentFinder.getProjectByKey(dbSession, projectKey);
|
||||
handleProjectRequest(project, request, response, dbSession);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void handleProjectRequest(ProjectDto project, Request request, Response response, DbSession dbSession);
|
||||
|
||||
protected DbClient getDbClient() {
|
||||
return dbClient;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
@FunctionalInterface
|
||||
interface ProtoBufWriter {
|
||||
|
||||
void write(Message message, Request request, Response response);
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import org.sonar.server.ws.WsAction;
|
||||
|
||||
public interface PullRequestWsAction extends WsAction {
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,18 +18,11 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.sonar.core.platform.EditionProvider;
|
||||
import org.sonar.core.platform.PlatformEditionProvider;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.newcodeperiod.NewCodePeriodDao;
|
||||
import org.sonar.server.almsettings.MultipleAlmFeatureProvider;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.newcodeperiod.ws.SetAction;
|
||||
import org.sonar.server.newcodeperiod.ws.UnsetAction;
|
||||
import org.sonar.server.user.UserSession;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -40,49 +33,56 @@ import java.lang.instrument.UnmodifiableClassException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.sonar.api.SonarRuntime;
|
||||
import org.sonar.core.platform.EditionProvider;
|
||||
import org.sonar.core.platform.PlatformEditionProvider;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.newcodeperiod.NewCodePeriodDao;
|
||||
import org.sonar.server.almsettings.MultipleAlmFeature;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.feature.SonarQubeFeature;
|
||||
import org.sonar.server.newcodeperiod.ws.SetAction;
|
||||
import org.sonar.server.newcodeperiod.ws.UnsetAction;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
public class CommunityBranchAgentTest {
|
||||
class CommunityBranchAgentTest {
|
||||
|
||||
@Test
|
||||
public void checkErrorThrownIfAgentArgsNotValid() {
|
||||
void shouldThrowErrorIfAgentArgsNotValid() {
|
||||
assertThatThrownBy(() -> CommunityBranchAgent.premain("badarg", mock(Instrumentation.class)))
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Invalid/missing agent argument");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkRedefineForWebLaunchRedefinesMultipleAlmFeatureClass() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
void shouldRedefineMultipleAlmFeatureClassForWebLaunch() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
CustomClassloader classLoader = new CustomClassloader();
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
|
||||
CommunityBranchAgent.premain("web", instrumentation);
|
||||
|
||||
ArgumentCaptor<ClassFileTransformer> classFileTransformerArgumentCaptor = ArgumentCaptor.forClass(ClassFileTransformer.class);
|
||||
verify(instrumentation).retransformClasses(MultipleAlmFeatureProvider.class);
|
||||
verify(instrumentation).retransformClasses(MultipleAlmFeature.class);
|
||||
verify(instrumentation, times(3)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
try (InputStream inputStream = MultipleAlmFeatureProvider.class.getResourceAsStream(MultipleAlmFeatureProvider.class.getSimpleName())) {
|
||||
try (InputStream inputStream = MultipleAlmFeature.class.getResourceAsStream(MultipleAlmFeature.class.getSimpleName() + ".class")) {
|
||||
byte[] input = IOUtils.toByteArray(inputStream);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(0).transform(classLoader, MultipleAlmFeatureProvider.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
Class<?> redefined = classLoader.loadClass(MultipleAlmFeatureProvider.class.getName(), result);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(0).transform(classLoader, MultipleAlmFeature.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
Class<SonarQubeFeature> redefined = (Class<SonarQubeFeature>) classLoader.loadClass(MultipleAlmFeature.class.getName(), result);
|
||||
|
||||
PlatformEditionProvider platformEditionProvider = mock(PlatformEditionProvider.class);
|
||||
SonarRuntime sonarRuntime = mock(SonarRuntime.class);
|
||||
|
||||
Object multipleAlmFeatureProvider = redefined.getConstructor(PlatformEditionProvider.class).newInstance(platformEditionProvider);
|
||||
Field editionProviderField = redefined.getDeclaredField("editionProvider");
|
||||
editionProviderField.setAccessible(true);
|
||||
|
||||
assertThat(((EditionProvider) editionProviderField.get(multipleAlmFeatureProvider)).get()).isEqualTo(Optional.of(EditionProvider.Edition.ENTERPRISE));
|
||||
SonarQubeFeature multipleAlmFeatureProvider = redefined.getConstructor(SonarRuntime.class).newInstance(sonarRuntime);
|
||||
assertThat(multipleAlmFeatureProvider.isEnabled()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void checkRedefineForWebLaunchRedefinesSetActionClass() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
void shouldRedefineSetActionClassForWebLaunch() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
CustomClassloader classLoader = new CustomClassloader();
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
|
||||
@ -92,7 +92,7 @@ public class CommunityBranchAgentTest {
|
||||
verify(instrumentation).retransformClasses(SetAction.class);
|
||||
verify(instrumentation, times(3)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
try (InputStream inputStream = SetAction.class.getResourceAsStream(SetAction.class.getSimpleName())) {
|
||||
try (InputStream inputStream = SetAction.class.getResourceAsStream(SetAction.class.getSimpleName() + ".class")) {
|
||||
byte[] input = IOUtils.toByteArray(inputStream);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(1).transform(classLoader, SetAction.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
|
||||
@ -114,7 +114,7 @@ public class CommunityBranchAgentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkRedefineForWebLaunchRedefinesUnsetActionClass() throws IOException, UnmodifiableClassException, IllegalClassFormatException, ReflectiveOperationException {
|
||||
void shouldRedefinesUnsetActionClassForWebLaunch() throws IOException, UnmodifiableClassException, IllegalClassFormatException, ReflectiveOperationException {
|
||||
CustomClassloader classLoader = new CustomClassloader();
|
||||
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
@ -124,7 +124,7 @@ public class CommunityBranchAgentTest {
|
||||
verify(instrumentation).retransformClasses(UnsetAction.class);
|
||||
verify(instrumentation, times(3)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
try (InputStream inputStream = SetAction.class.getResourceAsStream(SetAction.class.getSimpleName())) {
|
||||
try (InputStream inputStream = SetAction.class.getResourceAsStream(SetAction.class.getSimpleName() + ".class")) {
|
||||
byte[] input = IOUtils.toByteArray(inputStream);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(2).transform(classLoader, UnsetAction.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
|
||||
@ -145,13 +145,13 @@ public class CommunityBranchAgentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkRedefineForWebLaunchSkipsNonTargetClass() throws UnmodifiableClassException, ClassNotFoundException, IllegalClassFormatException {
|
||||
void shouldSkipNonTargetClasForWebLaunch() throws UnmodifiableClassException, ClassNotFoundException, IllegalClassFormatException {
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
|
||||
CommunityBranchAgent.premain("web", instrumentation);
|
||||
|
||||
ArgumentCaptor<ClassFileTransformer> classFileTransformerArgumentCaptor = ArgumentCaptor.forClass(ClassFileTransformer.class);
|
||||
verify(instrumentation).retransformClasses(MultipleAlmFeatureProvider.class);
|
||||
verify(instrumentation).retransformClasses(MultipleAlmFeature.class);
|
||||
verify(instrumentation, times(3)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
byte[] input = new byte[]{1, 2, 3, 4, 5, 6};
|
||||
@ -161,14 +161,14 @@ public class CommunityBranchAgentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkRedefineForCeLaunchSkipsNonTargetClass() throws UnmodifiableClassException, ClassNotFoundException, IllegalClassFormatException {
|
||||
void shouldSkipNonTargetClassForCeLunch() throws UnmodifiableClassException, ClassNotFoundException, IllegalClassFormatException {
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
|
||||
CommunityBranchAgent.premain("ce", instrumentation);
|
||||
|
||||
ArgumentCaptor<ClassFileTransformer> classFileTransformerArgumentCaptor = ArgumentCaptor.forClass(ClassFileTransformer.class);
|
||||
verify(instrumentation).retransformClasses(PlatformEditionProvider.class);
|
||||
verify(instrumentation).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
verify(instrumentation, times(2)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
byte[] input = new byte[]{1, 2, 3, 4, 5, 6};
|
||||
byte[] result = classFileTransformerArgumentCaptor.getValue().transform(getClass().getClassLoader(), "com/github/mc1arke/Dummy", getClass(), getClass().getProtectionDomain(), input);
|
||||
@ -176,25 +176,38 @@ public class CommunityBranchAgentTest {
|
||||
assertThat(result).isEqualTo(input);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void checkRedefineForCeLaunchRedefinesTargetClass() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
void shouldRedefineTargetClassesForCeLaunch() throws ReflectiveOperationException, IOException, UnmodifiableClassException, IllegalClassFormatException {
|
||||
Instrumentation instrumentation = mock(Instrumentation.class);
|
||||
|
||||
CommunityBranchAgent.premain("ce", instrumentation);
|
||||
|
||||
ArgumentCaptor<ClassFileTransformer> classFileTransformerArgumentCaptor = ArgumentCaptor.forClass(ClassFileTransformer.class);
|
||||
verify(instrumentation).retransformClasses(MultipleAlmFeature.class);
|
||||
verify(instrumentation).retransformClasses(PlatformEditionProvider.class);
|
||||
verify(instrumentation).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
verify(instrumentation, times(2)).addTransformer(classFileTransformerArgumentCaptor.capture());
|
||||
|
||||
try (InputStream inputStream = PlatformEditionProvider.class.getResourceAsStream(PlatformEditionProvider.class.getSimpleName() + ".class")) {
|
||||
byte[] input = IOUtils.toByteArray(inputStream);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getValue().transform(getClass().getClassLoader(), PlatformEditionProvider.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(0).transform(getClass().getClassLoader(), PlatformEditionProvider.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
|
||||
CustomClassloader classLoader = new CustomClassloader();
|
||||
|
||||
Class<EditionProvider> redefined = (Class<EditionProvider>) classLoader.loadClass(PlatformEditionProvider.class.getName(), result);
|
||||
assertThat(redefined.getConstructor().newInstance().get()).isEqualTo(Optional.of(EditionProvider.Edition.DEVELOPER));
|
||||
assertThat(redefined.getConstructor().newInstance().get()).contains(EditionProvider.Edition.DEVELOPER);
|
||||
}
|
||||
|
||||
try (InputStream inputStream = MultipleAlmFeature.class.getResourceAsStream(MultipleAlmFeature.class.getSimpleName() + ".class")) {
|
||||
byte[] input = IOUtils.toByteArray(inputStream);
|
||||
byte[] result = classFileTransformerArgumentCaptor.getAllValues().get(1).transform(getClass().getClassLoader(), MultipleAlmFeature.class.getName().replaceAll("\\.", "/"), getClass(), getClass().getProtectionDomain(), input);
|
||||
|
||||
CustomClassloader classLoader = new CustomClassloader();
|
||||
|
||||
SonarRuntime sonarRuntime = mock(SonarRuntime.class);
|
||||
|
||||
Class<MultipleAlmFeature> redefined = (Class<MultipleAlmFeature>) classLoader.loadClass(MultipleAlmFeature.class.getName(), result);
|
||||
SonarQubeFeature multipleAlmFeatureProvider = redefined.getConstructor(SonarRuntime.class).newInstance(sonarRuntime);
|
||||
assertThat(multipleAlmFeatureProvider.isEnabled()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +217,6 @@ public class CommunityBranchAgentTest {
|
||||
return defineClass(name, value, 0, value.length);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,26 +18,7 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.ce.CommunityReportAnalysisComponentProvider;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchConfigurationLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchParamsValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectBranchesLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectPullRequestsLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.sonar.api.Plugin;
|
||||
import org.sonar.api.SonarQubeSide;
|
||||
import org.sonar.core.extension.CoreExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
@ -45,20 +26,31 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.sonar.api.Plugin;
|
||||
import org.sonar.api.SonarQubeSide;
|
||||
import org.sonar.core.extension.CoreExtension;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.ce.CommunityReportAnalysisComponentProvider;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchConfigurationLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchParamsValidator;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectBranchesLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectPullRequestsLoader;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
*/
|
||||
public class CommunityBranchPluginTest {
|
||||
|
||||
private final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException() {
|
||||
return expectedException;
|
||||
}
|
||||
class CommunityBranchPluginTest {
|
||||
|
||||
@Test
|
||||
public void testScannerSideDefine() {
|
||||
void shouldDefineClassesForScannerSide() {
|
||||
final CommunityBranchPlugin testCase = new CommunityBranchPlugin();
|
||||
|
||||
final Plugin.Context context = mock(Plugin.Context.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
@ -71,13 +63,12 @@ public class CommunityBranchPluginTest {
|
||||
.addExtensions(argumentCaptor.capture(), argumentCaptor.capture(), argumentCaptor.capture());
|
||||
|
||||
|
||||
assertEquals(Arrays.asList(CommunityProjectBranchesLoader.class, CommunityProjectPullRequestsLoader.class,
|
||||
CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class),
|
||||
argumentCaptor.getAllValues().subList(0, 4));
|
||||
assertThat(argumentCaptor.getAllValues().subList(0, 4)).isEqualTo(Arrays.asList(CommunityProjectBranchesLoader.class, CommunityProjectPullRequestsLoader.class,
|
||||
CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonScannerSideDefine() {
|
||||
void shouldDefineClassesForServerSide() {
|
||||
final CommunityBranchPlugin testCase = new CommunityBranchPlugin();
|
||||
|
||||
final Plugin.Context context = mock(Plugin.Context.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
@ -89,7 +80,7 @@ public class CommunityBranchPluginTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeEngineSideLoad() {
|
||||
void shouldDefineClassesForComputeEngineSide() {
|
||||
final CommunityBranchPlugin testCase = new CommunityBranchPlugin();
|
||||
|
||||
final CoreExtension.Context context = mock(CoreExtension.Context.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
@ -97,17 +88,16 @@ public class CommunityBranchPluginTest {
|
||||
|
||||
testCase.load(context);
|
||||
|
||||
final ArgumentCaptor<Class> argumentCaptor = ArgumentCaptor.forClass(Class.class);
|
||||
final ArgumentCaptor<Class<?>> argumentCaptor = ArgumentCaptor.forClass(Class.class);
|
||||
verify(context, times(2)).addExtensions(argumentCaptor.capture(), argumentCaptor.capture());
|
||||
|
||||
|
||||
assertEquals(Collections.singletonList(CommunityReportAnalysisComponentProvider.class),
|
||||
argumentCaptor.getAllValues().subList(0, 1));
|
||||
assertThat(argumentCaptor.getAllValues().subList(0, 1)).isEqualTo(List.of(CommunityReportAnalysisComponentProvider.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testServerSideLoad() {
|
||||
void shouldAddExtensionsForServerSideLoad() {
|
||||
final CommunityBranchPlugin testCase = new CommunityBranchPlugin();
|
||||
|
||||
final CoreExtension.Context context = mock(CoreExtension.Context.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
@ -118,14 +108,13 @@ public class CommunityBranchPluginTest {
|
||||
final ArgumentCaptor<Object> argumentCaptor = ArgumentCaptor.forClass(Object.class);
|
||||
verify(context, times(2)).addExtensions(argumentCaptor.capture(), argumentCaptor.capture());
|
||||
|
||||
assertEquals(25, argumentCaptor.getAllValues().size());
|
||||
assertThat(argumentCaptor.getAllValues()).hasSize(29);
|
||||
|
||||
assertEquals(Arrays.asList(CommunityBranchFeatureExtension.class, CommunityBranchSupportDelegate.class),
|
||||
argumentCaptor.getAllValues().subList(0, 2));
|
||||
assertThat(argumentCaptor.getAllValues().subList(0, 2)).isEqualTo(List.of(CommunityBranchFeatureExtension.class, CommunityBranchSupportDelegate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoad() {
|
||||
void shouldNotAddAnyExtensionsForScannerSideLoad() {
|
||||
final CommunityBranchPlugin testCase = new CommunityBranchPlugin();
|
||||
|
||||
final CoreExtension.Context context = mock(CoreExtension.Context.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
@ -137,7 +126,7 @@ public class CommunityBranchPluginTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetName() {
|
||||
assertEquals("Community Branch Plugin", new CommunityBranchPlugin().getName());
|
||||
void shouldReturnPluginNameForGetName() {
|
||||
assertThat(new CommunityBranchPlugin().getName()).isEqualTo("Community Branch Plugin");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,76 +18,50 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.ce;
|
||||
|
||||
import org.hamcrest.core.IsEqual;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.db.component.BranchType;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
*/
|
||||
public class CommunityBranchTest {
|
||||
|
||||
private final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException() {
|
||||
return expectedException;
|
||||
}
|
||||
class CommunityBranchTest {
|
||||
|
||||
@Test
|
||||
public void testGenerateKeyMainBranchNullFileOfPath() {
|
||||
void testGenerateKeyMainBranchNullFileOfPath() {
|
||||
CommunityBranch testCase = new CommunityBranch("name", BranchType.PULL_REQUEST, true, null, null, null);
|
||||
|
||||
assertEquals("projectKey", testCase.generateKey("projectKey", null));
|
||||
assertThat(testCase.generateKey("projectKey", null)).isEqualTo("projectKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateKeyMainBranchNonNullFileOfPathHolder() {
|
||||
void testGenerateKeyMainBranchNonNullFileOfPathHolder() {
|
||||
CommunityBranch testCase = new CommunityBranch("name", BranchType.PULL_REQUEST, true, null, null, null);
|
||||
|
||||
assertEquals("projectKey", testCase.generateKey("projectKey", ""));
|
||||
assertThat(testCase.generateKey("projectKey", "")).isEqualTo("projectKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateKeyMainBranchNonNullFileOfPathContent() {
|
||||
void testGenerateKeyMainBranchNonNullFileOfPathContent() {
|
||||
CommunityBranch testCase = new CommunityBranch("name", BranchType.PULL_REQUEST, true, null, null, null);
|
||||
|
||||
assertEquals("projectKey:path", testCase.generateKey("projectKey", "path"));
|
||||
assertThat(testCase.generateKey("projectKey", "path")).isEqualTo("projectKey:path");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateKeyNonMainBranchNonNullFileOfPathContentPullRequest() {
|
||||
CommunityBranch testCase =
|
||||
new CommunityBranch("name", BranchType.PULL_REQUEST, false, null, "pullRequestKey", null);
|
||||
|
||||
assertEquals("projectKey:path:PULL_REQUEST:pullRequestKey", testCase.generateKey("projectKey", "path"));
|
||||
void testGetPulRequestKey() {
|
||||
assertThat(new CommunityBranch("name", BranchType.PULL_REQUEST, false, null, "prKey", null)
|
||||
.getPullRequestKey()).isEqualTo("prKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateKeyNonMainBranchNonNullFileOfPathContentBranch() {
|
||||
CommunityBranch testCase = new CommunityBranch("name", BranchType.BRANCH, false, null, null, null);
|
||||
|
||||
assertEquals("projectKey:path:BRANCH:name", testCase.generateKey("projectKey", "path"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetPulRequestKey() {
|
||||
assertEquals("prKey", new CommunityBranch("name", BranchType.PULL_REQUEST, false, null, "prKey", null)
|
||||
.getPullRequestKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPulRequestKeyNonPullRequest() {
|
||||
expectedException
|
||||
.expectMessage(IsEqual.equalTo("Only a branch of type PULL_REQUEST can have a pull request ID"));
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
|
||||
new CommunityBranch("name", BranchType.BRANCH, false, null, "prKey", null).getPullRequestKey();
|
||||
void testGetPulRequestKeyNonPullRequest() {
|
||||
CommunityBranch underTest = new CommunityBranch("name", BranchType.BRANCH, false, null, "prKey", null);
|
||||
assertThatThrownBy(underTest::getPullRequestKey)
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Only a branch of type PULL_REQUEST can have a pull request ID");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -95,11 +95,11 @@ public class GitlabMergeRequestDecoratorIntegrationTest {
|
||||
AlmSettingDto almSettingDto = mock(AlmSettingDto.class);
|
||||
when(almSettingDto.getDecryptedPersonalAccessToken(any())).thenReturn("token");
|
||||
when(almSettingDto.getUrl()).thenReturn(wireMockRule.baseUrl()+"/api/v4");
|
||||
when(projectAlmSettingDto.getAlmRepo()).thenReturn(repositorySlug);
|
||||
|
||||
AnalysisDetails analysisDetails = mock(AnalysisDetails.class);
|
||||
when(almSettingDto.getUrl()).thenReturn(wireMockRule.baseUrl()+"/api/v4");
|
||||
when(projectAlmSettingDto.getAlmRepo()).thenReturn(repositorySlug);
|
||||
when(projectAlmSettingDto.getMonorepo()).thenReturn(true);
|
||||
when(analysisDetails.getQualityGateStatus()).thenReturn(status);
|
||||
when(analysisDetails.getAnalysisProjectKey()).thenReturn(projectKey);
|
||||
when(analysisDetails.getPullRequestId()).thenReturn(Long.toString(mergeRequestIid));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Michael Clarke
|
||||
* Copyright (C) 2019-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,17 +18,24 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
*/
|
||||
public class CommunityBranchFeatureExtensionTest {
|
||||
class CommunityBranchFeatureExtensionTest {
|
||||
|
||||
private final CommunityBranchFeatureExtension underTest = new CommunityBranchFeatureExtension();
|
||||
|
||||
@Test
|
||||
public void testEnabled() {
|
||||
assertTrue(new CommunityBranchFeatureExtension().isEnabled());
|
||||
void shouldReturnNameThatFrontEndLooksFor() {
|
||||
assertThat(underTest.getName()).isEqualTo("branch-support");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnEnabledForFeature() {
|
||||
assertThat(underTest.isEnabled()).isTrue();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -18,114 +18,91 @@
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server;
|
||||
|
||||
import org.hamcrest.core.IsEqual;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.sonar.core.util.SequenceUuidFactory;
|
||||
import org.sonar.core.util.UuidFactory;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.ComponentDao;
|
||||
import org.sonar.db.component.ComponentDto;
|
||||
import org.sonar.server.ce.queue.BranchSupport;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.sonar.api.config.Configuration;
|
||||
import org.sonar.core.util.SequenceUuidFactory;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.DbSession;
|
||||
import org.sonar.db.component.BranchDao;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.ComponentDao;
|
||||
import org.sonar.db.component.ComponentDto;
|
||||
import org.sonar.server.ce.queue.BranchSupport;
|
||||
import org.sonar.server.setting.ProjectConfigurationLoader;
|
||||
|
||||
/**
|
||||
* @author Michael Clarke
|
||||
*/
|
||||
public class CommunityBranchSupportDelegateTest {
|
||||
class CommunityBranchSupportDelegateTest {
|
||||
|
||||
private final ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException() {
|
||||
return expectedException;
|
||||
}
|
||||
private final Clock clock = mock(Clock.class);
|
||||
private final SequenceUuidFactory sequenceUuidFactory = mock(SequenceUuidFactory.class);
|
||||
private final DbClient dbClient = mock(DbClient.class);
|
||||
private final ProjectConfigurationLoader projectConfigurationLoader = mock(ProjectConfigurationLoader.class);
|
||||
private final CommunityBranchSupportDelegate underTest = new CommunityBranchSupportDelegate(sequenceUuidFactory, dbClient, clock, projectConfigurationLoader);
|
||||
|
||||
@Test
|
||||
public void testCreateComponentKeyBranchType() {
|
||||
void shouldReturnValidComponentKeyForBranchParameters() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("branch", "release-1.1");
|
||||
params.put("branchType", "BRANCH");
|
||||
|
||||
BranchSupport.ComponentKey componentKey =
|
||||
new CommunityBranchSupportDelegate(new SequenceUuidFactory(), mock(DbClient.class), mock(Clock.class))
|
||||
.createComponentKey("yyy", params);
|
||||
BranchSupport.ComponentKey componentKey = underTest.createComponentKey("yyy", params);
|
||||
|
||||
assertEquals("yyy:BRANCH:release-1.1", componentKey.getDbKey());
|
||||
assertEquals("yyy", componentKey.getKey());
|
||||
assertFalse(componentKey.getPullRequestKey().isPresent());
|
||||
assertFalse(componentKey.isMainBranch());
|
||||
assertTrue(componentKey.getBranchName().isPresent());
|
||||
assertEquals("release-1.1", componentKey.getBranchName().get());
|
||||
assertTrue(componentKey.getMainBranchComponentKey().isMainBranch());
|
||||
assertThat(componentKey).usingRecursiveComparison().isEqualTo(new CommunityComponentKey("yyy", "release-1.1", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateComponentKeyPullRequest() {
|
||||
void shouldReturnValidComponentKeyForPullRequestParameters() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("pullRequest", "pullrequestkey");
|
||||
|
||||
CommunityComponentKey componentKey =
|
||||
new CommunityBranchSupportDelegate(new SequenceUuidFactory(), mock(DbClient.class), mock(Clock.class))
|
||||
.createComponentKey("yyy", params);
|
||||
assertEquals("yyy:PULL_REQUEST:pullrequestkey", componentKey.getDbKey());
|
||||
assertEquals("yyy", componentKey.getKey());
|
||||
assertTrue(componentKey.getPullRequestKey().isPresent());
|
||||
assertEquals("pullrequestkey", componentKey.getPullRequestKey().get());
|
||||
assertFalse(componentKey.isMainBranch());
|
||||
assertFalse(componentKey.getBranchName().isPresent());
|
||||
assertTrue(componentKey.getMainBranchComponentKey().isMainBranch());
|
||||
CommunityComponentKey mainBranchComponentKey = componentKey.getMainBranchComponentKey();
|
||||
assertSame(mainBranchComponentKey, mainBranchComponentKey.getMainBranchComponentKey());
|
||||
CommunityComponentKey componentKey = underTest.createComponentKey("aaa", params);
|
||||
|
||||
assertThat(componentKey).usingRecursiveComparison().isEqualTo(new CommunityComponentKey("aaa", null, "pullrequestkey"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateComponentKeyMissingBranchTypeAndPullParameters() {
|
||||
void shouldThrowExceptionOnCreateComponentKeyMissingBranchTypeAndPullParameters() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException
|
||||
.expectMessage(IsEqual.equalTo("One of 'branchType' or 'pullRequest' parameters must be specified"));
|
||||
|
||||
new CommunityBranchSupportDelegate(new SequenceUuidFactory(), mock(DbClient.class), mock(Clock.class))
|
||||
.createComponentKey("xxx", params);
|
||||
assertThatThrownBy(() -> underTest.createComponentKey("xxx", params)).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("One of 'branchType' or 'pullRequest' parameters must be specified");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateComponentKeyInvalidBranchTypeParameter() {
|
||||
void shouldThrowExceptoinOnCreateComponentKeyInvalidBranchTypeParameter() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("branchType", "abc");
|
||||
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectMessage(IsEqual.equalTo("Unsupported branch type 'abc'"));
|
||||
|
||||
new CommunityBranchSupportDelegate(new SequenceUuidFactory(), mock(DbClient.class), mock(Clock.class))
|
||||
.createComponentKey("xxx", params);
|
||||
|
||||
assertThatThrownBy(() -> underTest.createComponentKey("xxx", params)).isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessage("Unsupported branch type 'abc'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBranchComponentComponentKeyComponentDtoKeyMismatch() {
|
||||
void shouldThrowExceptionIfBranchAndComponentKeysMismatch() {
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
|
||||
ComponentDto componentDto = mock(ComponentDto.class);
|
||||
@ -139,128 +116,34 @@ public class CommunityBranchSupportDelegateTest {
|
||||
when(branchDto.getUuid()).thenReturn("componentUuid");
|
||||
when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
|
||||
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.millis()).thenReturn(12345678901234L);
|
||||
|
||||
BranchSupport.ComponentKey componentKey = mock(BranchSupport.ComponentKey.class);
|
||||
when(componentKey.getKey()).thenReturn("componentKey");
|
||||
when(componentKey.getDbKey()).thenReturn("dbKey");
|
||||
when(componentKey.getBranchName()).thenReturn(Optional.of("dummy"));
|
||||
when(componentKey.getPullRequestKey()).thenReturn(Optional.empty());
|
||||
|
||||
ComponentDao componentDao = spy(mock(ComponentDao.class));
|
||||
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
when(dbClient.componentDao()).thenReturn(componentDao);
|
||||
|
||||
UuidFactory uuidFactory = new SequenceUuidFactory();
|
||||
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(IsEqual.equalTo("Component Key and Main Component Key do not match"));
|
||||
|
||||
new CommunityBranchSupportDelegate(uuidFactory, dbClient, clock)
|
||||
.createBranchComponent(dbSession, componentKey, componentDto, branchDto);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBranchComponent() {
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
|
||||
ComponentDto componentDto = mock(ComponentDto.class);
|
||||
when(componentDto.getKey()).thenReturn("componentKey");
|
||||
when(componentDto.uuid()).thenReturn("componentUuid");
|
||||
|
||||
ComponentDto copyComponentDto = spy(ComponentDto.class);
|
||||
when(componentDto.copy()).thenReturn(copyComponentDto);
|
||||
|
||||
BranchDto branchDto = mock(BranchDto.class);
|
||||
when(branchDto.getUuid()).thenReturn("componentUuid");
|
||||
when(branchDto.getKey()).thenReturn("nonDummy");
|
||||
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.millis()).thenReturn(12345678901234L);
|
||||
|
||||
BranchSupport.ComponentKey componentKey = mock(BranchSupport.ComponentKey.class);
|
||||
when(componentKey.getKey()).thenReturn("componentKey");
|
||||
when(componentKey.getDbKey()).thenReturn("dbKey");
|
||||
when(componentKey.getBranchName()).thenReturn(Optional.of("dummy"));
|
||||
when(componentKey.getPullRequestKey()).thenReturn(Optional.empty());
|
||||
|
||||
ComponentDao componentDao = mock(ComponentDao.class);
|
||||
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
when(dbClient.componentDao()).thenReturn(componentDao);
|
||||
|
||||
UuidFactory uuidFactory = mock(UuidFactory.class);
|
||||
when(uuidFactory.create()).then(new Answer<String>() {
|
||||
private int i = 0;
|
||||
|
||||
@Override
|
||||
public String answer(InvocationOnMock invocationOnMock) {
|
||||
return "uuid" + (i++);
|
||||
}
|
||||
});
|
||||
|
||||
ComponentDto result = new CommunityBranchSupportDelegate(uuidFactory, dbClient, clock)
|
||||
.createBranchComponent(dbSession, componentKey, componentDto, branchDto);
|
||||
|
||||
verify(componentDao).insert(dbSession, copyComponentDto);
|
||||
verify(copyComponentDto).setUuid("uuid0");
|
||||
verify(copyComponentDto).setProjectUuid("uuid0");
|
||||
verify(copyComponentDto).setRootUuid("uuid0");
|
||||
verify(copyComponentDto).setUuidPath(".");
|
||||
verify(copyComponentDto).setModuleUuidPath(".uuid0.");
|
||||
verify(copyComponentDto).setMainBranchProjectUuid("componentUuid");
|
||||
verify(copyComponentDto).setDbKey(componentKey.getDbKey());
|
||||
verify(copyComponentDto).setCreatedAt(new Date(12345678901234L));
|
||||
|
||||
assertSame(copyComponentDto, result);
|
||||
|
||||
assertThatThrownBy(() -> underTest.createBranchComponent(dbSession, componentKey, componentDto, branchDto)).isInstanceOf(IllegalStateException.class)
|
||||
.hasMessage("Component Key and Main Component Key do not match");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBranchComponentUseExistingDto() {
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
|
||||
ComponentDto componentDto = mock(ComponentDto.class);
|
||||
when(componentDto.getKey()).thenReturn("componentKey");
|
||||
when(componentDto.uuid()).thenReturn("componentUuid");
|
||||
|
||||
ComponentDto copyComponentDto = spy(ComponentDto.class);
|
||||
when(componentDto.copy()).thenReturn(copyComponentDto);
|
||||
|
||||
BranchDto branchDto = mock(BranchDto.class);
|
||||
when(branchDto.getUuid()).thenReturn("componentUuid");
|
||||
when(branchDto.getKey()).thenReturn("dummy");
|
||||
when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
|
||||
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.millis()).thenReturn(1234567890123L);
|
||||
|
||||
BranchSupport.ComponentKey componentKey = mock(BranchSupport.ComponentKey.class);
|
||||
when(componentKey.getKey()).thenReturn("componentKey");
|
||||
when(componentKey.getDbKey()).thenReturn("dbKey");
|
||||
when(componentKey.getBranchName()).thenReturn(Optional.of("dummy"));
|
||||
when(componentKey.getPullRequestKey()).thenReturn(Optional.empty());
|
||||
|
||||
ComponentDao componentDao = spy(mock(ComponentDao.class));
|
||||
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
when(dbClient.componentDao()).thenReturn(componentDao);
|
||||
|
||||
UuidFactory uuidFactory = new SequenceUuidFactory();
|
||||
|
||||
ComponentDto result = new CommunityBranchSupportDelegate(uuidFactory, dbClient, clock)
|
||||
.createBranchComponent(dbSession, componentKey, componentDto, branchDto);
|
||||
|
||||
assertSame(componentDto, result);
|
||||
|
||||
static Stream<Arguments> shouldCreateComponentAndBranchDtoIfValidationPassesData() {
|
||||
return Stream.of(
|
||||
Arguments.of("branchName", null, BranchType.BRANCH, new String[0], false),
|
||||
Arguments.of(null, "pullRequestKey", BranchType.PULL_REQUEST, new String[0], false),
|
||||
Arguments.of("complex-name", null, BranchType.BRANCH, new String[]{"abc", "def", "comp.*"}, true)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateBranchComponentUseExistingDto2() {
|
||||
@MethodSource("shouldCreateComponentAndBranchDtoIfValidationPassesData")
|
||||
@ParameterizedTest
|
||||
void shouldCreateComponentAndBranchDtoIfValidationPasses(String branchName, String pullRequestKey, BranchType branchType,
|
||||
String[] retainBranchesConfiguration, boolean excludedFromPurge) {
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
|
||||
ComponentDto componentDto = mock(ComponentDto.class);
|
||||
@ -269,44 +152,58 @@ public class CommunityBranchSupportDelegateTest {
|
||||
|
||||
ComponentDto copyComponentDto = mock(ComponentDto.class);
|
||||
when(componentDto.copy()).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setBranchUuid(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setKey(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setRootUuid(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setUuidPath(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setModuleUuidPath(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setUuid(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setMainBranchProjectUuid(any())).thenReturn(copyComponentDto);
|
||||
when(copyComponentDto.setCreatedAt(any())).thenReturn(copyComponentDto);
|
||||
|
||||
BranchDto branchDto = mock(BranchDto.class);
|
||||
when(branchDto.getUuid()).thenReturn("componentUuid");
|
||||
when(branchDto.getKey()).thenReturn("dummy");
|
||||
when(branchDto.getBranchType()).thenReturn(BranchType.BRANCH);
|
||||
when(branchDto.getKey()).thenReturn("nonDummy");
|
||||
|
||||
Clock clock = mock(Clock.class);
|
||||
when(clock.millis()).thenReturn(1234567890123L);
|
||||
when(clock.millis()).thenReturn(12345678901234L);
|
||||
|
||||
BranchSupport.ComponentKey componentKey = mock(BranchSupport.ComponentKey.class);
|
||||
when(componentKey.getKey()).thenReturn("componentKey");
|
||||
when(componentKey.getDbKey()).thenReturn("dbKey");
|
||||
when(componentKey.getBranchName()).thenReturn(Optional.empty());
|
||||
when(componentKey.getPullRequestKey()).thenReturn(Optional.empty());
|
||||
when(componentKey.getBranchName()).thenReturn(Optional.ofNullable(branchName));
|
||||
when(componentKey.getPullRequestKey()).thenReturn(Optional.ofNullable(pullRequestKey));
|
||||
|
||||
BranchDao branchDao = mock(BranchDao.class);
|
||||
ComponentDao componentDao = mock(ComponentDao.class);
|
||||
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
when(dbClient.componentDao()).thenReturn(componentDao);
|
||||
when(dbClient.branchDao()).thenReturn(branchDao);
|
||||
|
||||
UuidFactory uuidFactory = new SequenceUuidFactory();
|
||||
when(sequenceUuidFactory.create()).thenReturn("uuid0");
|
||||
|
||||
ComponentDto result = new CommunityBranchSupportDelegate(uuidFactory, dbClient, clock)
|
||||
.createBranchComponent(dbSession, componentKey, componentDto, branchDto);
|
||||
Configuration configuration = mock(Configuration.class);
|
||||
when(configuration.getStringArray(any())).thenReturn(retainBranchesConfiguration);
|
||||
when(projectConfigurationLoader.loadProjectConfiguration(any(), any())).thenReturn(configuration);
|
||||
|
||||
ComponentDto result = underTest.createBranchComponent(dbSession, componentKey, componentDto, branchDto);
|
||||
|
||||
verify(componentDao).insert(dbSession, copyComponentDto);
|
||||
verify(copyComponentDto).setUuid("1");
|
||||
verify(copyComponentDto).setProjectUuid("1");
|
||||
verify(copyComponentDto).setRootUuid("1");
|
||||
verify(copyComponentDto).setUuid("uuid0");
|
||||
verify(copyComponentDto).setRootUuid("uuid0");
|
||||
verify(copyComponentDto).setUuidPath(".");
|
||||
verify(copyComponentDto).setModuleUuidPath(".1.");
|
||||
verify(copyComponentDto).setModuleUuidPath(".uuid0.");
|
||||
verify(copyComponentDto).setMainBranchProjectUuid("componentUuid");
|
||||
verify(copyComponentDto).setDbKey(componentKey.getDbKey());
|
||||
verify(copyComponentDto).setCreatedAt(new Date(1234567890123L));
|
||||
verify(copyComponentDto).setCreatedAt(new Date(12345678901234L));
|
||||
|
||||
assertSame(copyComponentDto, result);
|
||||
assertThat(result).isSameAs(copyComponentDto);
|
||||
|
||||
ArgumentCaptor<BranchDto> branchDtoArgumentCaptor = ArgumentCaptor.forClass(BranchDto.class);
|
||||
verify(branchDao).insert(eq(dbSession), branchDtoArgumentCaptor.capture());
|
||||
|
||||
assertThat(branchDtoArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(new BranchDto()
|
||||
.setBranchType(branchType)
|
||||
.setExcludeFromPurge(excludedFromPurge)
|
||||
.setProjectUuid("componentUuid")
|
||||
.setKey(branchType == BranchType.BRANCH ? branchName : pullRequestKey)
|
||||
.setUuid("uuid0"));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class MonoRepoFeatureTest {
|
||||
|
||||
private final MonoRepoFeature underTest = new MonoRepoFeature();
|
||||
|
||||
@Test
|
||||
void shouldMatchNameRequiredByFrontEnd() {
|
||||
assertThat(underTest.getName()).isEqualTo("monorepo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetFeatureAsEnabled() {
|
||||
assertThat(underTest.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,27 @@
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
@ -13,43 +34,38 @@ import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class DeleteBindingActionTest {
|
||||
class DeleteBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testDefine() {
|
||||
void shouldDefineEndpointWithParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
DeleteBindingAction testCase = new DeleteBindingAction(dbClient, userSession, componentFinder);
|
||||
|
||||
WebService.NewParam keyParam = mock(WebService.NewParam.class);
|
||||
when(keyParam.setMaximumLength(eq(200))).thenReturn(keyParam);
|
||||
when(keyParam.setMaximumLength(200)).thenReturn(keyParam);
|
||||
WebService.NewParam newKeyParam = mock(WebService.NewParam.class);
|
||||
when(newKeyParam.setMaximumLength(eq(200))).thenReturn(newKeyParam);
|
||||
when(newKeyParam.setMaximumLength(200)).thenReturn(newKeyParam);
|
||||
WebService.NewController newController = mock(WebService.NewController.class);
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newController.createAction(eq("delete_binding"))).thenReturn(newAction);
|
||||
when(newAction.setPost(eq(true))).thenReturn(newAction);
|
||||
when(newAction.setHandler(eq(testCase))).thenReturn(newAction);
|
||||
when(newAction.createParam(eq("project"))).thenReturn(keyParam);
|
||||
when(newController.createAction("delete_binding")).thenReturn(newAction);
|
||||
when(newAction.setPost(true)).thenReturn(newAction);
|
||||
when(newAction.setHandler(testCase)).thenReturn(newAction);
|
||||
when(newAction.createParam("project")).thenReturn(keyParam);
|
||||
|
||||
testCase.define(newController);
|
||||
|
||||
verify(newAction).setHandler(eq(testCase));
|
||||
verify(newAction).setHandler(testCase);
|
||||
verify(keyParam).setRequired(true);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandle() {
|
||||
void shouldHandleEndpointWithValidRequest() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
when(dbClient.openSession(eq(false))).thenReturn(dbSession);
|
||||
when(dbClient.openSession(false)).thenReturn(dbSession);
|
||||
AlmSettingDao almSettingDao = mock(AlmSettingDao.class);
|
||||
when(dbClient.almSettingDao()).thenReturn(almSettingDao);
|
||||
|
||||
@ -60,18 +76,18 @@ public class DeleteBindingActionTest {
|
||||
|
||||
ProjectDto componentDto = mock(ProjectDto.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
when(componentFinder.getProjectByKey(eq(dbSession), eq("projectKey"))).thenReturn(componentDto);
|
||||
when(componentFinder.getProjectByKey(dbSession, "projectKey")).thenReturn(componentDto);
|
||||
|
||||
DeleteBindingAction testCase = new DeleteBindingAction(dbClient, userSession, componentFinder);
|
||||
|
||||
Request request = mock(Request.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
when(request.param("project")).thenReturn("projectKey");
|
||||
when(request.mandatoryParam("project")).thenReturn("projectKey");
|
||||
Response response = mock(Response.class, Mockito.RETURNS_DEEP_STUBS);
|
||||
|
||||
testCase.handle(request, response);
|
||||
|
||||
verify(dbSession).commit();
|
||||
verify(projectAlmSettingDao).deleteByProject(eq(dbSession), eq(componentDto));
|
||||
verify(projectAlmSettingDao).deleteByProject(dbSession, componentDto);
|
||||
verify(response).noContent();
|
||||
verify(userSession).checkProjectPermission("admin", componentDto);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
@ -33,15 +33,16 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetAzureBindingActionTest {
|
||||
class SetAzureBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureAction() {
|
||||
void shouldDefineActionWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
WebService.NewParam repositoryNameParameter = mock(WebService.NewParam.class);
|
||||
when(repositoryNameParameter.setMaximumLength(any(Integer.class))).thenReturn(repositoryNameParameter);
|
||||
@ -58,16 +59,23 @@ public class SetAzureBindingActionTest {
|
||||
when(almSettingParameter.setRequired(anyBoolean())).thenReturn(almSettingParameter);
|
||||
when(newAction.createParam("almSetting")).thenReturn(almSettingParameter);
|
||||
|
||||
WebService.NewParam monoRepoParameter = mock(WebService.NewParam.class);
|
||||
when(monoRepoParameter.setRequired(anyBoolean())).thenReturn(monoRepoParameter);
|
||||
when(newAction.createParam("monorepo")).thenReturn(monoRepoParameter);
|
||||
|
||||
SetAzureBindingAction testCase = new SetAzureBindingAction(dbClient, componentFinder, userSession);
|
||||
testCase.configureAction(newAction);
|
||||
|
||||
verify(newAction).setPost(true);
|
||||
verify(repositoryNameParameter).setRequired(true);
|
||||
verify(projectNameParameter).setRequired(true);
|
||||
verify(almSettingParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectAlmSettingDto() {
|
||||
void shouldHandleRequestWithValidParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
@ -77,9 +85,9 @@ public class SetAzureBindingActionTest {
|
||||
when(request.mandatoryParam("projectName")).thenReturn("project");
|
||||
|
||||
SetAzureBindingAction testCase = new SetAzureBindingAction(dbClient, componentFinder, userSession);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", request);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", true, request);
|
||||
|
||||
assertThat(result).isEqualToComparingFieldByField(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setAlmSlug("project").setMonorepo(false));
|
||||
assertThat(result).usingRecursiveComparison().isEqualTo(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setAlmSlug("project").setMonorepo(true));
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +1,35 @@
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
/*
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
@ -14,21 +43,10 @@ import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetBindingActionTest {
|
||||
class SetBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testDefine() {
|
||||
void shouldDefineActionWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
@ -36,7 +54,7 @@ public class SetBindingActionTest {
|
||||
SetBindingAction testCase = new SetBindingAction(dbClient, componentFinder, userSession, "dummy") {
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, Request request) {
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, boolean monoRepo, Request request) {
|
||||
return projectAlmSettingDto;
|
||||
}
|
||||
};
|
||||
@ -46,37 +64,40 @@ public class SetBindingActionTest {
|
||||
WebService.NewController newController = mock(WebService.NewController.class);
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newController.createAction(any())).thenReturn(newAction);
|
||||
when(newAction.setPost(eq(true))).thenReturn(newAction);
|
||||
when(newAction.setHandler(eq(testCase))).thenReturn(newAction);
|
||||
when(newAction.setPost(true)).thenReturn(newAction);
|
||||
when(newAction.setHandler(testCase)).thenReturn(newAction);
|
||||
when(newAction.createParam(any())).then(i -> {
|
||||
WebService.NewParam newParam = mock(WebService.NewParam.class);
|
||||
paramMap.put(i.getArgument(0), newParam);
|
||||
when(newParam.setRequired(anyBoolean())).thenReturn(newParam);
|
||||
return newParam;
|
||||
});
|
||||
testCase.define(newController);
|
||||
|
||||
verify(newAction).createParam(eq("project"));
|
||||
verify(newAction).createParam(eq("almSetting"));
|
||||
verify(newAction).createParam("project");
|
||||
verify(newAction).createParam("almSetting");
|
||||
verify(paramMap.get("project")).setRequired(true);
|
||||
verify(paramMap.get("almSetting")).setRequired(true);
|
||||
verify(paramMap.get("monorepo")).setRequired(true);
|
||||
verify(paramMap.get("monorepo")).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandle() {
|
||||
void shouldHandleRequestWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
DbSession dbSession = mock(DbSession.class);
|
||||
when(dbClient.openSession(eq(false))).thenReturn(dbSession);
|
||||
when(dbClient.openSession(false)).thenReturn(dbSession);
|
||||
AlmSettingDao almSettingDao = mock(AlmSettingDao.class);
|
||||
AlmSettingDto almSettingDto = mock(AlmSettingDto.class);
|
||||
when(almSettingDto.getUuid()).thenReturn("almSettingsUuid");
|
||||
when(almSettingDao.selectByKey(eq(dbSession), eq("almSetting"))).thenReturn(Optional.of(almSettingDto));
|
||||
when(almSettingDao.selectByKey(dbSession, "almSetting")).thenReturn(Optional.of(almSettingDto));
|
||||
when(dbClient.almSettingDao()).thenReturn(almSettingDao);
|
||||
ProjectAlmSettingDao projectAlmSettingDao = mock(ProjectAlmSettingDao.class);
|
||||
when(dbClient.projectAlmSettingDao()).thenReturn(projectAlmSettingDao);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
ProjectDto componentDto = mock(ProjectDto.class);
|
||||
when(componentDto.getUuid()).thenReturn("projectUuid");
|
||||
when(componentFinder.getProjectByKey(eq(dbSession), eq("project"))).thenReturn(componentDto);
|
||||
when(componentFinder.getProjectByKey(dbSession, "project")).thenReturn(componentDto);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ThreadLocal<WebService.NewAction> capturedAction = new ThreadLocal<>();
|
||||
ProjectAlmSettingDto projectAlmSettingDto = mock(ProjectAlmSettingDto.class);
|
||||
@ -88,7 +109,7 @@ public class SetBindingActionTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, Request request) {
|
||||
protected ProjectAlmSettingDto createProjectAlmSettingDto(String projectUuid, String settingsUuid, boolean monoRepo, Request request) {
|
||||
assertThat(projectUuid).isEqualTo("projectUuid");
|
||||
assertThat(settingsUuid).isEqualTo("almSettingsUuid");
|
||||
return projectAlmSettingDto;
|
||||
@ -99,7 +120,7 @@ public class SetBindingActionTest {
|
||||
Response response = mock(Response.class);
|
||||
|
||||
when(request.mandatoryParam("almSetting")).thenReturn("almSetting");
|
||||
when(request.param("project")).thenReturn("project");
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
|
||||
testCase.handle(request, response);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
@ -33,15 +33,16 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetBitBucketBindingActionTest {
|
||||
class SetBitBucketBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureAction() {
|
||||
void shouldDefineActionWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
WebService.NewParam slugParameter = mock(WebService.NewParam.class);
|
||||
when(slugParameter.setMaximumLength(any(Integer.class))).thenReturn(slugParameter);
|
||||
@ -58,18 +59,26 @@ public class SetBitBucketBindingActionTest {
|
||||
when(almSettingParameter.setRequired(anyBoolean())).thenReturn(almSettingParameter);
|
||||
when(newAction.createParam("almSetting")).thenReturn(almSettingParameter);
|
||||
|
||||
WebService.NewParam monoRepoParameter = mock(WebService.NewParam.class);
|
||||
when(monoRepoParameter.setRequired(anyBoolean())).thenReturn(monoRepoParameter);
|
||||
when(newAction.createParam("monorepo")).thenReturn(monoRepoParameter);
|
||||
|
||||
SetBitbucketBindingAction testCase = new SetBitbucketBindingAction(dbClient, componentFinder, userSession);
|
||||
testCase.configureAction(newAction);
|
||||
|
||||
verify(newAction).setPost(true);
|
||||
verify(slugParameter).setRequired(true);
|
||||
|
||||
verify(repositoryParameter).setRequired(true);
|
||||
|
||||
verify(almSettingParameter).setRequired(true);
|
||||
|
||||
verify(monoRepoParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectAlmSettingDto() {
|
||||
void shouldHandleRequestWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
@ -79,9 +88,9 @@ public class SetBitBucketBindingActionTest {
|
||||
when(request.mandatoryParam("repository")).thenReturn("repository");
|
||||
|
||||
SetBitbucketBindingAction testCase = new SetBitbucketBindingAction(dbClient, componentFinder, userSession);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", request);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", true, request);
|
||||
|
||||
assertThat(result).isEqualToComparingFieldByField(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setAlmSlug("slug").setMonorepo(false));
|
||||
assertThat(result).usingRecursiveComparison().isEqualTo(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setAlmSlug("slug").setMonorepo(true));
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
@ -33,15 +33,16 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetBitBucketCloudBindingActionTest {
|
||||
class SetBitBucketCloudBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureAction() {
|
||||
void shouldDefineActionWithValidParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
WebService.NewParam repositoryParameter = mock(WebService.NewParam.class);
|
||||
when(repositoryParameter.setMaximumLength(any(Integer.class))).thenReturn(repositoryParameter);
|
||||
@ -53,16 +54,24 @@ public class SetBitBucketCloudBindingActionTest {
|
||||
when(almSettingParameter.setRequired(anyBoolean())).thenReturn(almSettingParameter);
|
||||
when(newAction.createParam("almSetting")).thenReturn(almSettingParameter);
|
||||
|
||||
WebService.NewParam monoRepoParameter = mock(WebService.NewParam.class);
|
||||
when(monoRepoParameter.setRequired(anyBoolean())).thenReturn(monoRepoParameter);
|
||||
when(newAction.createParam("monorepo")).thenReturn(monoRepoParameter);
|
||||
|
||||
SetBitbucketCloudBindingAction testCase = new SetBitbucketCloudBindingAction(dbClient, componentFinder, userSession);
|
||||
testCase.configureAction(newAction);
|
||||
|
||||
verify(newAction).setPost(true);
|
||||
verify(repositoryParameter).setRequired(true);
|
||||
|
||||
verify(almSettingParameter).setRequired(true);
|
||||
|
||||
verify(monoRepoParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectAlmSettingDto() {
|
||||
void shouldHandleRequestWithValidParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
@ -71,9 +80,9 @@ public class SetBitBucketCloudBindingActionTest {
|
||||
when(request.mandatoryParam("repository")).thenReturn("repository");
|
||||
|
||||
SetBitbucketCloudBindingAction testCase = new SetBitbucketCloudBindingAction(dbClient, componentFinder, userSession);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", request);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", true, request);
|
||||
|
||||
assertThat(result).isEqualToComparingFieldByField(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setMonorepo(false));
|
||||
assertThat(result).usingRecursiveComparison().isEqualTo(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setMonorepo(true));
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
@ -33,15 +33,16 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetGithubBindingActionTest {
|
||||
class SetGithubBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureAction() {
|
||||
void shouldDefineActionWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
WebService.NewParam repositoryParameter = mock(WebService.NewParam.class);
|
||||
when(repositoryParameter.setMaximumLength(any(Integer.class))).thenReturn(repositoryParameter);
|
||||
@ -58,15 +59,22 @@ public class SetGithubBindingActionTest {
|
||||
when(almSettingParameter.setRequired(anyBoolean())).thenReturn(almSettingParameter);
|
||||
when(newAction.createParam("almSetting")).thenReturn(almSettingParameter);
|
||||
|
||||
WebService.NewParam monoRepoParameter = mock(WebService.NewParam.class);
|
||||
when(monoRepoParameter.setRequired(anyBoolean())).thenReturn(monoRepoParameter);
|
||||
when(newAction.createParam("monorepo")).thenReturn(monoRepoParameter);
|
||||
|
||||
SetGithubBindingAction testCase = new SetGithubBindingAction(dbClient, componentFinder, userSession);
|
||||
testCase.configureAction(newAction);
|
||||
|
||||
verify(newAction).setPost(true);
|
||||
verify(repositoryParameter).setRequired(true);
|
||||
verify(almSettingParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectAlmSettingDto() {
|
||||
void shouldHandleRequestWithRequiredParmaeters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
@ -76,9 +84,9 @@ public class SetGithubBindingActionTest {
|
||||
when(request.paramAsBoolean("summaryCommentEnabled")).thenReturn(true);
|
||||
|
||||
SetGithubBindingAction testCase = new SetGithubBindingAction(dbClient, componentFinder, userSession);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", request);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", true, request);
|
||||
|
||||
assertThat(result).isEqualToComparingFieldByField(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setSummaryCommentEnabled(true).setMonorepo(false));
|
||||
assertThat(result).usingRecursiveComparison().isEqualTo(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repository").setSummaryCommentEnabled(true).setMonorepo(true));
|
||||
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Michael Clarke
|
||||
* Copyright (C) 2020-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
@ -33,15 +33,16 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SetGitlabBindingActionTest {
|
||||
class SetGitlabBindingActionTest {
|
||||
|
||||
@Test
|
||||
public void testConfigureAction() {
|
||||
void shouldDefineActionWithRequiredParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
WebService.NewParam repositoryParameter = mock(WebService.NewParam.class);
|
||||
when(newAction.createParam("repository")).thenReturn(repositoryParameter);
|
||||
@ -50,16 +51,23 @@ public class SetGitlabBindingActionTest {
|
||||
when(almSettingParameter.setRequired(anyBoolean())).thenReturn(almSettingParameter);
|
||||
when(newAction.createParam("almSetting")).thenReturn(almSettingParameter);
|
||||
|
||||
WebService.NewParam monoRepoParameter = mock(WebService.NewParam.class);
|
||||
when(monoRepoParameter.setRequired(anyBoolean())).thenReturn(monoRepoParameter);
|
||||
when(newAction.createParam("monorepo")).thenReturn(monoRepoParameter);
|
||||
|
||||
SetGitlabBindingAction testCase = new SetGitlabBindingAction(dbClient, componentFinder, userSession);
|
||||
testCase.configureAction(newAction);
|
||||
|
||||
verify(newAction).createParam("repository");
|
||||
verify(newAction).setPost(true);
|
||||
|
||||
verify(almSettingParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setRequired(true);
|
||||
verify(monoRepoParameter).setBooleanPossibleValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateProjectAlmSettingDto() {
|
||||
void shouldHandleRequestWithValidParameters() {
|
||||
DbClient dbClient = mock(DbClient.class);
|
||||
UserSession userSession = mock(UserSession.class);
|
||||
ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
@ -68,9 +76,9 @@ public class SetGitlabBindingActionTest {
|
||||
when(request.param("repository")).thenReturn("repositoryId");
|
||||
|
||||
SetGitlabBindingAction testCase = new SetGitlabBindingAction(dbClient, componentFinder, userSession);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", request);
|
||||
ProjectAlmSettingDto result = testCase.createProjectAlmSettingDto("projectUuid", "settingsUuid", true, request);
|
||||
|
||||
assertThat(result).isEqualToComparingFieldByField(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repositoryId").setMonorepo(false));
|
||||
assertThat(result).usingRecursiveComparison().isEqualTo(new ProjectAlmSettingDto().setProjectUuid("projectUuid").setAlmSettingUuid("settingsUuid").setAlmRepo("repositoryId").setMonorepo(true));
|
||||
verify(request).param("repository");
|
||||
verifyNoMoreInteractions(request);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Michael Clarke
|
||||
* Copyright (C) 2021-2022 Michael Clarke
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -16,7 +16,7 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.action;
|
||||
package com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.binding.action;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.InvalidConfigurationException;
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.validator.Validator;
|
||||
@ -198,7 +198,7 @@ class ValidateBindingActionTest {
|
||||
when(almSettingDao.selectByUuid(dbSession, almUuid)).thenReturn(Optional.of(almSettingDto));
|
||||
when(dbClient.almSettingDao()).thenReturn(almSettingDao);
|
||||
|
||||
when(request.param("project")).thenReturn("project");
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
|
||||
underTest.handle(request, response);
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest;
|
||||
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
|
||||
import com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action.PullRequestWsAction;
|
||||
|
||||
class PullRequestWsTest {
|
||||
|
||||
@Test
|
||||
void shouldCallDefineOnEachAction() {
|
||||
PullRequestWsAction[] pullRequestWsActions = new PullRequestWsAction[]{mock(PullRequestWsAction.class), mock(PullRequestWsAction.class), mock(PullRequestWsAction.class)};
|
||||
|
||||
WebService.Context context = mock(WebService.Context.class);
|
||||
WebService.NewController controller = mock(WebService.NewController.class);
|
||||
when(context.createController(any())).thenReturn(controller);
|
||||
|
||||
new PullRequestWs(pullRequestWsActions).define(context);
|
||||
|
||||
for (PullRequestWsAction pullRequestWsAction : pullRequestWsActions) {
|
||||
verify(pullRequestWsAction).define(controller);
|
||||
}
|
||||
verify(context).createController("api/project_pull_requests");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.component.BranchDao;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.server.component.ComponentCleanerService;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.exceptions.UnauthorizedException;
|
||||
import org.sonar.server.user.UserSession;
|
||||
|
||||
class DeleteActionTest {
|
||||
|
||||
private final DbClient dbClient = mock(DbClient.class);
|
||||
private final UserSession userSession = mock(UserSession.class);
|
||||
private final ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
private final ComponentCleanerService componentCleanerService = mock(ComponentCleanerService.class);
|
||||
private final DeleteAction underTest = new DeleteAction(dbClient, componentFinder, userSession, componentCleanerService);
|
||||
|
||||
@Test
|
||||
void shouldDefineEndpointWithAllParameters() {
|
||||
WebService.NewController newController = mock(WebService.NewController.class);
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setHandler(any())).thenReturn(newAction);
|
||||
when(newController.createAction(any())).thenReturn(newAction);
|
||||
WebService.NewParam projectParam = mock(WebService.NewParam.class);
|
||||
WebService.NewParam pullRequestParam = mock(WebService.NewParam.class);
|
||||
when(newAction.createParam(any())).thenReturn(projectParam, pullRequestParam);
|
||||
|
||||
when(newAction.setPost(anyBoolean())).thenReturn(newAction);
|
||||
|
||||
underTest.define(newController);
|
||||
|
||||
verify(newController).createAction("delete");
|
||||
verify(newAction).setHandler(underTest);
|
||||
verify(newAction).createParam("project");
|
||||
verify(newAction).createParam("pullRequest");
|
||||
verify(newAction).setPost(true);
|
||||
verifyNoMoreInteractions(newAction);
|
||||
verify(projectParam).setRequired(true);
|
||||
verify(pullRequestParam).setRequired(true);
|
||||
verifyNoMoreInteractions(projectParam);
|
||||
verifyNoMoreInteractions(pullRequestParam);
|
||||
|
||||
verifyNoMoreInteractions(newController);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExecuteRequestWithValidParameters() {
|
||||
Request request = mock(Request.class);
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
when(request.mandatoryParam("pullRequest")).thenReturn("pullRequestId");
|
||||
|
||||
when(componentFinder.getProjectByKey(any(), any())).thenReturn(new ProjectDto().setKey("projectKey").setUuid("uuid0"));
|
||||
|
||||
when(userSession.checkLoggedIn()).thenReturn(userSession);
|
||||
|
||||
BranchDto pullRequest = new BranchDto().setBranchType(BranchType.PULL_REQUEST);
|
||||
BranchDao branchDao = mock(BranchDao.class);
|
||||
when(dbClient.branchDao()).thenReturn(branchDao);
|
||||
when(branchDao.selectByPullRequestKey(any(), any(), any())).thenReturn(Optional.of(pullRequest));
|
||||
|
||||
Response response = mock(Response.class);
|
||||
|
||||
underTest.handle(request, response);
|
||||
|
||||
verify(componentCleanerService).deleteBranch(any(), eq(pullRequest));
|
||||
verify(response).noContent();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotPerformDeleteIfUserNotLoggedIn() {
|
||||
Request request = mock(Request.class);
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
when(request.mandatoryParam("pullRequest")).thenReturn("pullRequestId");
|
||||
|
||||
when(componentFinder.getProjectByKey(any(), any())).thenReturn(new ProjectDto().setKey("projectKey").setUuid("uuid0"));
|
||||
|
||||
when(userSession.checkLoggedIn()).thenThrow(new UnauthorizedException("Dummy"));
|
||||
|
||||
Response response = mock(Response.class);
|
||||
|
||||
assertThatThrownBy(() -> underTest.handle(request, response)).isInstanceOf(UnauthorizedException.class).hasMessage("Dummy");
|
||||
|
||||
verify(componentCleanerService, never()).deleteBranch(any(), any());
|
||||
verify(response, never()).noContent();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotPerformDeleteIfUserNotProjectAdmin() {
|
||||
Request request = mock(Request.class);
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
when(request.mandatoryParam("pullRequest")).thenReturn("pullRequestId");
|
||||
|
||||
when(componentFinder.getProjectByKey(any(), any())).thenReturn(new ProjectDto().setKey("projectKey").setUuid("uuid0"));
|
||||
|
||||
when(userSession.checkLoggedIn()).thenReturn(userSession);
|
||||
when(userSession.checkProjectPermission(any(), any())).thenThrow(new UnauthorizedException("Dummy"));
|
||||
|
||||
Response response = mock(Response.class);
|
||||
|
||||
assertThatThrownBy(() -> underTest.handle(request, response)).isInstanceOf(UnauthorizedException.class).hasMessage("Dummy");
|
||||
|
||||
verify(componentCleanerService, never()).deleteBranch(any(), any());
|
||||
verify(response, never()).noContent();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (C) 2022 Michael Clarke
|
||||
*
|
||||
* 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 com.github.mc1arke.sonarqube.plugin.server.pullrequest.ws.pullrequest.action;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.sonar.api.server.ws.Request;
|
||||
import org.sonar.api.server.ws.Response;
|
||||
import org.sonar.api.server.ws.WebService;
|
||||
import org.sonar.db.DbClient;
|
||||
import org.sonar.db.component.BranchDao;
|
||||
import org.sonar.db.component.BranchDto;
|
||||
import org.sonar.db.component.BranchType;
|
||||
import org.sonar.db.component.SnapshotDao;
|
||||
import org.sonar.db.component.SnapshotDto;
|
||||
import org.sonar.db.measure.LiveMeasureDao;
|
||||
import org.sonar.db.measure.LiveMeasureDto;
|
||||
import org.sonar.db.project.ProjectDto;
|
||||
import org.sonar.db.protobuf.DbProjectBranches;
|
||||
import org.sonar.scanner.protocol.output.ScannerReport;
|
||||
import org.sonar.server.component.ComponentFinder;
|
||||
import org.sonar.server.exceptions.ForbiddenException;
|
||||
import org.sonar.server.issue.index.IssueIndex;
|
||||
import org.sonar.server.issue.index.PrStatistics;
|
||||
import org.sonar.server.user.UserSession;
|
||||
import org.sonarqube.ws.ProjectPullRequests;
|
||||
|
||||
class ListActionTest {
|
||||
|
||||
private final DbClient dbClient = mock(DbClient.class);
|
||||
private final UserSession userSession = mock(UserSession.class);
|
||||
private final ComponentFinder componentFinder = mock(ComponentFinder.class);
|
||||
private final IssueIndex issueIndex = mock(IssueIndex.class);
|
||||
private final ProtoBufWriter protoBufWriter = mock(ProtoBufWriter.class);
|
||||
private final ListAction underTest = new ListAction(dbClient, componentFinder, userSession, issueIndex, protoBufWriter);
|
||||
|
||||
@Test
|
||||
void shouldDefineEndpointWithProjectParameter() {
|
||||
WebService.NewController newController = mock(WebService.NewController.class);
|
||||
WebService.NewAction newAction = mock(WebService.NewAction.class);
|
||||
when(newAction.setHandler(any())).thenReturn(newAction);
|
||||
when(newController.createAction(any())).thenReturn(newAction);
|
||||
WebService.NewParam projectParam = mock(WebService.NewParam.class);
|
||||
when(newAction.createParam(any())).thenReturn(projectParam);
|
||||
|
||||
underTest.define(newController);
|
||||
|
||||
verify(newController).createAction("list");
|
||||
verify(newAction).setHandler(underTest);
|
||||
verify(newAction).createParam("project");
|
||||
verifyNoMoreInteractions(newAction);
|
||||
verify(projectParam).setRequired(true);
|
||||
verifyNoMoreInteractions(projectParam);
|
||||
|
||||
verifyNoMoreInteractions(newController);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExecuteRequestWithValidParameter() {
|
||||
Request request = mock(Request.class);
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
|
||||
when(componentFinder.getProjectByKey(any(), any())).thenReturn(new ProjectDto().setKey("projectKey").setUuid("uuid0"));
|
||||
|
||||
when(userSession.hasPermission(any())).thenReturn(true);
|
||||
|
||||
BranchDao branchDao = mock(BranchDao.class);
|
||||
when(dbClient.branchDao()).thenReturn(branchDao);
|
||||
when(branchDao.selectByProject(any(), any())).thenReturn(List.of(new BranchDto()
|
||||
.setBranchType(BranchType.PULL_REQUEST)
|
||||
.setKey("prKey")
|
||||
.setUuid("uuid1")
|
||||
.setMergeBranchUuid("uuid2")
|
||||
.setPullRequestData(DbProjectBranches.PullRequestData.newBuilder()
|
||||
.setBranch("prBranch")
|
||||
.setTitle("title")
|
||||
.setTarget("target")
|
||||
.setUrl("url")
|
||||
.build()),
|
||||
new BranchDto()
|
||||
.setBranchType(BranchType.PULL_REQUEST)
|
||||
.setKey("prKey2")
|
||||
.setUuid("uuid3")
|
||||
.setMergeBranchUuid("orphan")
|
||||
.setPullRequestData(DbProjectBranches.PullRequestData.newBuilder()
|
||||
.setBranch("prBranch2")
|
||||
.setTitle("title2")
|
||||
.setUrl("url2")
|
||||
.build()),
|
||||
new BranchDto()
|
||||
.setBranchType(BranchType.PULL_REQUEST)
|
||||
.setKey("prKey3")
|
||||
.setUuid("uuid4")
|
||||
.setMergeBranchUuid("uuid2")
|
||||
.setPullRequestData(DbProjectBranches.PullRequestData.newBuilder()
|
||||
.setBranch("prBranch2")
|
||||
.setTitle("title3")
|
||||
.setUrl("url3")
|
||||
.build())));
|
||||
|
||||
when(branchDao.selectByUuids(any(), any())).thenReturn(List.of(new BranchDto()
|
||||
.setUuid("uuid2")
|
||||
.setKey("branch2Key")));
|
||||
|
||||
LiveMeasureDao liveMeasureDao = mock(LiveMeasureDao.class);
|
||||
when(dbClient.liveMeasureDao()).thenReturn(liveMeasureDao);
|
||||
when(liveMeasureDao.selectByComponentUuidsAndMetricKeys(any(), any(), any())).thenReturn(List.of(new LiveMeasureDto()
|
||||
.setComponentUuid("uuid1")
|
||||
.setData("live measure")));
|
||||
|
||||
SnapshotDao snapshotDao = mock(SnapshotDao.class);
|
||||
when(dbClient.snapshotDao()).thenReturn(snapshotDao);
|
||||
when(snapshotDao.selectLastAnalysesByRootComponentUuids(any(), any())).thenReturn(List.of(new SnapshotDto().setComponentUuid("componentUuid").setCreatedAt(1234L)));
|
||||
|
||||
when(issueIndex.searchBranchStatistics(any(), any())).thenReturn(List.of(new PrStatistics("uuid1", Map.of(ScannerReport.IssueType.BUG.name(), 11L, ScannerReport.IssueType.CODE_SMELL.name(), 22L, ScannerReport.IssueType.VULNERABILITY.name(), 33L)),
|
||||
new PrStatistics("uuid4", Map.of(ScannerReport.IssueType.BUG.name(), 1L, ScannerReport.IssueType.CODE_SMELL.name(), 2L, ScannerReport.IssueType.VULNERABILITY.name(), 3L))));
|
||||
|
||||
Response response = mock(Response.class);
|
||||
|
||||
ProjectPullRequests.ListWsResponse expected = ProjectPullRequests.ListWsResponse.newBuilder()
|
||||
.addPullRequests(ProjectPullRequests.PullRequest.newBuilder()
|
||||
.setKey("prKey")
|
||||
.setTitle("title")
|
||||
.setBranch("prBranch")
|
||||
.setBase("branch2Key")
|
||||
.setStatus(ProjectPullRequests.Status.newBuilder()
|
||||
.setQualityGateStatus("live measure")
|
||||
.setBugs(11)
|
||||
.setVulnerabilities(33)
|
||||
.setCodeSmells(22)
|
||||
.build())
|
||||
.setUrl("url")
|
||||
.setTarget("target")
|
||||
.build())
|
||||
.addPullRequests(ProjectPullRequests.PullRequest.newBuilder()
|
||||
.setKey("prKey2")
|
||||
.setTitle("title2")
|
||||
.setBranch("prBranch2")
|
||||
.setStatus(ProjectPullRequests.Status.newBuilder()
|
||||
.setBugs(0)
|
||||
.setCodeSmells(0)
|
||||
.setVulnerabilities(0)
|
||||
.build())
|
||||
.setIsOrphan(true)
|
||||
.setUrl("url2"))
|
||||
.addPullRequests(ProjectPullRequests.PullRequest.newBuilder()
|
||||
.setKey("prKey3")
|
||||
.setTitle("title3")
|
||||
.setBranch("prBranch2")
|
||||
.setBase("branch2Key")
|
||||
.setStatus(ProjectPullRequests.Status.newBuilder()
|
||||
.setBugs(1)
|
||||
.setVulnerabilities(3)
|
||||
.setCodeSmells(2)
|
||||
.build())
|
||||
.setUrl("url3")
|
||||
.setTarget("branch2Key")
|
||||
.build())
|
||||
.build();
|
||||
|
||||
|
||||
underTest.handle(request, response);
|
||||
|
||||
ArgumentCaptor<ProjectPullRequests.ListWsResponse> messageArgumentCaptor = ArgumentCaptor.forClass(ProjectPullRequests.ListWsResponse.class);
|
||||
verify(protoBufWriter).write(messageArgumentCaptor.capture(), eq(request), eq(response));
|
||||
|
||||
assertThat(messageArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotExecuteRequestIfUserDoesNotHaveAnyPermissions() {
|
||||
Request request = mock(Request.class);
|
||||
when(request.mandatoryParam("project")).thenReturn("project");
|
||||
|
||||
Response response = mock(Response.class);
|
||||
|
||||
assertThatThrownBy(() -> underTest.handle(request, response)).isInstanceOf(ForbiddenException.class);
|
||||
|
||||
verifyNoMoreInteractions(protoBufWriter);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user