@@ -32,6 +32,7 @@ import org.sonar.ce.task.projectanalysis.qualityprofile.RegisterQualityProfileSt | |||
import org.sonar.ce.task.projectanalysis.source.PersistFileSourcesStep; | |||
import org.sonar.ce.task.step.ComputationStep; | |||
import org.sonar.ce.task.step.ExecuteStatelessInitExtensionsStep; | |||
import org.sonar.ce.task.step.ExecuteStatelessOnFinishStep; | |||
/** | |||
* Ordered list of steps classes and instances to be executed for batch processing | |||
@@ -127,6 +128,7 @@ public class ReportComputationSteps extends AbstractComputationSteps { | |||
// notifications are sent at the end, so that webapp displays up-to-date information | |||
SendIssueNotificationsStep.class, | |||
ExecuteStatelessOnFinishStep.class, | |||
PublishTaskResultStep.class, | |||
TriggerViewRefreshStep.class); | |||
@@ -0,0 +1,54 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2024 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.ce.task.step; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
import org.springframework.beans.factory.annotation.Autowired; | |||
/** | |||
* This step is executed when the computation is about to be finished. | |||
*/ | |||
@ComputeEngineSide | |||
public class ExecuteStatelessOnFinishStep implements ComputationStep { | |||
private final StatelessFinishExtension[] extensions; | |||
@Autowired(required = false) | |||
public ExecuteStatelessOnFinishStep(StatelessFinishExtension[] extensions) { | |||
this.extensions = extensions; | |||
} | |||
@Autowired(required = false) | |||
public ExecuteStatelessOnFinishStep() { | |||
this(new StatelessFinishExtension[0]); | |||
} | |||
@Override | |||
public void execute(Context context) { | |||
for (StatelessFinishExtension extension : extensions) { | |||
extension.onFinish(); | |||
} | |||
} | |||
@Override | |||
public String getDescription() { | |||
return "Actions to execute when the computation is about to be finished"; | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2024 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.ce.task.step; | |||
import org.sonar.api.ExtensionPoint; | |||
import org.sonar.api.ce.ComputeEngineSide; | |||
/** | |||
* Extension point that is called during processing of a task | |||
* by {@link ExecuteStatelessOnFinishStep}. | |||
* It is stateless, the same instance is reused for all tasks. | |||
* As a consequence Compute Engine task components can't be injected | |||
* as dependencies. | |||
*/ | |||
@ComputeEngineSide | |||
@ExtensionPoint | |||
public interface StatelessFinishExtension { | |||
/** | |||
* This method can make the task fail by throwing a {@link RuntimeException} and it is called befoe the task is finished | |||
*/ | |||
void onFinish(); | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2024 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.ce.task.step; | |||
import org.junit.Test; | |||
import org.mockito.Mockito; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.verify; | |||
public class ExecuteStatelessOnFinishStepTest { | |||
@Test | |||
public void execute_whenNoExtensionsRegistered_shouldNotThrowExeption() { | |||
ExecuteStatelessOnFinishStep step = new ExecuteStatelessOnFinishStep(); | |||
assertDoesNotThrow(() -> step.execute(mock(ComputationStep.Context.class))); | |||
} | |||
@Test | |||
public void execute_whenTwoExtensionsRegistered_shouldCallTwoOfThem() { | |||
StatelessFinishExtension firstMock = mock(StatelessFinishExtension.class); | |||
StatelessFinishExtension secondMock = mock(StatelessFinishExtension.class); | |||
StatelessFinishExtension[] extensions = new StatelessFinishExtension[]{firstMock, secondMock}; | |||
ExecuteStatelessOnFinishStep step = new ExecuteStatelessOnFinishStep(extensions); | |||
step.execute(mock(ComputationStep.Context.class)); | |||
verify(firstMock, Mockito.times(1)).onFinish(); | |||
verify(secondMock, Mockito.times(1)).onFinish(); | |||
} | |||
@Test | |||
public void getDescription_shouldReturnNotEmptyString() { | |||
ExecuteStatelessOnFinishStep step = new ExecuteStatelessOnFinishStep(); | |||
assertThat(step.getDescription()).isNotEmpty(); | |||
} | |||
} |