Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Only fetch unresolved issues #177

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public List<Issue> fetchIssues(TaskListener listener) throws InterruptedExceptio

SearchRequest issueSearchRequest =
new SearchRequest()
.setResolved("false")
.setComponentKeys(Collections.singletonList(componentKey))
.setPullRequest(pullRequestKey);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import jenkins.model.ParameterizedJobMixIn;
import me.redaalaoui.gerrit_rest_java_client.thirdparty.com.google.gerrit.extensions.common.ChangeInfo;
Expand All @@ -39,16 +41,17 @@
/** @author Réda Housni Alaoui */
@EnableCluster
class PullRequestAnalysisTest {
private static final Logger LOGGER = Logger.getLogger(PullRequestAnalysisTest.class.getName());

private static final String MAVEN_FREESTYLE_TARGET =
"clean verify sonar:sonar "
+ "-Dsonar.pullrequest.key=${GERRIT_CHANGE_NUMBER}-${GERRIT_PATCHSET_NUMBER} "
+ "-Dsonar.pullrequest.key=${GERRIT_CHANGE_NUMBER} "
+ "-Dsonar.pullrequest.base=${GERRIT_BRANCH} "
+ "-Dsonar.pullrequest.branch=${GERRIT_REFSPEC}";

private static final String MAVEN_PIPELINE_TARGET =
"clean verify sonar:sonar "
+ "-Dsonar.pullrequest.key=${env.GERRIT_CHANGE_NUMBER}-${env.GERRIT_PATCHSET_NUMBER} "
+ "-Dsonar.pullrequest.key=${env.GERRIT_CHANGE_NUMBER} "
+ "-Dsonar.pullrequest.base=${env.GERRIT_BRANCH} "
+ "-Dsonar.pullrequest.branch=${env.GERRIT_REFSPEC}";

Expand Down Expand Up @@ -113,29 +116,41 @@ void test1() throws Exception {
@Test
@DisplayName("Good quality freestyle build")
void test2() throws Exception {
testWithGoodQualityCode(this::createFreestyleJob);
testWithGoodQualityCode(this::createFreestyleJob, false, null);
}

@Test
@DisplayName("Bad quality pipeline build")
@DisplayName("Bad then good quality freestyle build")
void test3() throws Exception {
GerritChange change = testWithBadQualityCode(this::createFreestyleJob);
testWithGoodQualityCode(this::createFreestyleJob, true, change);
}

@Test
@DisplayName("Bad quality pipeline build")
void test4() throws Exception {
testWithBadQualityCode(this::createPipelineJob);
}

@Test
@DisplayName("Good quality pipeline build")
void test4() throws Exception {
testWithGoodQualityCode(this::createPipelineJob);
void test5() throws Exception {
testWithGoodQualityCode(this::createPipelineJob, false, null);
}

@Test
@DisplayName("Bad then good quality pipeline build")
void test6() throws Exception {
GerritChange change = testWithBadQualityCode(this::createPipelineJob);
testWithGoodQualityCode(this::createFreestyleJob, true, change);
}

private void testWithBadQualityCode(JobFactory jobFactory) throws Exception {
private GerritChange testWithBadQualityCode(JobFactory jobFactory) throws Exception {
git.addAndCommitFile(
"src/main/java/org/example/UselessConstructorDeclaration.java",
"package org.example; "
+ "public class UselessConstructorDeclaration { "
+ "public UselessConstructorDeclaration() {} "
+ "}");
"src/main/java/org/example/Foo.java",
"package org.example; public class Foo { public Foo() {} }");
GerritChange change = git.createGerritChangeForMaster();
LOGGER.log(Level.INFO, "Testing bad quality code with change {0}", change.changeNumericId());

triggerAndAssertSuccess(jobFactory.build(change));

Expand All @@ -148,12 +163,24 @@ private void testWithBadQualityCode(JobFactory jobFactory) throws Exception {
.map(commentInfo -> commentInfo.message)
.filteredOn(message -> message.contains("S1186"))
.hasSize(1);

return change;
}

private void testWithGoodQualityCode(JobFactory jobFactory) throws Exception {
private void testWithGoodQualityCode(
JobFactory jobFactory, boolean amend, GerritChange previousChange) throws Exception {
git.addAndCommitFile(
"src/main/java/org/example/Foo.java", "package org.example; public interface Foo {}");
"src/main/java/org/example/Foo.java",
"package org.example; public interface Foo {}",
amend);
GerritChange change = git.createGerritChangeForMaster();
LOGGER.log(Level.INFO, "Testing good quality code with change {0}", change.changeNumericId());

if (previousChange != null) {
LOGGER.log(
Level.INFO, "Comparing to previous change with ID {0}", previousChange.changeNumericId());
assertThat(previousChange.changeNumericId()).isEqualTo(change.changeNumericId());
}

triggerAndAssertSuccess(jobFactory.build(change));

Expand Down Expand Up @@ -215,24 +242,24 @@ private Job createPipelineJob(GerritChange change) throws IOException {
"node {\n"
+ "stage('Build') {\n"
+ "try {\n"
+ String.format("env.GERRIT_NAME = '%s'\n", cluster.jenkinsGerritTriggerServerName())
+ String.format("env.GERRIT_CHANGE_NUMBER = '%s'\n", change.changeNumericId())
+ String.format("env.GERRIT_PATCHSET_NUMBER = '%s'\n", patchSetNumber)
+ String.format("env.GERRIT_BRANCH = '%s'\n", "master")
+ String.format("env.GERRIT_REFSPEC = '%s'\n", change.refName(patchSetNumber))
+ String.format("env.GERRIT_NAME = '%s'%n", cluster.jenkinsGerritTriggerServerName())
+ String.format("env.GERRIT_CHANGE_NUMBER = '%s'%n", change.changeNumericId())
+ String.format("env.GERRIT_PATCHSET_NUMBER = '%s'%n", patchSetNumber)
+ String.format("env.GERRIT_BRANCH = '%s'%n", "master")
+ String.format("env.GERRIT_REFSPEC = '%s'%n", change.refName(patchSetNumber))
+ "checkout scm: ([\n"
+ "$class: 'GitSCM',\n"
+ String.format(
"userRemoteConfigs: [[url: '%s', refspec: '%s', credentialsId: '%s']],\n",
"userRemoteConfigs: [[url: '%s', refspec: '%s', credentialsId: '%s']],%n",
git.httpUrl(), change.refName(patchSetNumber), cluster.jenkinsGerritCredentialsId())
+ "branches: [[name: 'FETCH_HEAD']]\n"
+ "])\n"
+ String.format(
"withSonarQubeEnv('%s') {\n", cluster.jenkinsSonarqubeInstallationName())
"withSonarQubeEnv('%s') {%n", cluster.jenkinsSonarqubeInstallationName())
+ String.format(
"withMaven(jdk: '%s', maven: '%s') {\n",
"withMaven(jdk: '%s', maven: '%s') {%n",
cluster.jenkinsJdk17InstallationName(), cluster.jenkinsMavenInstallationName())
+ String.format("sh \"mvn %s\"\n", MAVEN_PIPELINE_TARGET)
+ String.format("sh \"mvn %s\"%n", MAVEN_PIPELINE_TARGET)
+ "}\n" // withMaven
+ "}\n" // withSonarQubeEnv
+ "} finally {\n"
Expand All @@ -253,7 +280,7 @@ private Job createPipelineJob(GerritChange change) throws IOException {
+ "newIssuesOnly: false,"
+ "changedLinesOnly: true"
+ "],\n" // issueFilterConfig
+ String.format("category: '%s',\n", GerritServer.CODE_QUALITY_LABEL)
+ String.format("category: '%s',%n", GerritServer.CODE_QUALITY_LABEL)
+ "noIssuesScore: 1,\n"
+ "issuesScore: -1,\n"
+ "]\n" // scoreConfig
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.jenkinsci.plugins.sonargerrit.test_infrastructure;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.testcontainers.containers.output.BaseConsumer;
import org.testcontainers.containers.output.OutputFrame;

// based on org.testcontainers.containers.output.Slf4jLogConsumer
public class JulLogConsumer extends BaseConsumer<JulLogConsumer> {
private final Logger logger;
private boolean separateOutputStreams;
private String prefix = "";

public JulLogConsumer(Logger logger) {
this(logger, false);
}

public JulLogConsumer(Logger logger, boolean separateOutputStreams) {
this.logger = logger;
this.separateOutputStreams = separateOutputStreams;
}

public JulLogConsumer withPrefix(String prefix) {
this.prefix = "[" + prefix + "]";
return this;
}

public JulLogConsumer withSeparateOutputStreams() {
this.separateOutputStreams = true;
return this;
}

@Override
public void accept(OutputFrame outputFrame) {
OutputFrame.OutputType outputType = outputFrame.getType();

String utf8String = outputFrame.getUtf8String().replaceAll("((\\r?\\n)|(\\r))$", "");

switch (outputType) {
case END:
break;
case STDOUT:
if (separateOutputStreams) {
logger.log(Level.INFO, () -> prefix.isEmpty() ? "" : (prefix + ": ") + utf8String);
} else {
logger.log(Level.INFO, () -> prefix + " " + outputType + ": " + utf8String);
}
break;
case STDERR:
if (separateOutputStreams) {
logger.log(Level.SEVERE, () -> prefix.isEmpty() ? "" : (prefix + ": ") + utf8String);
} else {
logger.log(Level.INFO, () -> prefix + " " + outputType + ": " + utf8String);
}
break;
default:
throw new IllegalArgumentException("Unexpected outputType " + outputType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -15,11 +16,14 @@
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RefSpec;

/** @author Réda Housni Alaoui */
public class GerritGit {
private static final String CHANGE_ID = "Change-Id: I";

private final GerritServer gerrit;
private final Git git;
Expand Down Expand Up @@ -55,10 +59,27 @@ public Path workTree() {
return git.getRepository().getWorkTree().toPath();
}

public CommitCommand commit(String message) {
String changeId = "I" + DigestUtils.sha1Hex(String.format("%s|%s", UUID.randomUUID(), message));
public CommitCommand commit(String message, boolean amend) throws IOException {
String changeIdLine = null;
if (amend) {
Repository repository = git.getRepository();
String previousMessage =
repository.parseCommit(repository.resolve(Constants.HEAD)).getFullMessage();
changeIdLine =
Arrays.stream(previousMessage.split("\n"))
.filter(msg -> msg.startsWith(CHANGE_ID))
.findFirst()
.orElse(null);
}

if (changeIdLine == null) {
changeIdLine =
CHANGE_ID + DigestUtils.sha1Hex(String.format("%s|%s", UUID.randomUUID(), message));
}

return git.commit()
.setMessage(message + "\n\nChange-Id: " + changeId)
.setAmend(amend)
.setMessage(message + "\n\n" + changeIdLine)
.setAuthor(agent)
.setCommitter(agent);
}
Expand Down Expand Up @@ -99,8 +120,13 @@ public GerritGit resetToOriginMaster() throws GitAPIException {

public GerritGit addAndCommitFile(String relativePath, String content)
throws IOException, GitAPIException {
return addAndCommitFile(relativePath, content, false);
}

public GerritGit addAndCommitFile(String relativePath, String content, boolean amend)
throws IOException, GitAPIException {
addFile(relativePath, content);
commit("Add " + relativePath).call();
commit("Add " + relativePath, amend).call();
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import me.redaalaoui.gerrit_rest_java_client.rest.GerritAuthData;
import me.redaalaoui.gerrit_rest_java_client.rest.GerritRestApiFactory;
import me.redaalaoui.gerrit_rest_java_client.thirdparty.com.google.gerrit.extensions.api.GerritApi;
Expand All @@ -19,16 +20,14 @@
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.jenkinsci.plugins.sonargerrit.test_infrastructure.CloseableResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jenkinsci.plugins.sonargerrit.test_infrastructure.JulLogConsumer;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.output.Slf4jLogConsumer;

/** @author Réda Housni Alaoui */
public class GerritServer {

private static final Logger LOG = LoggerFactory.getLogger(GerritServer.class);
private static final Logger LOG = Logger.getLogger(GerritServer.class.getName());

private static final int HTTP_PORT = 8080;
private static final int SSH_PORT = 29418;
Expand Down Expand Up @@ -60,7 +59,7 @@ public void close() {
private GerritServer(Network network) {
container =
new GenericContainer<>("gerritcodereview/gerrit:3.4.1-ubuntu20")
.withLogConsumer(new Slf4jLogConsumer(LOG))
.withLogConsumer(new JulLogConsumer(LOG).withPrefix("Gerrit"))
.withExposedPorts(HTTP_PORT, SSH_PORT)
.withNetwork(network)
.withNetworkAliases(NETWORK_ALIAS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,22 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.logging.Logger;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.jenkinsci.plugins.sonargerrit.test_infrastructure.CloseableResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jenkinsci.plugins.sonargerrit.test_infrastructure.JulLogConsumer;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.images.builder.ImageFromDockerfile;

/** @author Réda Housni Alaoui */
public class SonarqubeServer {

private static final Logger LOG = LoggerFactory.getLogger(SonarqubeServer.class);
private static final Logger LOG = Logger.getLogger(SonarqubeServer.class.getName());

private static final int HTTP_PORT = 9000;

Expand Down Expand Up @@ -62,7 +61,7 @@ private SonarqubeServer(Network network) {
.withEnv(
"SONAR_CE_JAVAADDITIONALOPTS",
"-javaagent:./extensions/plugins/sonarqube-community-branch-plugin.jar=ce")
.withLogConsumer(new Slf4jLogConsumer(LOG))
.withLogConsumer(new JulLogConsumer(LOG).withPrefix("SonarQube"))
.withExposedPorts(HTTP_PORT)
.withNetwork(network)
.withNetworkAliases(NETWORK_ALIAS);
Expand Down
Loading