@@ -117,7 +117,6 @@ import org.sonar.server.computation.task.projectanalysis.source.SourceHashReposi | |||
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryImpl; | |||
import org.sonar.server.computation.task.projectanalysis.step.ReportComputationSteps; | |||
import org.sonar.server.computation.task.projectanalysis.step.SmallChangesetQualityGateSpecialCase; | |||
import org.sonar.server.computation.task.projectanalysis.webhook.WebhookPayloadFactoryImpl; | |||
import org.sonar.server.computation.task.projectanalysis.webhook.WebhookPostTask; | |||
import org.sonar.server.computation.task.step.ComputationStepExecutor; | |||
import org.sonar.server.computation.task.step.ComputationSteps; | |||
@@ -274,7 +273,6 @@ public final class ProjectAnalysisTaskContainerPopulator implements ContainerPop | |||
// webhooks | |||
WebhookModule.class, | |||
WebhookPayloadFactoryImpl.class, | |||
WebhookPostTask.class); | |||
} | |||
@@ -19,10 +19,18 @@ | |||
*/ | |||
package org.sonar.server.computation.task.projectanalysis.webhook; | |||
import java.util.Date; | |||
import java.util.Optional; | |||
import java.util.stream.Collectors; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.api.config.Configuration; | |||
import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository; | |||
import org.sonar.server.webhook.Branch; | |||
import org.sonar.server.webhook.CeTask; | |||
import org.sonar.server.webhook.Project; | |||
import org.sonar.server.webhook.QualityGate; | |||
import org.sonar.server.webhook.WebHooks; | |||
import org.sonar.server.webhook.WebhookPayloadFactory; | |||
public class WebhookPostTask implements PostProjectAnalysisTask { | |||
@@ -43,7 +51,27 @@ public class WebhookPostTask implements PostProjectAnalysisTask { | |||
webHooks.sendProjectAnalysisUpdate( | |||
config, | |||
new WebHooks.Analysis(analysis.getProject().getUuid(), analysis.getCeTask().getId()), | |||
() -> payloadFactory.create(analysis)); | |||
() -> payloadFactory.create(convert(analysis))); | |||
} | |||
private static org.sonar.server.webhook.ProjectAnalysis convert(ProjectAnalysis analysis) { | |||
return new org.sonar.server.webhook.ProjectAnalysis( | |||
new CeTask(analysis.getCeTask().getId(), CeTask.Status.valueOf(analysis.getCeTask().getStatus().name())), | |||
new Project(analysis.getProject().getUuid(), analysis.getProject().getKey(), analysis.getProject().getName()), | |||
analysis.getBranch().map(b -> new Branch(b.isMain(), b.getName().orElse(null), Branch.Type.valueOf(b.getType().name()))).orElse(null), | |||
Optional.ofNullable(analysis.getQualityGate()) | |||
.map(qg -> new QualityGate( | |||
qg.getId(), | |||
qg.getName(), | |||
QualityGate.Status.valueOf(qg.getStatus().name()), | |||
qg.getConditions().stream() | |||
.map(c -> new QualityGate.Condition(QualityGate.EvaluationStatus.valueOf(c.getStatus().name()), c.getMetricKey(), QualityGate.Operator.valueOf(c.getOperator().name()), | |||
c.getErrorThreshold(), c.getWarningThreshold(), c.isOnLeakPeriod(), | |||
c.getStatus() == org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE ? null : c.getValue())) | |||
.collect(Collectors.toSet()))) | |||
.orElse(null), | |||
analysis.getAnalysisDate().map(Date::getTime).orElse(null), | |||
analysis.getScannerContext().getProperties()); | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import static java.util.Objects.requireNonNull; | |||
public final class Branch { | |||
private final boolean main; | |||
private final String name; | |||
private final Type type; | |||
public Branch(boolean main, @Nullable String name, Type type) { | |||
this.main = main; | |||
this.name = name; | |||
this.type = requireNonNull(type, "type can't be null"); | |||
} | |||
public boolean isMain() { | |||
return main; | |||
} | |||
public Optional<String> getName() { | |||
return Optional.ofNullable(name); | |||
} | |||
public Type getType() { | |||
return type; | |||
} | |||
public enum Type { | |||
LONG, SHORT | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Branch branch = (Branch) o; | |||
return main == branch.main && | |||
Objects.equals(name, branch.name) && | |||
type == branch.type; | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(main, name, type); | |||
} | |||
@Override | |||
public String toString() { | |||
return "Branch{" + | |||
"main=" + main + | |||
", name='" + name + '\'' + | |||
", type=" + type + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Objects; | |||
import static java.util.Objects.requireNonNull; | |||
public final class CeTask { | |||
private final String id; | |||
private final Status status; | |||
public CeTask(String id, Status status) { | |||
this.id = requireNonNull(id, "id can't be null"); | |||
this.status = requireNonNull(status, "status can't be null"); | |||
} | |||
public String getId() { | |||
return id; | |||
} | |||
public Status getStatus() { | |||
return status; | |||
} | |||
public enum Status { | |||
SUCCESS, FAILED | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
CeTask task = (CeTask) o; | |||
return Objects.equals(id, task.id) && | |||
status == task.status; | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id, status); | |||
} | |||
@Override | |||
public String toString() { | |||
return "CeTask{" + | |||
"id='" + id + '\'' + | |||
", status=" + status + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Objects; | |||
import static java.util.Objects.requireNonNull; | |||
public final class Project { | |||
private final String uuid; | |||
private final String key; | |||
private final String name; | |||
public Project(String uuid, String key, String name) { | |||
this.uuid = requireNonNull(uuid, "uuid can't be null"); | |||
this.key = requireNonNull(key, "key can't be null"); | |||
this.name = requireNonNull(name, "name can't be null"); | |||
} | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
public String getKey() { | |||
return key; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Project project = (Project) o; | |||
return Objects.equals(uuid, project.uuid) && | |||
Objects.equals(key, project.key) && | |||
Objects.equals(name, project.name); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(uuid, key, name); | |||
} | |||
@Override | |||
public String toString() { | |||
return "Project{" + | |||
"uuid='" + uuid + '\'' + | |||
", key='" + key + '\'' + | |||
", name='" + name + '\'' + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,106 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Date; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import static com.google.common.collect.ImmutableMap.copyOf; | |||
import static java.util.Objects.requireNonNull; | |||
public class ProjectAnalysis { | |||
private final CeTask ceTask; | |||
private final Project project; | |||
private final Branch branch; | |||
private final QualityGate qualityGate; | |||
private final Long date; | |||
private final Map<String, String> properties; | |||
public ProjectAnalysis(CeTask ceTask, Project project, | |||
@Nullable Branch branch, @Nullable QualityGate qualityGate, @Nullable Long date, Map<String, String> properties) { | |||
this.ceTask = requireNonNull(ceTask, "ceTask can't be null"); | |||
this.project = requireNonNull(project, "project can't be null"); | |||
this.branch = branch; | |||
this.qualityGate = qualityGate; | |||
this.date = date; | |||
this.properties = copyOf(requireNonNull(properties, "properties can't be null")); | |||
} | |||
public CeTask getCeTask() { | |||
return ceTask; | |||
} | |||
public Project getProject() { | |||
return project; | |||
} | |||
public Optional<Branch> getBranch() { | |||
return Optional.ofNullable(branch); | |||
} | |||
public Optional<QualityGate> getQualityGate() { | |||
return Optional.ofNullable(qualityGate); | |||
} | |||
public Optional<Date> getAnalysisDate() { | |||
return Optional.ofNullable(date).map(Date::new); | |||
} | |||
public Map<String, String> getProperties() { | |||
return properties; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
ProjectAnalysis that = (ProjectAnalysis) o; | |||
return Objects.equals(ceTask, that.ceTask) && | |||
Objects.equals(project, that.project) && | |||
Objects.equals(branch, that.branch) && | |||
Objects.equals(qualityGate, that.qualityGate) && | |||
Objects.equals(date, that.date) && | |||
Objects.equals(properties, that.properties); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(ceTask, project, branch, qualityGate, date, properties); | |||
} | |||
@Override | |||
public String toString() { | |||
return "ProjectAnalysis{" + | |||
"ceTask=" + ceTask + | |||
", project=" + project + | |||
", branch=" + branch + | |||
", qualityGate=" + qualityGate + | |||
", date=" + date + | |||
", properties=" + properties + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,211 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Collection; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import static java.util.Objects.requireNonNull; | |||
public final class QualityGate { | |||
private final String id; | |||
private final String name; | |||
private final Status status; | |||
private final Set<Condition> conditions; | |||
public QualityGate(String id, String name, Status status, Set<Condition> conditions) { | |||
this.id = requireNonNull(id, "id can't be null"); | |||
this.name = requireNonNull(name, "name can't be null"); | |||
this.status = requireNonNull(status, "status can't be null"); | |||
this.conditions = ImmutableSet.copyOf(requireNonNull(conditions, "conditions can't be null")); | |||
} | |||
public String getId() { | |||
return id; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public Status getStatus() { | |||
return status; | |||
} | |||
public Collection<Condition> getConditions() { | |||
return conditions; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
QualityGate that = (QualityGate) o; | |||
return Objects.equals(id, that.id) && | |||
Objects.equals(name, that.name) && | |||
status == that.status && | |||
Objects.equals(conditions, that.conditions); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id, name, status, conditions); | |||
} | |||
@Override | |||
public String toString() { | |||
return "QualityGate{" + | |||
"id='" + id + '\'' + | |||
", name='" + name + '\'' + | |||
", status=" + status + | |||
", conditions=" + conditions + | |||
'}'; | |||
} | |||
public enum Status { | |||
OK, | |||
WARN, | |||
ERROR | |||
} | |||
public static final class Condition { | |||
private final EvaluationStatus status; | |||
private final String metricKey; | |||
private final Operator operator; | |||
private final String errorThreshold; | |||
private final String warnThreshold; | |||
private final boolean onLeakPeriod; | |||
private final String value; | |||
public Condition(EvaluationStatus status, String metricKey, Operator operator, | |||
@Nullable String errorThreshold, @Nullable String warnThreshold, | |||
boolean onLeakPeriod, @Nullable String value) { | |||
this.status = requireNonNull(status, "status can't be null"); | |||
this.metricKey = requireNonNull(metricKey, "metricKey can't be null"); | |||
this.operator = requireNonNull(operator, "operator can't be null"); | |||
this.errorThreshold = errorThreshold; | |||
this.warnThreshold = warnThreshold; | |||
this.onLeakPeriod = onLeakPeriod; | |||
this.value = value; | |||
} | |||
public EvaluationStatus getStatus() { | |||
return status; | |||
} | |||
public String getMetricKey() { | |||
return metricKey; | |||
} | |||
public Operator getOperator() { | |||
return operator; | |||
} | |||
public Optional<String> getErrorThreshold() { | |||
return Optional.ofNullable(errorThreshold); | |||
} | |||
public Optional<String> getWarningThreshold() { | |||
return Optional.ofNullable(warnThreshold); | |||
} | |||
public boolean isOnLeakPeriod() { | |||
return onLeakPeriod; | |||
} | |||
public Optional<String> getValue() { | |||
return Optional.ofNullable(value); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Condition condition = (Condition) o; | |||
return onLeakPeriod == condition.onLeakPeriod && | |||
status == condition.status && | |||
Objects.equals(metricKey, condition.metricKey) && | |||
operator == condition.operator && | |||
Objects.equals(errorThreshold, condition.errorThreshold) && | |||
Objects.equals(warnThreshold, condition.warnThreshold) && | |||
Objects.equals(value, condition.value); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(status, metricKey, operator, errorThreshold, warnThreshold, onLeakPeriod, value); | |||
} | |||
@Override | |||
public String toString() { | |||
return "Condition{" + | |||
"status=" + status + | |||
", metricKey='" + metricKey + '\'' + | |||
", operator=" + operator + | |||
", errorThreshold='" + errorThreshold + '\'' + | |||
", warnThreshold='" + warnThreshold + '\'' + | |||
", onLeakPeriod=" + onLeakPeriod + | |||
", value='" + value + '\'' + | |||
'}'; | |||
} | |||
} | |||
/** | |||
* Quality Gate condition operator. | |||
*/ | |||
public enum Operator { | |||
EQUALS, NOT_EQUALS, GREATER_THAN, LESS_THAN | |||
} | |||
/** | |||
* Quality gate condition evaluation status. | |||
*/ | |||
public enum EvaluationStatus { | |||
/** | |||
* No measure found or measure had no value. The condition has not been evaluated and therefor ignored in | |||
* the computation of the Quality Gate status. | |||
*/ | |||
NO_VALUE, | |||
/** | |||
* Condition evaluated as OK, neither error nor warning thresholds have been reached. | |||
*/ | |||
OK, | |||
/** | |||
* Condition evaluated as WARN, only warning thresholds has been reached. | |||
*/ | |||
WARN, | |||
/** | |||
* Condition evaluated as ERROR, error thresholds has been reached (and most likely warning thresholds too). | |||
*/ | |||
ERROR | |||
} | |||
} |
@@ -27,6 +27,7 @@ public class WebhookModule extends Module { | |||
add( | |||
WebhookCallerImpl.class, | |||
WebhookDeliveryStorage.class, | |||
WebHooksImpl.class); | |||
WebHooksImpl.class, | |||
WebhookPayloadFactoryImpl.class); | |||
} | |||
} |
@@ -17,14 +17,11 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.computation.task.projectanalysis.webhook; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.server.webhook.WebhookPayload; | |||
package org.sonar.server.webhook; | |||
@FunctionalInterface | |||
public interface WebhookPayloadFactory { | |||
WebhookPayload create(PostProjectAnalysisTask.ProjectAnalysis analysis); | |||
WebhookPayload create(ProjectAnalysis analysis); | |||
} |
@@ -17,25 +17,18 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.computation.task.projectanalysis.webhook; | |||
package org.sonar.server.webhook; | |||
import java.io.StringWriter; | |||
import java.io.UnsupportedEncodingException; | |||
import java.io.Writer; | |||
import java.net.URLEncoder; | |||
import java.util.Date; | |||
import javax.annotation.Nullable; | |||
import java.util.Map; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
import org.sonar.api.ce.posttask.Branch; | |||
import org.sonar.api.ce.posttask.CeTask; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.api.ce.posttask.Project; | |||
import org.sonar.api.ce.posttask.QualityGate; | |||
import org.sonar.api.ce.posttask.ScannerContext; | |||
import org.sonar.api.platform.Server; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.text.JsonWriter; | |||
import org.sonar.server.webhook.WebhookPayload; | |||
import static java.lang.String.format; | |||
import static org.sonar.core.config.WebhookProperties.ANALYSIS_PROPERTY_PREFIX; | |||
@@ -52,7 +45,7 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { | |||
} | |||
@Override | |||
public WebhookPayload create(PostProjectAnalysisTask.ProjectAnalysis analysis) { | |||
public WebhookPayload create(ProjectAnalysis analysis) { | |||
Writer string = new StringWriter(); | |||
try (JsonWriter writer = JsonWriter.of(string)) { | |||
writer.beginObject(); | |||
@@ -61,8 +54,8 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { | |||
writeDates(writer, analysis, system2); | |||
writeProject(analysis, writer, analysis.getProject()); | |||
analysis.getBranch().ifPresent(b -> writeBranch(writer, analysis.getProject(), b)); | |||
writeQualityGate(writer, analysis.getQualityGate()); | |||
writeAnalysisProperties(writer, analysis.getScannerContext()); | |||
analysis.getQualityGate().ifPresent(qualityGate -> writeQualityGate(writer, qualityGate)); | |||
writeAnalysisProperties(writer, analysis.getProperties()); | |||
writer.endObject().close(); | |||
return new WebhookPayload(analysis.getProject().getKey(), string.toString()); | |||
} | |||
@@ -72,12 +65,12 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { | |||
writer.prop("serverUrl", server.getPublicRootUrl()); | |||
} | |||
private static void writeDates(JsonWriter writer, PostProjectAnalysisTask.ProjectAnalysis analysis, System2 system2) { | |||
private static void writeDates(JsonWriter writer, ProjectAnalysis analysis, System2 system2) { | |||
analysis.getAnalysisDate().ifPresent(date -> writer.propDateTime("analysedAt", date)); | |||
writer.propDateTime("changedAt", analysis.getAnalysisDate().orElseGet(() -> new Date(system2.now()))); | |||
} | |||
private void writeProject(PostProjectAnalysisTask.ProjectAnalysis analysis, JsonWriter writer, Project project) { | |||
private void writeProject(ProjectAnalysis analysis, JsonWriter writer, Project project) { | |||
writer | |||
.name("project") | |||
.beginObject() | |||
@@ -87,11 +80,11 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { | |||
.endObject(); | |||
} | |||
private static void writeAnalysisProperties(JsonWriter writer, ScannerContext scannerContext) { | |||
private static void writeAnalysisProperties(JsonWriter writer, Map<String, String> properties) { | |||
writer | |||
.name("properties") | |||
.beginObject(); | |||
scannerContext.getProperties().entrySet() | |||
properties.entrySet() | |||
.stream() | |||
.filter(prop -> prop.getKey().startsWith(ANALYSIS_PROPERTY_PREFIX)) | |||
.forEach(prop -> writer.prop(prop.getKey(), prop.getValue())); | |||
@@ -132,34 +125,30 @@ public class WebhookPayloadFactoryImpl implements WebhookPayloadFactory { | |||
} | |||
} | |||
private static void writeQualityGate(JsonWriter writer, @Nullable QualityGate gate) { | |||
if (gate != null) { | |||
private static void writeQualityGate(JsonWriter writer, QualityGate gate) { | |||
writer | |||
.name("qualityGate") | |||
.beginObject() | |||
.prop("name", gate.getName()) | |||
.prop("status", gate.getStatus().toString()) | |||
.name("conditions") | |||
.beginArray(); | |||
for (QualityGate.Condition condition : gate.getConditions()) { | |||
writer | |||
.name("qualityGate") | |||
.beginObject() | |||
.prop("name", gate.getName()) | |||
.prop("status", gate.getStatus().toString()) | |||
.name("conditions") | |||
.beginArray(); | |||
for (QualityGate.Condition condition : gate.getConditions()) { | |||
writer | |||
.beginObject() | |||
.prop("metric", condition.getMetricKey()) | |||
.prop("operator", condition.getOperator().name()); | |||
if (condition.getStatus() != QualityGate.EvaluationStatus.NO_VALUE) { | |||
writer.prop("value", condition.getValue()); | |||
} | |||
writer | |||
.prop("status", condition.getStatus().name()) | |||
.prop("onLeakPeriod", condition.isOnLeakPeriod()) | |||
.prop("errorThreshold", condition.getErrorThreshold()) | |||
.prop("warningThreshold", condition.getWarningThreshold()) | |||
.endObject(); | |||
} | |||
.prop("metric", condition.getMetricKey()) | |||
.prop("operator", condition.getOperator().name()); | |||
condition.getValue().ifPresent(t -> writer.prop("value", t)); | |||
writer | |||
.endArray() | |||
.prop("status", condition.getStatus().name()) | |||
.prop("onLeakPeriod", condition.isOnLeakPeriod()) | |||
.prop("errorThreshold", condition.getErrorThreshold().orElse(null)) | |||
.prop("warningThreshold", condition.getWarningThreshold().orElse(null)) | |||
.endObject(); | |||
} | |||
writer | |||
.endArray() | |||
.endObject(); | |||
} | |||
private static String encode(String toEncode) { |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.computation.task.projectanalysis.webhook; | |||
import java.util.Collections; | |||
import java.util.Date; | |||
import java.util.Random; | |||
import java.util.function.Supplier; | |||
@@ -26,13 +27,14 @@ import org.junit.Before; | |||
import org.junit.Test; | |||
import org.mockito.ArgumentCaptor; | |||
import org.sonar.api.ce.posttask.CeTask; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester; | |||
import org.sonar.api.ce.posttask.Project; | |||
import org.sonar.api.config.Configuration; | |||
import org.sonar.server.computation.task.projectanalysis.component.ConfigurationRepository; | |||
import org.sonar.server.webhook.ProjectAnalysis; | |||
import org.sonar.server.webhook.WebHooks; | |||
import org.sonar.server.webhook.WebhookPayload; | |||
import org.sonar.server.webhook.WebhookPayloadFactory; | |||
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -57,7 +59,7 @@ public class WebhookPostTaskTest { | |||
@Before | |||
public void wireMocks() throws Exception { | |||
when(payloadFactory.create(any(PostProjectAnalysisTask.ProjectAnalysis.class))).thenReturn(webhookPayload); | |||
when(payloadFactory.create(any(ProjectAnalysis.class))).thenReturn(webhookPayload); | |||
when(configurationRepository.getConfiguration()).thenReturn(configuration); | |||
} | |||
@@ -72,9 +74,10 @@ public class WebhookPostTaskTest { | |||
.setStatus(CeTask.Status.values()[new Random().nextInt(CeTask.Status.values().length)]) | |||
.setId(randomAlphanumeric(6)) | |||
.build(); | |||
Date date = new Date(); | |||
PostProjectAnalysisTask.ProjectAnalysis projectAnalysis = PostProjectAnalysisTaskTester.of(underTest) | |||
.at(new Date()) | |||
PostProjectAnalysisTaskTester.of(underTest) | |||
.at(date) | |||
.withCeTask(ceTask) | |||
.withProject(project) | |||
.withScannerContext(newScannerContextBuilder().build()) | |||
@@ -85,7 +88,14 @@ public class WebhookPostTaskTest { | |||
assertThat(supplierCaptor.getValue().get()).isSameAs(webhookPayload); | |||
verify(payloadFactory).create(same(projectAnalysis)); | |||
verify(payloadFactory).create(new ProjectAnalysis( | |||
new org.sonar.server.webhook.CeTask(ceTask.getId(), | |||
org.sonar.server.webhook.CeTask.Status.valueOf(ceTask.getStatus().name())), | |||
new org.sonar.server.webhook.Project(project.getUuid(), project.getKey(), project.getName()), | |||
null, | |||
null, | |||
date.getTime(), | |||
Collections.emptyMap())); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Random; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class BranchTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private Branch underTest = new Branch(true, "b", Branch.Type.SHORT); | |||
@Test | |||
public void constructor_throws_NPE_if_type_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("type can't be null"); | |||
new Branch(new Random().nextBoolean(), "s", null); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.isMain()).isTrue(); | |||
assertThat(underTest.getName()).contains("b"); | |||
assertThat(underTest.getType()).isEqualTo(Branch.Type.SHORT); | |||
Branch underTestWithNull = new Branch(false, null, Branch.Type.LONG); | |||
assertThat(underTestWithNull.isMain()).isFalse(); | |||
assertThat(underTestWithNull.getName()).isEmpty(); | |||
assertThat(underTestWithNull.getType()).isEqualTo(Branch.Type.LONG); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class CeTaskTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private CeTask underTest = new CeTask("A", CeTask.Status.SUCCESS); | |||
@Test | |||
public void constructor_throws_NPE_if_id_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("id can't be null"); | |||
new CeTask(null, CeTask.Status.SUCCESS); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_status_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
new CeTask("B", null); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getId()).isEqualTo("A"); | |||
assertThat(underTest.getStatus()).isEqualTo(CeTask.Status.SUCCESS); | |||
} | |||
} |
@@ -0,0 +1,150 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Date; | |||
import java.util.Map; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static java.util.Collections.emptyMap; | |||
import static java.util.Collections.emptySet; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class ProjectAnalysisTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private final CeTask ceTask = new CeTask("id", CeTask.Status.SUCCESS); | |||
private final Project project = new Project("uuid", "key", "name"); | |||
private final Branch branch = new Branch(true, "name", Branch.Type.SHORT); | |||
private final QualityGate qualityGate = new QualityGate("id", "name", QualityGate.Status.WARN, emptySet()); | |||
private final Map<String, String> properties = ImmutableMap.of("a", "b"); | |||
private ProjectAnalysis underTest = new ProjectAnalysis(ceTask, | |||
project, | |||
branch, | |||
qualityGate, | |||
1L, | |||
properties); | |||
@Test | |||
public void constructor_throws_NPE_if_ceTask_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("ceTask can't be null"); | |||
new ProjectAnalysis(null, | |||
project, | |||
branch, | |||
qualityGate, | |||
1L, | |||
emptyMap()); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_project_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("project can't be null"); | |||
new ProjectAnalysis(ceTask, | |||
null, | |||
branch, | |||
qualityGate, | |||
1L, | |||
emptyMap()); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_properties_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("properties can't be null"); | |||
new ProjectAnalysis(ceTask, | |||
project, | |||
branch, | |||
qualityGate, | |||
1L, | |||
null); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getCeTask()).isSameAs(ceTask); | |||
assertThat(underTest.getProject()).isSameAs(project); | |||
assertThat(underTest.getBranch().get()).isSameAs(branch); | |||
assertThat(underTest.getQualityGate().get()).isSameAs(qualityGate); | |||
assertThat(underTest.getAnalysisDate()).contains(new Date(1L)); | |||
assertThat(underTest.getProperties()).isEqualTo(properties); | |||
ProjectAnalysis underTestWithNulls = new ProjectAnalysis(ceTask, project, null, null, null, emptyMap()); | |||
assertThat(underTestWithNulls.getBranch()).isEmpty(); | |||
assertThat(underTestWithNulls.getQualityGate()).isEmpty(); | |||
assertThat(underTestWithNulls.getAnalysisDate()).isEmpty(); | |||
assertThat(underTestWithNulls.getProperties()).isEmpty(); | |||
} | |||
@Test | |||
public void defines_equals_based_on_all_fields() { | |||
assertThat(underTest).isEqualTo(underTest); | |||
assertThat(underTest).isEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(null); | |||
assertThat(underTest).isNotEqualTo(new Object()); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, branch, qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, null, 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, null, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 2L, properties)); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, emptyMap())); | |||
assertThat(underTest).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, ImmutableMap.of("A", "B"))); | |||
} | |||
@Test | |||
public void defines_hashcode_based_on_all_fields() { | |||
assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); | |||
assertThat(underTest.hashCode()).isEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(new CeTask("2", CeTask.Status.SUCCESS), project, branch, qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, new Project("A", "B", "C"), branch, qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, null, qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, new Branch(false, "B", Branch.Type.SHORT), qualityGate, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, null, 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()) | |||
.isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, new QualityGate("A", "B", QualityGate.Status.WARN, emptySet()), 1L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, null, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 2L, properties).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, emptyMap()).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new ProjectAnalysis(ceTask, project, branch, qualityGate, 1L, ImmutableMap.of("B", "C")).hashCode()); | |||
} | |||
@Test | |||
public void verify_toString() { | |||
assertThat(underTest.toString()).isEqualTo( | |||
"ProjectAnalysis{ceTask=CeTask{id='id', status=SUCCESS}, project=Project{uuid='uuid', key='key', name='name'}, branch=Branch{main=true, name='name', type=SHORT}, qualityGate=QualityGate{id='id', name='name', status=WARN, conditions=[]}, date=1, properties={a=b}}"); | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class ProjectTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private Project underTest = new Project("a", "b", "c"); | |||
@Test | |||
public void constructor_throws_NPE_if_uuid_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("uuid can't be null"); | |||
new Project(null, "b", "c"); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_key_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("key can't be null"); | |||
new Project("a", null, "c"); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_name_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("name can't be null"); | |||
new Project("a", "b", null); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getUuid()).isEqualTo("a"); | |||
assertThat(underTest.getKey()).isEqualTo("b"); | |||
assertThat(underTest.getName()).isEqualTo("c"); | |||
} | |||
} |
@@ -0,0 +1,122 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import java.util.Random; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class QualityGateTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private final Random random = new Random(); | |||
private boolean onLeak = random.nextBoolean(); | |||
private QualityGate.EvaluationStatus randomEvaluationStatus = QualityGate.EvaluationStatus.values()[random.nextInt(QualityGate.EvaluationStatus.values().length)]; | |||
private QualityGate.Condition condition = new QualityGate.Condition( | |||
randomEvaluationStatus, "k", QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val"); | |||
private QualityGate.Status randomStatus = QualityGate.Status.values()[random.nextInt(QualityGate.Status.values().length)]; | |||
private QualityGate underTest = new QualityGate("i", "j", randomStatus, singleton(condition)); | |||
@Test | |||
public void constructor_throws_NPE_if_id_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("id can't be null"); | |||
new QualityGate(null, "j", QualityGate.Status.WARN, singleton(condition)); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_name_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("name can't be null"); | |||
new QualityGate("i", null, QualityGate.Status.WARN, singleton(condition)); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_status_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
new QualityGate("i", "j", null, singleton(condition)); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_conditions_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("conditions can't be null"); | |||
new QualityGate("i", "j", QualityGate.Status.WARN, null); | |||
} | |||
@Test | |||
public void condition_constructor_throws_NPE_if_evaluation_status_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
new QualityGate.Condition(null, "k", QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val"); | |||
} | |||
@Test | |||
public void condition_constructor_throws_NPE_if_metricKey_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("metricKey can't be null"); | |||
new QualityGate.Condition(randomEvaluationStatus, null, QualityGate.Operator.GREATER_THAN, "l", "m", onLeak, "val"); | |||
} | |||
@Test | |||
public void condition_constructor_throws_NPE_if_operator_status_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("operator can't be null"); | |||
new QualityGate.Condition(randomEvaluationStatus, "k", null, "l", "m", onLeak, "val"); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getId()).isEqualTo("i"); | |||
assertThat(underTest.getName()).isEqualTo("j"); | |||
assertThat(underTest.getStatus()).isEqualTo(randomStatus); | |||
assertThat(underTest.getConditions()).isEqualTo(singleton(condition)); | |||
} | |||
@Test | |||
public void verify_condition_getters() { | |||
assertThat(condition.getStatus()).isEqualTo(randomEvaluationStatus); | |||
assertThat(condition.getMetricKey()).isEqualTo("k"); | |||
assertThat(condition.getErrorThreshold()).contains("l"); | |||
assertThat(condition.getWarningThreshold()).contains("m"); | |||
assertThat(condition.isOnLeakPeriod()).isEqualTo(onLeak); | |||
assertThat(condition.getValue()).contains("val"); | |||
QualityGate.Condition conditionWithNulls = new QualityGate.Condition( | |||
randomEvaluationStatus, "k", QualityGate.Operator.GREATER_THAN, null, null, onLeak, null); | |||
assertThat(conditionWithNulls.getErrorThreshold()).isEmpty(); | |||
assertThat(conditionWithNulls.getWarningThreshold()).isEmpty(); | |||
assertThat(conditionWithNulls.getValue()).isEmpty(); | |||
} | |||
} |
@@ -1,33 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.webhook; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.server.computation.task.projectanalysis.webhook.WebhookPayloadFactory; | |||
public class TestWebhookPayloadFactory implements WebhookPayloadFactory { | |||
private static final String FAKE_JSON = "{\"payload\": true}"; | |||
@Override | |||
public WebhookPayload create(PostProjectAnalysisTask.ProjectAnalysis analysis) { | |||
return new WebhookPayload(analysis.getProject().getKey(), FAKE_JSON); | |||
} | |||
} |
@@ -40,6 +40,6 @@ public class WebhookModuleTest { | |||
underTest.configure(container); | |||
assertThat(container.size()).isEqualTo(3 + COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER); | |||
assertThat(container.size()).isEqualTo(4 + COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER); | |||
} | |||
} |
@@ -17,35 +17,22 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.computation.task.projectanalysis.webhook; | |||
package org.sonar.server.webhook; | |||
import com.google.common.collect.ImmutableMap; | |||
import java.util.Date; | |||
import java.util.Map; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.sonar.api.ce.posttask.Branch; | |||
import org.sonar.api.ce.posttask.CeTask; | |||
import org.sonar.api.ce.posttask.PostProjectAnalysisTask; | |||
import org.sonar.api.ce.posttask.Project; | |||
import org.sonar.api.ce.posttask.QualityGate; | |||
import org.sonar.api.ce.posttask.ScannerContext; | |||
import org.sonar.api.platform.Server; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.server.computation.task.projectanalysis.api.posttask.BranchImpl; | |||
import org.sonar.server.webhook.WebhookPayload; | |||
import static java.util.Collections.emptyMap; | |||
import static java.util.Collections.emptySet; | |||
import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newCeTaskBuilder; | |||
import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newConditionBuilder; | |||
import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newProjectBuilder; | |||
import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newQualityGateBuilder; | |||
import static org.sonar.api.ce.posttask.PostProjectAnalysisTaskTester.newScannerContextBuilder; | |||
import static org.sonar.test.JsonAssert.assertJson; | |||
public class WebhookPayloadFactoryImplTest { | |||
@@ -64,23 +51,11 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_for_successful_analysis() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
QualityGate gate = newQualityGateBuilder() | |||
.setId("G1") | |||
.setName("Gate One") | |||
.setStatus(QualityGate.Status.WARN) | |||
.add(newConditionBuilder() | |||
.setMetricKey("coverage") | |||
.setOperator(QualityGate.Operator.GREATER_THAN) | |||
.setOnLeakPeriod(true) | |||
.setWarningThreshold("75.0") | |||
.setErrorThreshold("70.0") | |||
.build(QualityGate.EvaluationStatus.WARN, "74.0")) | |||
.build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap()); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, singleton(new QualityGate.Condition( | |||
QualityGate.EvaluationStatus.WARN, | |||
"coverage", QualityGate.Operator.GREATER_THAN, "70.0", "75.0", true, "74.0"))); | |||
ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertThat(payload.getProjectKey()).isEqualTo(PROJECT_KEY); | |||
@@ -118,22 +93,10 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_with_gate_conditions_without_value() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
QualityGate gate = newQualityGateBuilder() | |||
.setId("G1") | |||
.setName("Gate One") | |||
.setStatus(QualityGate.Status.WARN) | |||
.add(newConditionBuilder() | |||
.setMetricKey("coverage") | |||
.setOperator(QualityGate.Operator.GREATER_THAN) | |||
.setWarningThreshold("75.0") | |||
.setErrorThreshold("70.0") | |||
.buildNoValue()) | |||
.build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap()); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, singleton( | |||
new QualityGate.Condition(QualityGate.EvaluationStatus.NO_VALUE, "coverage", QualityGate.Operator.GREATER_THAN, "70.0", "75.0", false, null))); | |||
ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertThat(payload.getProjectKey()).isEqualTo(PROJECT_KEY); | |||
@@ -168,21 +131,14 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_with_analysis_properties() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
QualityGate gate = newQualityGateBuilder() | |||
.setId("G1") | |||
.setName("Gate One") | |||
.setStatus(QualityGate.Status.WARN) | |||
.build(); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
QualityGate gate = new QualityGate("G1", "Gate One", QualityGate.Status.WARN, emptySet()); | |||
Map<String, String> scannerProperties = ImmutableMap.of( | |||
"sonar.analysis.revision", "ab45d24", | |||
"sonar.analysis.buildNumber", "B123", | |||
"not.prefixed.with.sonar.analysis", "should be ignored", | |||
"ignored", "should be ignored too"); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, scannerProperties); | |||
ProjectAnalysis analysis = newAnalysis(task, gate, null, 1_500_000_000_000L, scannerProperties); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertJson(payload.getJson()) | |||
@@ -215,8 +171,8 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_for_failed_analysis() { | |||
CeTask ceTask = newCeTaskBuilder().setStatus(CeTask.Status.FAILED).setId("#1").build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(ceTask, null, null, 1_500_000_000_000L, emptyMap()); | |||
CeTask ceTask = new CeTask("#1", CeTask.Status.FAILED); | |||
ProjectAnalysis analysis = newAnalysis(ceTask, null, null, 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
@@ -239,8 +195,8 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_for_no_analysis_date() { | |||
CeTask ceTask = newCeTaskBuilder().setStatus(CeTask.Status.FAILED).setId("#1").build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(ceTask, null, null, null, emptyMap()); | |||
CeTask ceTask = new CeTask("#1", CeTask.Status.FAILED); | |||
ProjectAnalysis analysis = newAnalysis(ceTask, null, null, null, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
@@ -262,11 +218,8 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_on_short_branch() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, null, new BranchImpl(false, "feature/foo", Branch.Type.SHORT), 1_500_000_000_000L, emptyMap()); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
ProjectAnalysis analysis = newAnalysis(task, null, new Branch(false, "feature/foo", Branch.Type.SHORT), 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertJson(payload.getJson()) | |||
@@ -282,11 +235,8 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_on_long_branch() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, null, new BranchImpl(false, "feature/foo", Branch.Type.LONG), 1_500_000_000_000L, emptyMap()); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
ProjectAnalysis analysis = newAnalysis(task, null, new Branch(false, "feature/foo", Branch.Type.LONG), 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertJson(payload.getJson()) | |||
@@ -302,11 +252,8 @@ public class WebhookPayloadFactoryImplTest { | |||
@Test | |||
public void create_payload_on_main_branch_without_name() { | |||
CeTask task = newCeTaskBuilder() | |||
.setStatus(CeTask.Status.SUCCESS) | |||
.setId("#1") | |||
.build(); | |||
PostProjectAnalysisTask.ProjectAnalysis analysis = newAnalysis(task, null, new BranchImpl(true, null, Branch.Type.LONG), 1_500_000_000_000L, emptyMap()); | |||
CeTask task = new CeTask("#1", CeTask.Status.SUCCESS); | |||
ProjectAnalysis analysis = newAnalysis(task, null, new Branch(true, null, Branch.Type.LONG), 1_500_000_000_000L, emptyMap()); | |||
WebhookPayload payload = underTest.create(analysis); | |||
assertJson(payload.getJson()) | |||
@@ -319,50 +266,9 @@ public class WebhookPayloadFactoryImplTest { | |||
"}"); | |||
} | |||
private static PostProjectAnalysisTask.ProjectAnalysis newAnalysis(CeTask task, @Nullable QualityGate gate, | |||
private static ProjectAnalysis newAnalysis(CeTask task, @Nullable QualityGate gate, | |||
@Nullable Branch branch, @Nullable Long analysisDate, Map<String, String> scannerProperties) { | |||
return new PostProjectAnalysisTask.ProjectAnalysis() { | |||
@Override | |||
public CeTask getCeTask() { | |||
return task; | |||
} | |||
@Override | |||
public Project getProject() { | |||
return newProjectBuilder() | |||
.setUuid("P1_UUID") | |||
.setKey(PROJECT_KEY) | |||
.setName("Project One") | |||
.build(); | |||
} | |||
@Override | |||
public Optional<Branch> getBranch() { | |||
return Optional.ofNullable(branch); | |||
} | |||
@Override | |||
public QualityGate getQualityGate() { | |||
return gate; | |||
} | |||
@Override | |||
public Date getDate() { | |||
throw new UnsupportedOperationException(); | |||
} | |||
@Override | |||
public Optional<Date> getAnalysisDate() { | |||
return Optional.ofNullable(analysisDate).map(Date::new); | |||
} | |||
@Override | |||
public ScannerContext getScannerContext() { | |||
return newScannerContextBuilder() | |||
.addProperties(scannerProperties) | |||
.build(); | |||
} | |||
}; | |||
return new ProjectAnalysis(task, new Project("P1_UUID", PROJECT_KEY, "Project One"), branch, gate, analysisDate, scannerProperties); | |||
} | |||
} |