You've already forked sonarqube-community-branch-plugin
mirror of
https://github.com/mc1arke/sonarqube-community-branch-plugin.git
synced 2025-10-08 22:52:13 +02:00
#1115: Differentiate Gitlab pipelines on monorepos
The Gitlab decorator used a constant name for the pipeline which meant the last executed pipeline in a monorepo may allow a Merge Request to be marked as successful even if other projects in the repository had failed their pipelines. To overcome this the decorator has been altered to include the project key in the pipeline name if the project is a monorepo to ensure that the pipeline is unique across all projects in the monorepo.
This commit is contained in:
committed by
Michael Clarke
parent
7085d58013
commit
9e5caf732b
@@ -111,7 +111,7 @@ public abstract class DiscussionAwarePullRequestDecorator<C, P, U, D, N> impleme
|
|||||||
|
|
||||||
AnalysisSummary analysisSummary = reportGenerator.createAnalysisSummary(analysis);
|
AnalysisSummary analysisSummary = reportGenerator.createAnalysisSummary(analysis);
|
||||||
submitSummaryNote(client, pullRequest, analysis, analysisSummary);
|
submitSummaryNote(client, pullRequest, analysis, analysisSummary);
|
||||||
submitPipelineStatus(client, pullRequest, analysis, analysisSummary);
|
submitPipelineStatus(client, pullRequest, analysis, analysisSummary, projectAlmSettingDto);
|
||||||
|
|
||||||
DecorationResult.Builder builder = DecorationResult.builder();
|
DecorationResult.Builder builder = DecorationResult.builder();
|
||||||
createFrontEndUrl(pullRequest, analysis).ifPresent(builder::withPullRequestUrl);
|
createFrontEndUrl(pullRequest, analysis).ifPresent(builder::withPullRequestUrl);
|
||||||
@@ -130,7 +130,7 @@ public abstract class DiscussionAwarePullRequestDecorator<C, P, U, D, N> impleme
|
|||||||
|
|
||||||
protected abstract List<String> getCommitIdsForPullRequest(C client, P pullRequest);
|
protected abstract List<String> getCommitIdsForPullRequest(C client, P pullRequest);
|
||||||
|
|
||||||
protected abstract void submitPipelineStatus(C client, P pullRequest, AnalysisDetails analysis, AnalysisSummary analysisSummary);
|
protected abstract void submitPipelineStatus(C client, P pullRequest, AnalysisDetails analysis, AnalysisSummary analysisSummary, ProjectAlmSettingDto projectAlmSettingDto);
|
||||||
|
|
||||||
protected abstract void submitCommitNoteForIssue(C client, P pullRequest, PostAnalysisIssueVisitor.ComponentIssue issue, String filePath,
|
protected abstract void submitCommitNoteForIssue(C client, P pullRequest, PostAnalysisIssueVisitor.ComponentIssue issue, String filePath,
|
||||||
AnalysisDetails analysis, AnalysisIssueSummary analysisIssueSummary);
|
AnalysisDetails analysis, AnalysisIssueSummary analysisIssueSummary);
|
||||||
|
@@ -144,7 +144,7 @@ public class AzureDevOpsPullRequestDecorator extends DiscussionAwarePullRequestD
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void submitPipelineStatus(AzureDevopsClient client, PullRequest pullRequest, AnalysisDetails analysis, AnalysisSummary analysisSummary) {
|
protected void submitPipelineStatus(AzureDevopsClient client, PullRequest pullRequest, AnalysisDetails analysis, AnalysisSummary analysisSummary, ProjectAlmSettingDto projectAlmSettingDto) {
|
||||||
try {
|
try {
|
||||||
GitPullRequestStatus gitPullRequestStatus = new GitPullRequestStatus(
|
GitPullRequestStatus gitPullRequestStatus = new GitPullRequestStatus(
|
||||||
GitStatusStateMapper.toGitStatusState(analysis.getQualityGateStatus()),
|
GitStatusStateMapper.toGitStatusState(analysis.getQualityGateStatus()),
|
||||||
|
@@ -122,14 +122,15 @@ public class GitlabMergeRequestDecorator extends DiscussionAwarePullRequestDecor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void submitPipelineStatus(GitlabClient gitlabClient, MergeRequest mergeRequest, AnalysisDetails analysis,
|
protected void submitPipelineStatus(GitlabClient gitlabClient, MergeRequest mergeRequest, AnalysisDetails analysis,
|
||||||
AnalysisSummary analysisSummary) {
|
AnalysisSummary analysisSummary, ProjectAlmSettingDto projectAlmSettingDto) {
|
||||||
Long pipelineId = analysis.getScannerProperty(PULLREQUEST_GITLAB_PIPELINE_ID)
|
Long pipelineId = analysis.getScannerProperty(PULLREQUEST_GITLAB_PIPELINE_ID)
|
||||||
.map(Long::parseLong)
|
.map(Long::parseLong)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PipelineStatus pipelineStatus = new PipelineStatus("SonarQube",
|
boolean isMonorepo = Boolean.TRUE.equals(projectAlmSettingDto.getMonorepo());
|
||||||
"SonarQube Status",
|
PipelineStatus pipelineStatus = new PipelineStatus("SonarQube" + (isMonorepo ? " - " + analysis.getAnalysisProjectKey() : ""),
|
||||||
|
"SonarQube Status" + (isMonorepo ? " - " + analysis.getAnalysisProjectName() : ""),
|
||||||
analysis.getQualityGateStatus() == QualityGate.Status.OK ? PipelineStatus.State.SUCCESS : PipelineStatus.State.FAILED,
|
analysis.getQualityGateStatus() == QualityGate.Status.OK ? PipelineStatus.State.SUCCESS : PipelineStatus.State.FAILED,
|
||||||
analysisSummary.getDashboardUrl(),
|
analysisSummary.getDashboardUrl(),
|
||||||
analysisSummary.getNewCoverage(),
|
analysisSummary.getNewCoverage(),
|
||||||
|
@@ -73,20 +73,21 @@ class GitlabMergeRequestDecoratorIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void decorateQualityGateStatusOk() {
|
void decorateQualityGateStatusOk() {
|
||||||
decorateQualityGateStatus(QualityGate.Status.OK);
|
decorateQualityGateStatus(QualityGate.Status.OK, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void decorateQualityGateStatusError() {
|
void decorateQualityGateStatusError() {
|
||||||
decorateQualityGateStatus(QualityGate.Status.ERROR);
|
decorateQualityGateStatus(QualityGate.Status.ERROR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void decorateQualityGateStatus(QualityGate.Status status) {
|
private void decorateQualityGateStatus(QualityGate.Status status, boolean isMonorepo) {
|
||||||
String user = "sonar_user";
|
String user = "sonar_user";
|
||||||
String repositorySlug = "repo/slug";
|
String repositorySlug = "repo/slug";
|
||||||
String commitSha = "commitSha";
|
String commitSha = "commitSha";
|
||||||
long mergeRequestIid = 6;
|
long mergeRequestIid = 6;
|
||||||
String projectKey = "projectKey";
|
String projectKey = "projectKey";
|
||||||
|
String projectName = "project name";
|
||||||
String sonarRootUrl = "http://sonar:9000/sonar";
|
String sonarRootUrl = "http://sonar:9000/sonar";
|
||||||
String discussionId = "6a9c1750b37d513a43987b574953fceb50b03ce7";
|
String discussionId = "6a9c1750b37d513a43987b574953fceb50b03ce7";
|
||||||
String noteId = "1126";
|
String noteId = "1126";
|
||||||
@@ -95,16 +96,18 @@ class GitlabMergeRequestDecoratorIntegrationTest {
|
|||||||
int lineNumber = 5;
|
int lineNumber = 5;
|
||||||
|
|
||||||
ProjectAlmSettingDto projectAlmSettingDto = mock();
|
ProjectAlmSettingDto projectAlmSettingDto = mock();
|
||||||
|
when(projectAlmSettingDto.getAlmRepo()).thenReturn(repositorySlug);
|
||||||
|
when(projectAlmSettingDto.getMonorepo()).thenReturn(isMonorepo);
|
||||||
|
|
||||||
AlmSettingDto almSettingDto = mock();
|
AlmSettingDto almSettingDto = mock();
|
||||||
when(almSettingDto.getDecryptedPersonalAccessToken(any())).thenReturn("token");
|
when(almSettingDto.getDecryptedPersonalAccessToken(any())).thenReturn("token");
|
||||||
when(almSettingDto.getUrl()).thenReturn(wireMockExtension.baseUrl() + "/api/v4");
|
when(almSettingDto.getUrl()).thenReturn(wireMockExtension.baseUrl() + "/api/v4");
|
||||||
|
|
||||||
AnalysisDetails analysisDetails = mock();
|
AnalysisDetails analysisDetails = mock();
|
||||||
when(almSettingDto.getUrl()).thenReturn(wireMockExtension.baseUrl() + "/api/v4");
|
when(almSettingDto.getUrl()).thenReturn(wireMockExtension.baseUrl() + "/api/v4");
|
||||||
when(projectAlmSettingDto.getAlmRepo()).thenReturn(repositorySlug);
|
|
||||||
when(projectAlmSettingDto.getMonorepo()).thenReturn(true);
|
|
||||||
when(analysisDetails.getQualityGateStatus()).thenReturn(status);
|
when(analysisDetails.getQualityGateStatus()).thenReturn(status);
|
||||||
when(analysisDetails.getAnalysisProjectKey()).thenReturn(projectKey);
|
when(analysisDetails.getAnalysisProjectKey()).thenReturn(projectKey);
|
||||||
|
when(analysisDetails.getAnalysisProjectName()).thenReturn(projectName);
|
||||||
when(analysisDetails.getPullRequestId()).thenReturn(Long.toString(mergeRequestIid));
|
when(analysisDetails.getPullRequestId()).thenReturn(Long.toString(mergeRequestIid));
|
||||||
when(analysisDetails.getCommitSha()).thenReturn(commitSha);
|
when(analysisDetails.getCommitSha()).thenReturn(commitSha);
|
||||||
|
|
||||||
@@ -215,9 +218,15 @@ class GitlabMergeRequestDecoratorIntegrationTest {
|
|||||||
.withRequestBody(equalTo("body=" + urlEncode("This issue no longer exists in SonarQube, but due to other comments being present in this discussion, the discussion is not being being closed automatically. Please manually resolve this discussion once the other comments have been reviewed.")))
|
.withRequestBody(equalTo("body=" + urlEncode("This issue no longer exists in SonarQube, but due to other comments being present in this discussion, the discussion is not being being closed automatically. Please manually resolve this discussion once the other comments have been reviewed.")))
|
||||||
.willReturn(created()));
|
.willReturn(created()));
|
||||||
|
|
||||||
wireMockExtension.stubFor(post(urlEqualTo("/api/v4/projects/" + sourceProjectId + "/statuses/" + commitSha + "?state=" + (status == QualityGate.Status.OK ? "success" : "failed")))
|
if (isMonorepo) {
|
||||||
.withRequestBody(equalTo("name=SonarQube&target_url=" + urlEncode(sonarRootUrl + "/dashboard?id=" + projectKey + "&pullRequest=" + mergeRequestIid) + "&description=SonarQube+Status&coverage=10"))
|
wireMockExtension.stubFor(post(urlEqualTo("/api/v4/projects/" + sourceProjectId + "/statuses/" + commitSha + "?state=" + (status == QualityGate.Status.OK ? "success" : "failed")))
|
||||||
.willReturn(created()));
|
.withRequestBody(equalTo("name=SonarQube+-+projectKey&target_url=" + urlEncode(sonarRootUrl + "/dashboard?id=" + projectKey + "&pullRequest=" + mergeRequestIid) + "&description=SonarQube+Status+-+project+name&coverage=10"))
|
||||||
|
.willReturn(created()));
|
||||||
|
} else {
|
||||||
|
wireMockExtension.stubFor(post(urlEqualTo("/api/v4/projects/" + sourceProjectId + "/statuses/" + commitSha + "?state=" + (status == QualityGate.Status.OK ? "success" : "failed")))
|
||||||
|
.withRequestBody(equalTo("name=SonarQube&target_url=" + urlEncode(sonarRootUrl + "/dashboard?id=" + projectKey + "&pullRequest=" + mergeRequestIid) + "&description=SonarQube+Status&coverage=10"))
|
||||||
|
.willReturn(created()));
|
||||||
|
}
|
||||||
|
|
||||||
wireMockExtension.stubFor(post(urlPathEqualTo("/api/v4/projects/" + sourceProjectId + "/merge_requests/" + mergeRequestIid + "/discussions"))
|
wireMockExtension.stubFor(post(urlPathEqualTo("/api/v4/projects/" + sourceProjectId + "/merge_requests/" + mergeRequestIid + "/discussions"))
|
||||||
.withRequestBody(equalTo("body=summary+comm%C3%A9nt%0A%0A%5Blink+text%5D"))
|
.withRequestBody(equalTo("body=summary+comm%C3%A9nt%0A%0A%5Blink+text%5D"))
|
||||||
@@ -244,6 +253,13 @@ class GitlabMergeRequestDecoratorIntegrationTest {
|
|||||||
.willReturn(ok())
|
.willReturn(ok())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!isMonorepo) {
|
||||||
|
wireMockExtension.stubFor(put(urlPathEqualTo("/api/v4/projects/" + sourceProjectId + "/merge_requests/" + mergeRequestIid + "/discussions/" + discussionId + 7))
|
||||||
|
.withQueryParam("resolved", equalTo("true"))
|
||||||
|
.willReturn(ok())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
LinkHeaderReader linkHeaderReader = mock();
|
LinkHeaderReader linkHeaderReader = mock();
|
||||||
Settings settings = mock();
|
Settings settings = mock();
|
||||||
Encryption encryption = mock();
|
Encryption encryption = mock();
|
||||||
|
Reference in New Issue
Block a user