Skip to content

Commit

Permalink
Allow override configuration from CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
artemy-osipov authored and mc1arke committed Feb 24, 2020
1 parent 997df1e commit e129d90
Show file tree
Hide file tree
Showing 18 changed files with 473 additions and 411 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#Gradle
/.gradle/
/build/
.gradletasknamecache

#Intellij
/out/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
import com.github.mc1arke.sonarqube.plugin.ce.CommunityReportAnalysisComponentProvider;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PullRequestBuildStatusDecorator;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.bitbucket.server.BitbucketServerPullRequestDecorator;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.github.v4.GraphqlCheckRunProvider;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.gitlab.GitlabServerPullRequestDecorator;
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.scanner.ScannerConfigurationLoaderSensor;
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension;
import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate;
import org.sonar.api.CoreProperties;
Expand All @@ -43,6 +45,7 @@
*/
public class CommunityBranchPlugin implements Plugin, CoreExtension {

public static final String PULL_REQUEST_PROVIDER = "sonar.pullrequest.provider";
private static final String PULL_REQUEST_CATEGORY_LABEL = "Pull Request";
private static final String GITHUB_INTEGRATION_SUBCATEGORY_LABEL = "Integration With Github";
private static final String GENERAL = "General";
Expand Down Expand Up @@ -86,29 +89,29 @@ public void load(CoreExtension.Context context) {
if (SonarQubeSide.COMPUTE_ENGINE == context.getRuntime().getSonarQubeSide() ||
SonarQubeSide.SERVER == context.getRuntime().getSonarQubeSide()) {
context.addExtensions(
PropertyDefinition.builder("sonar.pullrequest.provider").category(PULL_REQUEST_CATEGORY_LABEL)
PropertyDefinition.builder(PULL_REQUEST_PROVIDER).category(PULL_REQUEST_CATEGORY_LABEL)
.subCategory("General").onQualifiers(Qualifiers.PROJECT).name("Provider")
.type(PropertyType.SINGLE_SELECT_LIST).options("Github", "BitbucketServer", "GitlabServer").build(),

PropertyDefinition.builder("sonar.alm.github.app.privateKey.secured")
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_TOKEN)
.category(PULL_REQUEST_CATEGORY_LABEL).subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL)
.onQualifiers(Qualifiers.APP).name("App Private Key").type(PropertyType.TEXT).build(),

PropertyDefinition.builder("sonar.alm.github.app.name").category(PULL_REQUEST_CATEGORY_LABEL)
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_APP_NAME).category(PULL_REQUEST_CATEGORY_LABEL)
.subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL).onQualifiers(Qualifiers.APP)
.name("App Name").defaultValue("SonarQube Community Pull Request Analysis")
.type(PropertyType.STRING).build(),

PropertyDefinition.builder("sonar.alm.github.app.id").category(PULL_REQUEST_CATEGORY_LABEL)
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_APP_ID).category(PULL_REQUEST_CATEGORY_LABEL)
.subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL).onQualifiers(Qualifiers.APP)
.name("App ID").type(PropertyType.STRING).build(),

PropertyDefinition.builder("sonar.pullrequest.github.repository")
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_REPOSITORY)
.category(PULL_REQUEST_CATEGORY_LABEL).subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL)
.onlyOnQualifiers(Qualifiers.PROJECT).name("Repository identifier")
.description("Example: SonarSource/sonarqube").type(PropertyType.STRING).build(),

PropertyDefinition.builder("sonar.pullrequest.github.endpoint")
PropertyDefinition.builder(GraphqlCheckRunProvider.PULL_REQUEST_GITHUB_URL)
.category(PULL_REQUEST_CATEGORY_LABEL).subCategory(GITHUB_INTEGRATION_SUBCATEGORY_LABEL)
.onQualifiers(Qualifiers.APP).name("The API URL for a GitHub instance").description(
"The API url for a GitHub instance. https://api.github.com/ for github.com, https://github.company.com/api/ when using GitHub Enterprise")
Expand Down Expand Up @@ -185,7 +188,8 @@ public void load(CoreExtension.Context context) {
public void define(Plugin.Context context) {
if (SonarQubeSide.SCANNER == context.getRuntime().getSonarQubeSide()) {
context.addExtensions(CommunityProjectBranchesLoader.class, CommunityProjectPullRequestsLoader.class,
CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class);
CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class,
ScannerConfigurationLoaderSensor.class);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ public interface PullRequestBuildStatusDecorator {

String name();

void decorateQualityGateStatus(AnalysisDetails analysisDetails);
void decorateQualityGateStatus(AnalysisDetails analysisDetails, UnifyConfiguration configuration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package com.github.mc1arke.sonarqube.plugin.ce.pullrequest;

import com.github.mc1arke.sonarqube.plugin.CommunityBranchPlugin;
import org.sonar.api.ce.posttask.Analysis;
import org.sonar.api.ce.posttask.Branch;
import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
Expand Down Expand Up @@ -86,9 +87,10 @@ public void finished(PostProjectAnalysisTask.ProjectAnalysis projectAnalysis) {
}

Configuration configuration = configurationRepository.getConfiguration();
UnifyConfiguration unifyConfiguration = new UnifyConfiguration(configuration, projectAnalysis.getScannerContext());

Optional<PullRequestBuildStatusDecorator> optionalPullRequestDecorator =
findCurrentPullRequestStatusDecorator(configuration, pullRequestDecorators);
findCurrentPullRequestStatusDecorator(unifyConfiguration, pullRequestDecorators);

if (!optionalPullRequestDecorator.isPresent()) {
LOGGER.info("No decorator found for this Pull Request");
Expand Down Expand Up @@ -127,16 +129,16 @@ public void finished(PostProjectAnalysisTask.ProjectAnalysis projectAnalysis) {

PullRequestBuildStatusDecorator pullRequestDecorator = optionalPullRequestDecorator.get();
LOGGER.info("using pull request decorator" + pullRequestDecorator.name());
pullRequestDecorator.decorateQualityGateStatus(analysisDetails);
pullRequestDecorator.decorateQualityGateStatus(analysisDetails, unifyConfiguration);
}

private static Optional<PullRequestBuildStatusDecorator> findCurrentPullRequestStatusDecorator(
Configuration configuration, List<PullRequestBuildStatusDecorator> pullRequestDecorators) {
UnifyConfiguration unifyConfiguration, List<PullRequestBuildStatusDecorator> pullRequestDecorators) {

Optional<String> optionalImplementationName = configuration.get("sonar.pullrequest.provider");
Optional<String> optionalImplementationName = unifyConfiguration.getProperty(CommunityBranchPlugin.PULL_REQUEST_PROVIDER);

if (!optionalImplementationName.isPresent()) {
LOGGER.debug("'sonar.pullrequest.provider' property not set");
LOGGER.debug(CommunityBranchPlugin.PULL_REQUEST_PROVIDER + " property not set");
return Optional.empty();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (C) 2020 Artemy Osipov
*
* 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.ce.pullrequest;

import org.sonar.api.ce.posttask.ScannerContext;
import org.sonar.api.config.Configuration;

import java.util.Optional;

public class UnifyConfiguration {

private final Configuration serverConfiguration;
private final ScannerContext scannerContext;

public UnifyConfiguration(Configuration serverConfiguration, ScannerContext scannerContext) {
this.serverConfiguration = serverConfiguration;
this.scannerContext = scannerContext;
}

public Optional<String> getProperty(String propertyName) {
if (scannerContext.getProperties().containsKey(propertyName)) {
return Optional.of(scannerContext.getProperties().get(propertyName));
}

return getServerProperty(propertyName);
}

public String getRequiredProperty(String propertyName) {
return getProperty(propertyName).orElseThrow(() ->
new IllegalStateException(propertyName + " must be specified in the project configuration or as scanner parameter")
);
}

public Optional<String> getServerProperty(String propertyName) {
return serverConfiguration.get(propertyName);
}

public String getRequiredServerProperty(String propertyName) {
return getServerProperty(propertyName).orElseThrow(() ->
new IllegalStateException(propertyName + " must be specified in the project configuration")
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.UnifyConfiguration;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.AnalysisDetails;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PostAnalysisIssueVisitor;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PullRequestBuildStatusDecorator;
Expand Down Expand Up @@ -47,11 +48,9 @@
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.sonar.api.config.Configuration;
import org.sonar.api.issue.Issue;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository;
import org.sonar.core.issue.DefaultIssue;

import java.io.IOException;
Expand All @@ -69,11 +68,11 @@ public class BitbucketServerPullRequestDecorator implements PullRequestBuildStat

public static final String PULL_REQUEST_BITBUCKET_TOKEN = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.bitbucket.token";

public static final String PULL_REQUEST_BITBUCKET_PROJECT_KEY = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.bitbucket.projectKey";
public static final String PULL_REQUEST_BITBUCKET_PROJECT_KEY = "sonar.pullrequest.bitbucket.projectKey";

public static final String PULL_REQUEST_BITBUCKET_USER_SLUG = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.bitbucket.userSlug";
public static final String PULL_REQUEST_BITBUCKET_USER_SLUG = "sonar.pullrequest.bitbucket.userSlug";

public static final String PULL_REQUEST_BITBUCKET_REPOSITORY_SLUG = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.bitbucket.repositorySlug";
public static final String PULL_REQUEST_BITBUCKET_REPOSITORY_SLUG = "sonar.pullrequest.bitbucket.repositorySlug";

public static final String PULL_REQUEST_BITBUCKET_COMMENT_USER_SLUG = "com.github.mc1arke.sonarqube.plugin.branch.pullrequest.bitbucket.comment.userSlug";

Expand All @@ -98,31 +97,22 @@ public class BitbucketServerPullRequestDecorator implements PullRequestBuildStat
private static final String FULL_PR_DIFF_API = "%s" + REST_API + PROJECT_PR_API + DIFF_API;
private static final String FULL_PR_DIFF_USER_API = "%s" + REST_API + USER_PR_API + DIFF_API;


private final ConfigurationRepository configurationRepository;

public BitbucketServerPullRequestDecorator(ConfigurationRepository configurationRepository) {
super();
this.configurationRepository = configurationRepository;
}

@Override
public void decorateQualityGateStatus(AnalysisDetails analysisDetails) {
public void decorateQualityGateStatus(AnalysisDetails analysisDetails, UnifyConfiguration configuration) {
LOGGER.info("starting to analyze with " + analysisDetails.toString());

try {
Configuration configuration = configurationRepository.getConfiguration();
final String hostURL = getMandatoryProperty(PULL_REQUEST_BITBUCKET_URL, configuration);
final String apiToken = getMandatoryProperty(PULL_REQUEST_BITBUCKET_TOKEN, configuration);
final String repositorySlug = getMandatoryProperty(PULL_REQUEST_BITBUCKET_REPOSITORY_SLUG, configuration);
final String hostURL = configuration.getRequiredServerProperty(PULL_REQUEST_BITBUCKET_URL);
final String apiToken = configuration.getRequiredServerProperty(PULL_REQUEST_BITBUCKET_TOKEN);
final String repositorySlug = configuration.getRequiredProperty(PULL_REQUEST_BITBUCKET_REPOSITORY_SLUG);
final String pullRequestId = analysisDetails.getBranchName();
final String userSlug = configuration.get(PULL_REQUEST_BITBUCKET_USER_SLUG).orElse(StringUtils.EMPTY);
final String projectKey = configuration.get(PULL_REQUEST_BITBUCKET_PROJECT_KEY).orElse(StringUtils.EMPTY);
final String commentUserSlug = configuration.get(PULL_REQUEST_BITBUCKET_COMMENT_USER_SLUG).orElse(StringUtils.EMPTY);
final String userSlug = configuration.getProperty(PULL_REQUEST_BITBUCKET_USER_SLUG).orElse(StringUtils.EMPTY);
final String projectKey = configuration.getProperty(PULL_REQUEST_BITBUCKET_PROJECT_KEY).orElse(StringUtils.EMPTY);
final String commentUserSlug = configuration.getServerProperty(PULL_REQUEST_BITBUCKET_COMMENT_USER_SLUG).orElse(StringUtils.EMPTY);

final boolean summaryCommentEnabled = Boolean.parseBoolean(getMandatoryProperty(PULL_REQUEST_COMMENT_SUMMARY_ENABLED, configuration));
final boolean fileCommentEnabled = Boolean.parseBoolean(getMandatoryProperty(PULL_REQUEST_FILE_COMMENT_ENABLED, configuration));
final boolean deleteCommentsEnabled = Boolean.parseBoolean(getMandatoryProperty(PULL_REQUEST_DELETE_COMMENTS_ENABLED, configuration));
final boolean summaryCommentEnabled = Boolean.parseBoolean(configuration.getRequiredServerProperty(PULL_REQUEST_COMMENT_SUMMARY_ENABLED));
final boolean fileCommentEnabled = Boolean.parseBoolean(configuration.getRequiredServerProperty(PULL_REQUEST_FILE_COMMENT_ENABLED));
final boolean deleteCommentsEnabled = Boolean.parseBoolean(configuration.getRequiredServerProperty(PULL_REQUEST_DELETE_COMMENTS_ENABLED));

final String commentUrl;
final String activityUrl;
Expand Down Expand Up @@ -322,11 +312,6 @@ protected boolean postComment(String commentUrl, Map<String, String> headers, St
return commentPosted;
}

private static String getMandatoryProperty(String propertyName, Configuration configuration) {
return configuration.get(propertyName).orElseThrow(() -> new IllegalStateException(
String.format("%s must be specified in the project configuration", propertyName)));
}

@Override
public String name() {
return "BitbucketServer";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
package com.github.mc1arke.sonarqube.plugin.ce.pullrequest.github;

import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.AnalysisDetails;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.UnifyConfiguration;

import java.io.IOException;
import java.security.GeneralSecurityException;

public interface CheckRunProvider {
void createCheckRun(AnalysisDetails analysisDetails) throws IOException, GeneralSecurityException;
void createCheckRun(AnalysisDetails analysisDetails, UnifyConfiguration unifyConfiguration) throws IOException, GeneralSecurityException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.AnalysisDetails;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.PullRequestBuildStatusDecorator;
import com.github.mc1arke.sonarqube.plugin.ce.pullrequest.UnifyConfiguration;

public class GithubPullRequestDecorator implements PullRequestBuildStatusDecorator {

Expand All @@ -30,9 +31,9 @@ public GithubPullRequestDecorator(CheckRunProvider checkRunProvider) {
}

@Override
public void decorateQualityGateStatus(AnalysisDetails analysisDetails) {
public void decorateQualityGateStatus(AnalysisDetails analysisDetails, UnifyConfiguration unifyConfiguration) {
try {
checkRunProvider.createCheckRun(analysisDetails);
checkRunProvider.createCheckRun(analysisDetails, unifyConfiguration);
} catch (Exception ex) {
throw new IllegalStateException("Could not decorate Pull Request on Github", ex);
}
Expand Down
Loading

0 comments on commit e129d90

Please sign in to comment.