/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.thoughtworks.go.server.service; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import com.thoughtworks.go.config.*; import com.thoughtworks.go.config.materials.MaterialConfigs; import com.thoughtworks.go.config.materials.ScmMaterialConfig; import com.thoughtworks.go.config.materials.dependency.DependencyMaterial; import com.thoughtworks.go.config.materials.svn.SvnMaterialConfig; import com.thoughtworks.go.domain.*; import com.thoughtworks.go.domain.buildcause.BuildCause; import com.thoughtworks.go.domain.materials.Material; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.domain.materials.dependency.DependencyMaterialRevision; import com.thoughtworks.go.domain.materials.svn.SubversionRevision; import com.thoughtworks.go.fixture.ArtifactsDiskIsFull; import com.thoughtworks.go.fixture.PipelineWithMultipleStages; import com.thoughtworks.go.fixture.PipelineWithTwoStages; import com.thoughtworks.go.helper.ModificationsMother; import com.thoughtworks.go.helper.PipelineConfigMother; import com.thoughtworks.go.helper.StageConfigMother; import com.thoughtworks.go.i18n.Localizer; import com.thoughtworks.go.presentation.pipelinehistory.EmptyPipelineInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.NullStageHistoryItem; import com.thoughtworks.go.presentation.pipelinehistory.PipelineGroupModel; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.PipelineInstanceModels; import com.thoughtworks.go.presentation.pipelinehistory.PipelineModel; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModel; import com.thoughtworks.go.presentation.pipelinehistory.StageInstanceModels; import com.thoughtworks.go.server.cache.GoCache; import com.thoughtworks.go.server.dao.DatabaseAccessHelper; import com.thoughtworks.go.server.domain.PipelineTimeline; import com.thoughtworks.go.server.domain.Username; import com.thoughtworks.go.server.domain.user.PipelineSelections; import com.thoughtworks.go.server.materials.DependencyMaterialUpdateNotifier; import com.thoughtworks.go.server.persistence.MaterialRepository; import com.thoughtworks.go.server.persistence.PipelineRepository; import com.thoughtworks.go.server.scheduling.TriggerMonitor; import com.thoughtworks.go.server.service.result.HttpLocalizedOperationResult; import com.thoughtworks.go.server.service.result.HttpOperationResult; import com.thoughtworks.go.server.service.support.toggle.FeatureToggleService; import com.thoughtworks.go.server.service.support.toggle.Toggles; import com.thoughtworks.go.server.transaction.TransactionTemplate; import com.thoughtworks.go.server.util.Pagination; import com.thoughtworks.go.util.GoConfigFileHelper; import com.thoughtworks.go.util.TestFileUtil; import com.thoughtworks.go.util.TimeConverter; import com.thoughtworks.go.util.TimeProvider; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsInstanceOf.instanceOf; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:WEB-INF/applicationContext-global.xml", "classpath:WEB-INF/applicationContext-dataLocalAccess.xml", "classpath:WEB-INF/applicationContext-acegi-security.xml" }) public class PipelineHistoryServiceIntegrationTest { @Autowired private GoConfigDao goConfigDao; @Autowired private PipelineHistoryService pipelineHistoryService; @Autowired private CachedCurrentActivityService currentActivityService; @Autowired private DatabaseAccessHelper dbHelper; @Autowired private MaterialRepository materialRepository; @Autowired private GoConfigService goConfigService; @Autowired private TriggerMonitor triggerMonitor; @Autowired private PipelineRepository pipelineRepository; @Autowired private PipelineTimeline pipelineTimeline; @Autowired private GoCache goCache; @Autowired private TransactionTemplate transactionTemplate; @Autowired private PipelinePauseService pipelinePauseService; @Autowired private Localizer localizer; @Autowired private FeatureToggleService featureToggleService; @Autowired private DependencyMaterialUpdateNotifier notifier; private GoConfigFileHelper configHelper = new GoConfigFileHelper(); private PipelineWithMultipleStages pipelineOne; private PipelineWithTwoStages pipelineTwo; private ArtifactsDiskIsFull diskIsFull; private boolean pipelineCommentFeatureToggleState; @Before public void setUp() throws Exception { goCache.clear(); pipelineOne = new PipelineWithMultipleStages(3, materialRepository, transactionTemplate); pipelineOne.setGroupName("group1"); pipelineTwo = new PipelineWithTwoStages(materialRepository, transactionTemplate); pipelineTwo.setGroupName("group2"); diskIsFull = new ArtifactsDiskIsFull(); configHelper.usingCruiseConfigDao(goConfigDao); configHelper.onSetUp(); dbHelper.onSetUp(); pipelineOne.usingConfigHelper(configHelper).usingDbHelper(dbHelper).onSetUp(); pipelineTwo.usingConfigHelper(configHelper).usingDbHelper(dbHelper).addToSetup(); pipelineOne.configStageAsManualApprovalWithApprovedUsers(pipelineOne.stageName(2), "jez"); configHelper.addSecurityWithAdminConfig(); configHelper.setOperatePermissionForGroup("group1", "jez"); pipelineCommentFeatureToggleState = featureToggleService.isToggleOn(Toggles.PIPELINE_COMMENT_FEATURE_TOGGLE_KEY); featureToggleService.changeValueOfToggle(Toggles.PIPELINE_COMMENT_FEATURE_TOGGLE_KEY, true); notifier.disableUpdates(); } @After public void tearDown() throws Exception { notifier.enableUpdates(); diskIsFull.onTearDown(); dbHelper.onTearDown(); pipelineOne.onTearDown(); configHelper.onTearDown(); featureToggleService.changeValueOfToggle(Toggles.PIPELINE_COMMENT_FEATURE_TOGGLE_KEY, pipelineCommentFeatureToggleState); } @Test public void shouldLoadPipelineHistory() throws Exception { pipelineOne.createdPipelineWithAllStagesPassed(); PipelineInstanceModels history = pipelineHistoryService.load(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 10), "jez", true); assertThat(history.size(), is(1)); StageInstanceModels stageHistory = history.first().getStageHistory(); assertThat(stageHistory.size(), is(3)); for (StageInstanceModel stageHistoryItem : stageHistory) { assertThat(stageHistoryItem.isScheduled(), is(true)); assertThat(stageHistoryItem.getCanRun(), is(true)); } } @Test public void shouldGetLatestPipelineInstanceWithPreviousStateFromAllPipelineGroups() throws Exception { configHelper.setViewPermissionForGroup("group1", "jez"); dbHelper.updateNaturalOrder(pipelineOne.createdPipelineWithAllStagesPassed().getId(), 1.0); dbHelper.updateNaturalOrder(pipelineTwo.createdPipelineWithAllStagesPassed().getId(), 1.0); dbHelper.updateNaturalOrder(pipelineTwo.createPipelineWithFirstStagePassedAndSecondStageRunning().getId(), 2.0); Pipeline toRerun = pipelineTwo.createPipelineWithFirstStagePassedAndSecondStageHasNotStarted(); pipelineTwo.createPipelineWithFirstStagePassedAndSecondStageHasNotStarted(); dbHelper.updateNaturalOrder(toRerun.getId(), 3); dbHelper.scheduleStage(toRerun, pipelineTwo.devStage()); pipelineRepository.updatePipelineTimeline(pipelineTimeline, new ArrayList<>()); List<PipelineGroupModel> groupModels = pipelineHistoryService.allActivePipelineInstances(new Username(new CaseInsensitiveString("jez")), PipelineSelections.ALL); assertThat(groupModels.size(), is(2)); List<PipelineModel> pipelineOneModels = groupModels.get(1).getPipelineModels(); assertThat(pipelineOneModels.size(), is(1)); PipelineInstanceModels pipelineOneInstances = pipelineOneModels.get(0).getActivePipelineInstances(); assertThat(pipelineOneInstances.size(), is(1)); PipelineInstanceModel pipelineOne = pipelineOneInstances.get(0); assertThat(pipelineOne.getCounter(), is(1)); List<PipelineModel> pipelineTwoModels = groupModels.get(0).getPipelineModels(); assertThat(pipelineTwoModels.size(), is(1)); PipelineInstanceModels pipelineTwoInstances = pipelineTwoModels.get(0).getActivePipelineInstances(); assertThat(pipelineTwoInstances.size(), is(3)); PipelineInstanceModel pipelineTwoJustScheduled = pipelineTwoInstances.get(0); assertThat(pipelineTwoJustScheduled.getCounter(), is(4)); assertThat(pipelineTwoJustScheduled.getStageHistory().size(), is(2)); StageInstanceModel activeStage = pipelineTwoJustScheduled.activeStage(); assertThat(activeStage, is(nullValue())); PipelineInstanceModel pipelineTwoPostFirstStage = pipelineTwoInstances.get(1); assertThat(pipelineTwoPostFirstStage.getCounter(), is(3)); assertThat(pipelineTwoPostFirstStage.getStageHistory().size(), is(2)); activeStage = pipelineTwoPostFirstStage.activeStage(); assertThat(activeStage.getName(), is("dev")); assertThat(activeStage.hasPreviousStage(), is(true)); assertThat(activeStage.getPreviousStage().getResult(), is(StageResult.Passed)); PipelineInstanceModel pipelineTwoWithSecondStageRunning = pipelineTwoInstances.get(2); assertThat(pipelineTwoWithSecondStageRunning.getCounter(), is(2)); assertThat(pipelineTwoWithSecondStageRunning.getStageHistory().size(), is(2)); activeStage = pipelineTwoWithSecondStageRunning.activeStage(); assertThat(activeStage.getName(), is("ft")); assertThat(activeStage.hasPreviousStage(), is(true)); assertThat(activeStage.getPreviousStage().getResult(), is(StageResult.Passed)); } @Test public void shouldIncludePauseInformationWhenGettingLatestPipelineInstanceFromAllPipelineGroups() throws Exception { pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setOperatePermissionForGroup("group1","chris", "raghu"); Username userNameChris = new Username(new CaseInsensitiveString("chris")); pipelinePauseService.pause(pipelineOne.pipelineName, "paused", userNameChris); Username userNameRaghu = new Username(new CaseInsensitiveString("raghu")); pipelinePauseService.pause(pipelineTwo.pipelineName, "other paused", userNameRaghu); configHelper.setViewPermissionForGroup("group1", "jez"); List<PipelineGroupModel> groupModels = pipelineHistoryService.allActivePipelineInstances(new Username(new CaseInsensitiveString("jez")), PipelineSelections.ALL); assertThat(groupModels.size(), is(2)); List<PipelineModel> pipelineOneModels = groupModels.get(0).getPipelineModels(); assertThat(pipelineOneModels.size(), is(1)); PipelinePauseInfo pausedInfo = pipelineOneModels.get(0).getPausedInfo(); assertThat("isPaused", pausedInfo.isPaused(), is(true)); assertThat(pausedInfo.getPauseBy(), is("chris")); assertThat(pausedInfo.getPauseCause(), is("paused")); List<PipelineModel> pipelineTwoModels = groupModels.get(1).getPipelineModels(); assertThat(pipelineTwoModels.size(), is(1)); PipelinePauseInfo pipelineTwoPausedInfo = pipelineTwoModels.get(0).getPausedInfo(); assertThat("isPaused", pipelineTwoPausedInfo.isPaused(), is(true)); assertThat(pipelineTwoPausedInfo.getPauseBy(), is("raghu")); assertThat(pipelineTwoPausedInfo.getPauseCause(), is("other paused")); } @Test public void shouldSkipPipelinesThatAreScheduledButNotInConfigFile() throws Exception { pipelineOne.createPipelineWithFirstStageScheduled(); configHelper.removePipeline(pipelineOne.pipelineName); configHelper.removePipeline(pipelineTwo.pipelineName); List<PipelineGroupModel> groupModels = pipelineHistoryService.allActivePipelineInstances(new Username(new CaseInsensitiveString("jez")), PipelineSelections.ALL); assertThat(groupModels.size(), is(0)); } @Test public void shouldReturnPipelinesInConfigOrder() throws Exception { pipelineTwo.createdPipelineWithAllStagesPassed(); pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "jez"); List<PipelineGroupModel> groupModels = pipelineHistoryService.allActivePipelineInstances(new Username(new CaseInsensitiveString("jez")), PipelineSelections.ALL); assertThat(groupModels.size(), is(2)); List<PipelineModel> pipelineOneModels = groupModels.get(0).getPipelineModels(); assertThat(pipelineOneModels.size(), is(1)); assertThat(pipelineOneModels.get(0).getActivePipelineInstances().get(0).getName(), is(pipelineTwo.pipelineName)); List<PipelineModel> pipelineTwoModels = groupModels.get(1).getPipelineModels(); assertThat(pipelineTwoModels.size(), is(1)); assertThat(pipelineTwoModels.get(0).getActivePipelineInstances().get(0).getName(), is(pipelineOne.pipelineName)); } @Test public void shouldReturnActiveInstanceOfAPipeline() throws Exception { pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "jez"); String pipelineName = pipelineOne.pipelineName; List<PipelineGroupModel> groupModels = pipelineHistoryService.getActivePipelineInstance(new Username(new CaseInsensitiveString("jez")), pipelineName.toUpperCase()); assertThat(groupModels.size(), is(1)); List<PipelineModel> pipelineOneModels = groupModels.get(0).getPipelineModels(); assertThat(pipelineOneModels.size(), is(1)); assertThat(pipelineOneModels.get(0).getActivePipelineInstances().get(0).getName(), is(pipelineName)); } @Test public void shouldRememberOldStagesWhenConfigFileChanges() throws Exception { configHelper.removePipeline(pipelineTwo.pipelineName); Pipeline toRerun = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.addStageToPipeline(pipelineOne.pipelineName, "brand_new_stage", 1, "unit"); pipelineOne.createdPipelineWithAllStagesPassed(); dbHelper.scheduleStage(toRerun, pipelineOne.devStage()); configHelper.setViewPermissionForGroup("group1", "jez"); List<PipelineGroupModel> groupModels = pipelineHistoryService.allActivePipelineInstances(new Username(new CaseInsensitiveString("jez")), PipelineSelections.ALL); assertThat(groupModels.size(), is(1)); List<PipelineModel> pipelineOneModels = groupModels.get(0).getPipelineModels(); assertThat(pipelineOneModels.size(), is(1)); PipelineInstanceModels pipelineTwoInstances = pipelineOneModels.get(0).getActivePipelineInstances(); assertThat(pipelineTwoInstances.size(), is(2)); assertThat(pipelineTwoInstances.get(0).getCounter(), is(2)); assertThat(pipelineTwoInstances.get(0).getStageHistory().size(), is(4)); assertThat(pipelineTwoInstances.get(1).getCounter(), is(1)); assertThat(pipelineTwoInstances.get(1).getStageHistory().size(), is(3)); } @Test public void shouldLoadPipelineHistoryWithEmptyDefaultIfNone() throws Exception { configHelper.setViewPermissionForGroup("group1", "jez"); PipelineInstanceModels history = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 1), "jez"); assertThat(history.size(), is(1)); StageInstanceModels stageHistory = history.first().getStageHistory(); assertThat(stageHistory.size(), is(3)); assertStageHistory(stageHistory.get(0), false, true); assertStageHistory(stageHistory.get(1), false, false); assertStageHistory(stageHistory.get(2), false, false); } private void assertStageHistory(StageInstanceModel stageHistoryItem, boolean isScehduled, boolean canRun) { assertThat(stageHistoryItem.isScheduled(), is(isScehduled)); assertThat(stageHistoryItem.getCanRun(), is(canRun)); } @Test public void shouldNotLoadPipelinesThatTheUserDoesNotHavePermissionToSee() throws Exception { configHelper.addSecurityWithAdminConfig(); configHelper.setViewPermissionForGroup("group1", "foo"); PipelineInstanceModels history = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 1), "non-admin-user"); assertThat(history.size(), is(0)); } @Test public void shouldLoadPipelineHistoryWithPlaceholderStagesPopulated() throws Exception { pipelineOne.createPipelineWithFirstStagePassedAndSecondStageHasNotStarted(); PipelineInstanceModels history = pipelineHistoryService.load(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 10), "jez", true); StageInstanceModels stageHistory = history.first().getStageHistory(); assertThat("Should populate 2 placeholder stages from config", stageHistory.size(), is(3)); assertThat(stageHistory.first().isScheduled(), is(true)); assertThat(stageHistory.first().isAutoApproved(), is(true)); assertThat(stageHistory.first().getCanRun(), is(true)); assertThat(stageHistory.get(1).isScheduled(), is(false)); assertThat(stageHistory.get(1).isAutoApproved(), is(false)); assertThat("The first future stage should can run", stageHistory.get(1).getCanRun(), is(true)); assertThat(stageHistory.get(2).isScheduled(), is(false)); assertThat(stageHistory.get(2).isAutoApproved(), is(true)); assertThat("The second future stage should can not run", stageHistory.get(2).getCanRun(), is(false)); } @Test public void shouldMakePipelineInstanceCanRunFalseWhenDiskSpaceIsEmpty() throws Exception { diskIsFull.onSetUp(); configHelper.updateArtifactRoot(TestFileUtil.createTempFolder("serverlogs").getAbsolutePath()); pipelineOne.createdPipelineWithAllStagesPassed(); PipelineInstanceModels history = pipelineHistoryService.load(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 10), "jez", true); assertThat(history.size(), is(1)); assertThat(history.first().getCanRun(), is(false)); StageInstanceModels stageHistory = history.first().getStageHistory(); assertThat(stageHistory.size(), is(3)); for (StageInstanceModel stageHistoryItem : stageHistory) { assertThat(stageHistoryItem.isScheduled(), is(true)); assertThat(stageHistoryItem.getCanRun(), is(false)); } } @Test public void shouldSetCanRunWhenFirstStageIsManuallyTriggerable() throws Exception { configHelper.setViewPermissionForGroup(pipelineOne.groupName, "jez"); pipelineOne.createPipelineWithFirstStageScheduled(); pipelineOne.moveStageToEnd(CaseInsensitiveString.str(pipelineOne.stageConfig(1).name())); PipelineInstanceModels pipelineInstanceModels = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 1, "jez"); assertThat(pipelineInstanceModels.get(0).getCanRun(), is(true)); } @Test public void shouldMakePipelineInstanceCanRunFalseWhenFirstStageIsRunning() throws Exception { pipelineOne.createPipelineWithFirstStageScheduled(); configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels pipelineInstanceModels = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 1, "anyone"); assertThat(pipelineInstanceModels.get(0).getCanRun(), is(false)); } @Test public void shouldNotLoadDuplicatPlaceholderStages() throws Exception { goConfigService.addPipeline(PipelineConfigMother.createPipelineConfig("pipeline", "stage", "job"), "pipeline-group"); PipelineInstanceModels history = pipelineHistoryService.load("pipeline", Pagination.pageStartingAt(0, 1, 10), "anyone", true); PipelineInstanceModel instanceModel = history.first(); assertThat(instanceModel instanceof EmptyPipelineInstanceModel, is(true)); StageInstanceModels stageHistory = instanceModel.getStageHistory(); assertThat(stageHistory.size(), is(1)); assertThat(stageHistory.first() instanceof NullStageHistoryItem, is(true)); } @Test public void shouldLoadACertainNumberOfPipelines() throws Exception { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels history = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); assertThat(history.get(0).getName(), is(pipeline.getName())); assertThat(history.get(0).getLabel(), is(pipeline.getLabel())); } @Test public void shouldOnlyLoadPipelinesThatTheUserHasAcessTo() throws Exception { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels history = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); assertThat(history.get(0).getName(), is(pipeline.getName())); assertThat(history.get(0).getLabel(), is(pipeline.getLabel())); } @Test public void shouldHidePipelinesThatIDoNotHaveAccessTo() throws Exception { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "NOONE"); PipelineInstanceModels history = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); assertThat(history.size(), is(0)); } @Test public void shoulShowPipelinesThatIHaveAccessTo() throws Exception { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels history = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); assertThat(history.size(), is(1)); } @Test public void shouldContainLatestRevisionForEachPipeline() throws Exception { Pipeline pipeline = pipelineOne.createPipelineWithFirstStageScheduled(); MaterialRevision materialRevision = new MaterialRevision(pipeline.getMaterialRevisions().getMaterialRevision(0).getMaterial(), new Modification(new Date(), "2", "MOCK_LABEL-12", null)); saveRev(materialRevision); configHelper.setViewPermissionForGroup("group1", "username"); PipelineInstanceModels latest = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.ONE_ITEM, "username"); MaterialRevisions latestRevision = latest.get(0).getLatestRevisions(); assertThat(latestRevision.getMaterialRevision(0).getRevision(), is(new SubversionRevision("2"))); } private void saveRev(final MaterialRevision materialRevision) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { materialRepository.saveMaterialRevision(materialRevision); } }); } @Test public void shouldReturnLatestPipelineIntance() throws Exception { Pipeline pipeline = pipelineOne.createPipelineWithFirstStageScheduled(); saveRev(new MaterialRevision(pipeline.getMaterialRevisions().getMaterialRevision(0).getMaterial(), new Modification(new Date(), "2", "MOCK_LABEL-12", null))); configHelper.setViewPermissionForGroup("group1", "username"); PipelineInstanceModel latest = pipelineHistoryService.latest(pipeline.getName(), new Username(new CaseInsensitiveString("username"))); assertThat(latest.getLatestRevisions().getMaterialRevision(0).getRevision(), is(new SubversionRevision("2"))); } @Test public void shouldContainNoRevisionsForNewMaterialsThatHAveNotBeenUpdated() throws Exception { pipelineOne.createPipelineWithFirstStageScheduled(); SvnMaterialConfig svnMaterialConfig = new SvnMaterialConfig("new-material", null, null, false); svnMaterialConfig.setConfigAttributes(Collections.singletonMap(ScmMaterialConfig.FOLDER, "new-material")); configHelper.addMaterialToPipeline(pipelineOne.pipelineName, svnMaterialConfig); configHelper.setViewPermissionForGroup("group1", "username"); PipelineInstanceModels latest = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.ONE_ITEM, "username"); MaterialRevisions latestRevision = latest.get(0).getLatestRevisions(); assertThat(latestRevision.getRevisions().size(), is(1)); } @Test public void shouldCreateEmptyPipelineIfThePipelineHasNeverBeenRun() throws Exception { SvnMaterialConfig svnMaterial = new SvnMaterialConfig("https://some-url", "new-user", "new-pass", false); configHelper.addPipeline("new-pipeline", "new-stage", svnMaterial, "first-job"); PipelineInstanceModels instanceModels = pipelineHistoryService.loadWithEmptyAsDefault("new-pipeline", Pagination.ONE_ITEM, "username"); PipelineInstanceModel instanceModel = instanceModels.get(0); assertThat(instanceModel.getMaterials(), is(new MaterialConfigs(svnMaterial))); assertThat(instanceModel.getCurrentRevision(svnMaterial).getRevision(), is("No historical data")); assertThat(instanceModel.getLatestRevision(svnMaterial).getRevision(), is("No historical data")); assertThat(instanceModel.getStageHistory().size(), is(1)); assertThat(instanceModel.getStageHistory().get(0).getName(), is("new-stage")); } @Test public void shouldReturnEmptyPipelineInstanceModel() throws Exception { configHelper.setViewPermissionForGroup(pipelineOne.groupName, "jez"); PipelineInstanceModels models = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "jez"); assertThat(models.size(), is(1)); PipelineInstanceModel emptyModel = models.get(0); assertThat(emptyModel.getName(), is(pipelineOne.pipelineName)); assertThat(emptyModel.getLabel(), is("unknown")); assertThat(emptyModel.getBuildCauseMessage(), is("No modifications")); assertThat(emptyModel.getStageHistory().size(), is(3)); assertThat(emptyModel.getStageHistory().get(0).getState(), is(StageState.Unknown)); assertThat(emptyModel.getCreatedTimeForDisplay(), is(TimeConverter.ConvertedTime.NO_HISTORICAL_DATA)); assertThat(emptyModel.getCanRun(), is(true)); } @Test public void shouldUnderstandIfEmptyPipelineHasNewModifications() throws Exception { saveRev(new MaterialRevision(pipelineOne.getMaterial(), new Modification(new Date(), "2", "MOCK_LABEL-12", null))); configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels models = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); PipelineInstanceModel emptyModel = models.get(0); assertThat(emptyModel.hasNewRevisions(), is(true)); } @Test public void shouldUnderstandIfEmptyPipelineHasNoNewModifications() throws Exception { configHelper.setViewPermissionForGroup("group1", "anyone"); PipelineInstanceModels models = pipelineHistoryService.findPipelineInstances(pipelineOne.pipelineName, "latest", 3, "anyone"); PipelineInstanceModel emptyModel = models.get(0); assertThat(emptyModel.hasNewRevisions(), is(false)); } @Test public void shouldUnderstandIfMaterialHasNewModifications() throws Exception { Pipeline pipeline = pipelineOne.createPipelineWithFirstStageScheduled(); Material material = pipeline.getMaterialRevisions().getMaterialRevision(0).getMaterial(); saveRev(new MaterialRevision(material, new Modification(new Date(), "2", "MOCK_LABEL-12", null))); configHelper.setViewPermissionForGroup("group1", "username"); PipelineInstanceModels latest = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.ONE_ITEM, "username"); PipelineInstanceModel model = latest.get(0); assertThat(model.hasNewRevisions(material.config()), is(true)); } @Test public void shouldUnderstandIfMaterialHasNoNewModifications() throws Exception { Pipeline pipeline = pipelineOne.createPipelineWithFirstStageScheduled(); Material material = pipeline.getMaterialRevisions().getMaterialRevision(0).getMaterial(); configHelper.setViewPermissionForGroup("group1", "username"); PipelineInstanceModels latest = pipelineHistoryService.loadWithEmptyAsDefault(pipelineOne.pipelineName, Pagination.ONE_ITEM, "username"); PipelineInstanceModel model = latest.get(0); assertThat(model.hasNewRevisions(material.config()), is(false)); } @Test public void shouldReturnNullForLatestWhenPipelineNotViewable() throws Exception { configHelper.addPipelineWithGroup("admin_only", "admin_pipeline", "stage", "deploy"); configHelper.addRole(new RoleConfig(new CaseInsensitiveString("deployers"), new RoleUser(new CaseInsensitiveString("root")))); configHelper.blockPipelineGroupExceptFor("admin_only", "deployers"); assertThat(pipelineHistoryService.latest("admin_pipeline", new Username(new CaseInsensitiveString("root"))), is(not(nullValue()))); assertThat(pipelineHistoryService.latest("admin_pipeline", new Username(new CaseInsensitiveString("someone_else"))), is(nullValue())); } @Test public void shouldLoadPipelineInstanceModelGivenAnId() { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "foo"); PipelineInstanceModel pipelineInstance = pipelineHistoryService.load(pipeline.getId(), new Username(new CaseInsensitiveString("foo")), new HttpOperationResult()); assertThat(pipelineInstance, is(not(nullValue()))); assertThat(pipelineInstance.getMaterials().size(), is(greaterThan(0))); assertThat(pipelineInstance.getLatestRevisions().numberOfRevisions(), is(greaterThan(0))); assertThat(pipelineInstance.getBuildCause().getMaterialRevisions().numberOfRevisions(), is(greaterThan(0))); } @Test public void shouldLoadPipelineInstanceWithMultipleRevisions() { Pipeline pipeline = pipelineOne.createPipelineWithFirstStageScheduled(ModificationsMother.multipleModifications(pipelineOne.pipelineConfig())); configHelper.setViewPermissionForGroup("group1", "foo"); PipelineInstanceModel pipelineInstance = pipelineHistoryService.load(pipeline.getId(), new Username(new CaseInsensitiveString("foo")), new HttpOperationResult()); assertThat(pipelineInstance, is(not(nullValue()))); assertThat(pipelineInstance.hasNewRevisions(), is(false)); } @Test public void shouldPopulateResultAsNotFoundWhenPipelineNotFound() { HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModel pipelineInstance = pipelineHistoryService.load(-1, new Username(new CaseInsensitiveString("foo")), result); assertThat(pipelineInstance, is(nullValue())); assertThat(result.httpCode(), is(404)); } @Test public void shouldPopulateResultAsUnauthorizedWhenUserNotAllowedToViewPipeline() { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); String groupName = configHelper.currentConfig().getGroups().findGroupNameByPipeline(new CaseInsensitiveString(pipeline.getName())); configHelper.setViewPermissionForGroup(groupName, "admin"); HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModel pipelineInstance = pipelineHistoryService.load(pipeline.getId(), new Username(new CaseInsensitiveString("foo")), result); assertThat(pipelineInstance, is(nullValue())); assertThat(result.httpCode(), is(401)); result = new HttpOperationResult(); pipelineInstance = pipelineHistoryService.load(pipeline.getId(), new Username(new CaseInsensitiveString("admin")), result); assertThat(pipelineInstance, is(not(nullValue()))); } @Test public void shouldLoadPipelineHistoryWithPlaceholderStagesPopulated_loadMinimalData() throws Exception { pipelineOne.createPipelineWithFirstStagePassedAndSecondStageHasNotStarted(); HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModels pipelineInstanceModels = pipelineHistoryService.loadMinimalData(pipelineOne.pipelineName, Pagination.pageStartingAt(0, 1, 10), new Username(new CaseInsensitiveString("admin1")), result); StageInstanceModels stageHistory = pipelineInstanceModels.first().getStageHistory(); assertThat("Should populate 2 placeholder stages from config", stageHistory.size(), is(3)); assertThat(stageHistory.first().isScheduled(), is(true)); assertThat(stageHistory.first().isAutoApproved(), is(true)); assertThat(stageHistory.first().getCanRun(), is(true)); assertThat(stageHistory.get(1).isScheduled(), is(false)); assertThat(stageHistory.get(1).isAutoApproved(), is(false)); assertThat("The first future stage should can run", stageHistory.get(1).getCanRun(), is(true)); assertThat(stageHistory.get(2).isScheduled(), is(false)); assertThat(stageHistory.get(2).isAutoApproved(), is(true)); assertThat("The second future stage should can not run", stageHistory.get(2).getCanRun(), is(false)); } @Test public void shouldLoadLatestOrEmptyInstanceForAllConfiguredPipelines() { configHelper.removePipeline(pipelineTwo.pipelineName); Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "foo"); PipelineInstanceModels pipelines = pipelineHistoryService.latestInstancesForConfiguredPipelines(new Username(new CaseInsensitiveString("foo"))); assertThat(pipelines.size(), is(1)); assertThat(pipelines.first().getId(), is(pipeline.getId())); } @Test public void shouldNotLoadLatestOrEmptyInstanceForAllConfiguredPipelinesWhenNotViewable() { configHelper.removePipeline(pipelineTwo.pipelineName); Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); String groupName = configHelper.currentConfig().getGroups().findGroupNameByPipeline(new CaseInsensitiveString(pipeline.getName())); configHelper.setViewPermissionForGroup(groupName, "admin"); PipelineInstanceModels pipelines = pipelineHistoryService.latestInstancesForConfiguredPipelines(new Username(new CaseInsensitiveString("foo"))); assertThat(pipelines.size(), is(0)); pipelines = pipelineHistoryService.latestInstancesForConfiguredPipelines(new Username(new CaseInsensitiveString("admin"))); assertThat(pipelines.size(), is(1)); assertThat(pipelines.first().getId(), is(pipeline.getId())); } @Test public void shouldFindAllPipelineInstancesForGivenPipelineName() { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); configHelper.setViewPermissionForGroup("group1", "foo"); PipelineInstanceModels pipelineInstances = pipelineHistoryService.findAllPipelineInstances(pipeline.getName(), new Username(new CaseInsensitiveString("foo")), new HttpOperationResult()); assertThat(pipelineInstances.size(), is(1)); assertThat(pipelineInstances.first().getName(), is(pipeline.getName())); } @Test public void shouldNotFindPipelineInstancesForGivenPipelineNameWhenNonViewableForUser() { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); String groupName = configHelper.currentConfig().getGroups().findGroupNameByPipeline(new CaseInsensitiveString(pipeline.getName())); configHelper.setViewPermissionForGroup(groupName, "admin"); HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModels pipelineInstances = pipelineHistoryService.findAllPipelineInstances(pipeline.getName(), new Username(new CaseInsensitiveString("foo")), result); assertThat(pipelineInstances, is(nullValue())); assertThat(result.httpCode(), is(401)); assertThat(result.message(), is("Not authorized to view pipeline")); pipelineInstances = pipelineHistoryService.findAllPipelineInstances(pipeline.getName(), new Username(new CaseInsensitiveString("admin")), new HttpOperationResult()); assertThat(pipelineInstances.size(), is(1)); assertThat(pipelineInstances.first().getName(), is(pipeline.getName())); } @Test public void shouldSet404InOperationResultWhenPipelineUnknown() { HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModels pipelineInstances = pipelineHistoryService.findAllPipelineInstances("pipeline_that_does_not_exist", new Username(new CaseInsensitiveString("foo")), result); assertThat(result.httpCode(), is(404)); assertThat(result.message(), is("Pipeline named [pipeline_that_does_not_exist] is not known.")); assertThat(pipelineInstances, is(nullValue())); } @Test public void shouldHaveAPipelineInstanceForAPipelineThatIsPreparingToSchedule() { configHelper.addPipeline("pipeline-name", "stage-1"); triggerMonitor.markPipelineAsAlreadyTriggered("pipeline-name"); PipelineInstanceModel instance = pipelineHistoryService.latest("pipeline-name", new Username(new CaseInsensitiveString("admin"))); assertThat(instance.getName(), is("pipeline-name")); assertThat(instance.getStageHistory().size(), is(1)); assertThat(instance.getStageHistory().get(0).isScheduled(), is(false)); assertThat(instance.isPreparingToSchedule(), is(true)); } @Test public void shouldLoadPipelineInstanceForGivenNameAndCounter() { PipelineConfig mingleConfig = PipelineConfigMother.createPipelineConfig("mingle", "stage", "job"); goConfigService.addPipeline(mingleConfig, "pipeline-group"); Pipeline instance1 = dbHelper.schedulePipeline(mingleConfig, new TimeProvider()); dbHelper.cancelStage(instance1.getStages().get(0)); Pipeline instance2 = dbHelper.schedulePipeline(mingleConfig, new TimeProvider()); dbHelper.passStage(instance2.getStages().get(0)); HttpOperationResult operationResult = new HttpOperationResult(); assertPipeline(pipelineHistoryService.findPipelineInstance("mingle", 1, new Username(new CaseInsensitiveString("doesnotmatter")), operationResult), instance1, operationResult); assertPipeline(pipelineHistoryService.findPipelineInstance("mingle", 2, new Username(new CaseInsensitiveString("doesnotmatter")), operationResult), instance2, operationResult); } @Test public void shouldNotThrowUpWhenPipelineCounterIs0AndShouldReturnAnEmptyPIM() { PipelineConfig mingleConfig = PipelineConfigMother.createPipelineConfig("mingle", "stage", "job"); goConfigService.addPipeline(mingleConfig, "pipeline-group"); PipelineInstanceModel pim = pipelineHistoryService.findPipelineInstance("mingle", 0, new Username(new CaseInsensitiveString("doesnotmatter")), new HttpOperationResult()); assertThat(pim, instanceOf(EmptyPipelineInstanceModel.class)); } @Test public void findPipelineInstanceShouldNotFindPipelineInstancesNotViewableByUser() { Pipeline pipeline = pipelineOne.createdPipelineWithAllStagesPassed(); String groupName = configHelper.currentConfig().getGroups().findGroupNameByPipeline(new CaseInsensitiveString(pipeline.getName())); configHelper.setViewPermissionForGroup(groupName, "admin"); HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModel pipelineInstance = pipelineHistoryService.findPipelineInstance(pipeline.getName(), pipeline.getCounter(), new Username(new CaseInsensitiveString("foo")), result); assertThat(pipelineInstance, is(nullValue())); assertThat(result.httpCode(), is(401)); assertThat(result.message(), is("Not authorized to view pipeline")); pipelineInstance = pipelineHistoryService.findPipelineInstance(pipeline.getName(), pipeline.getCounter(), new Username(new CaseInsensitiveString("admin")), new HttpOperationResult()); assertThat(pipelineInstance, is(not(nullValue()))); } @Test public void findPipelineInstanceShouldPopulateResultAsNotFoundWhenPipelineNotFound() { HttpOperationResult result = new HttpOperationResult(); PipelineInstanceModel pipelineInstance = pipelineHistoryService.findPipelineInstance("blahName", 1, new Username(new CaseInsensitiveString("foo")), result); assertThat(pipelineInstance, is(nullValue())); assertThat(result.httpCode(), is(404)); } @Test public void shouldReturnListOfPipelineInstancesByPageNumber() { final int limit = 1; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("mingle", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); Pipeline instance1 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.cancelStage(instance1.getStages().get(0)); Pipeline instance2 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance2.getStages().get(0)); Pipeline instance3 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance3.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findPipelineInstancesByPageNumber(instance2.getName(), 2, limit, "admin"); assertThat(actual.size(), is(1)); assertThat(actual.get(0).getCounter(), is(2)); assertThat(actual.getPagination(), is(Pagination.pageStartingAt(1, 3, limit))); } @Test public void findMatchingPipelineInstances_shouldMatchLabels() { final int limit = 10; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-blah-1"); Pipeline instance1 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.cancelStage(instance1.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-2"); Pipeline instance2 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance2.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-1-1"); Pipeline instance3 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance3.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blaH-1-2"); Pipeline instance4 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance4.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "h-1", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(3)); assertThat(actual.get(0).getCounter(), is(4)); assertThat(actual.get(1).getCounter(), is(3)); assertThat(actual.get(2).getCounter(), is(1)); } @Test public void findMatchingPipelineInstances_shouldEscapeUnderscoreAndPercentageSymbols() { final int limit = 10; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-blah-1"); Pipeline instance1 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.cancelStage(instance1.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-2"); Pipeline instance2 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance2.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-1-1"); Pipeline instance3 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance3.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blaH-1-2"); Pipeline instance4 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance4.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "h-1", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(3)); actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "h%-%1_5", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(0)); } @Test public void findMatchingPipelineInstances_shouldTrimThePatternBeforeSearch() { final int limit = 10; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-blah-1"); Pipeline instance1 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.cancelStage(instance1.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-2"); Pipeline instance2 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance2.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blah-1-1"); Pipeline instance3 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance3.getStages().get(0)); pipelineConfig.setLabelTemplate("${COUNT}-blaH-1-2"); Pipeline instance4 = dbHelper.schedulePipeline(pipelineConfig, new TimeProvider()); dbHelper.passStage(instance4.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", " h-1 ", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(3)); assertThat(actual.get(0).getCounter(), is(4)); assertThat(actual.get(1).getCounter(), is(3)); assertThat(actual.get(2).getCounter(), is(1)); } @Test public void findMatchingPipelineInstances_shouldPopulatePipelineFieldsIncludingPlaceholderStages() { configHelper.setViewPermissionForGroup("group1", "jez"); Pipeline pipeline = pipelineOne.createPipelineWithFirstStagePassedAndSecondStageHasNotStarted(); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances(pipeline.getName(), pipeline.getBuildCause().getMaterialRevisions().getMaterialRevision(0).getLatestComment(), 2, new Username(new CaseInsensitiveString( "jez")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(1)); PipelineInstanceModel actualPipeline = actual.get(0); assertThat(actualPipeline.getCounter(), is(1)); assertThat(actualPipeline.getStageHistory().size(), is(3)); assertThat(actualPipeline.getStageHistory().get(1).getState(), is(StageState.Unknown)); assertThat(actualPipeline.getStageHistory().get(2).getState(), is(StageState.Unknown)); } @Test public void findMatchingPipelineInstances_shouldMatchModificationsFields() { final int limit = 3; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-blah-1"); Pipeline shouldMatch1 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "abc1234", "hello world -THIS SHOULD MATCH", "dev"), new TimeProvider()); dbHelper.cancelStage(shouldMatch1.getStages().get(0)); Pipeline shouldMatch2 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "abc12345", "some MONKEY", "THIS SHOULD ALSO MATCH - YELLOW"), new TimeProvider()); dbHelper.cancelStage(shouldMatch2.getStages().get(0)); Pipeline shouldMatch3 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "revision-HELLO-there-SHOULD_MATCH", "some monkey", "foo"), new TimeProvider()); dbHelper.cancelStage(shouldMatch3.getStages().get(0)); Pipeline shouldNotMatch = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "revision-there-2", "some monkey", "foo"), new TimeProvider()); dbHelper.cancelStage(shouldNotMatch.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "ello", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat("size", actual.size(), is(3)); assertThat("first counter", actual.get(0).getCounter(), is(3)); assertThat("second counter", actual.get(1).getCounter(), is(2)); assertThat("third counter", actual.get(2).getCounter(), is(1)); } @Test public void findMatchingPipelineInstances_shouldShowExactMatchesOnLabelBeforePartialMatches() { final int limit = 3; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-ABC"); Pipeline shouldMatch1 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "revision", "comment", "committer"), new TimeProvider()); dbHelper.cancelStage(shouldMatch1.getStages().get(0)); Pipeline shouldMatch2 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, String.format("revision-%s-abc-should-match", shouldMatch1.getCounter()), "another comment", "committer"), new TimeProvider()); dbHelper.cancelStage(shouldMatch2.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", String.format("%s-ABC", shouldMatch1.getCounter()), limit, new Username(new CaseInsensitiveString( "user")), new HttpLocalizedOperationResult()); assertThat("size", actual.size(), is(2)); assertThat("first counter", actual.get(0).getCounter(), is(shouldMatch1.getCounter())); assertThat("second counter", actual.get(1).getCounter(), is(shouldMatch2.getCounter())); } @Test public void findMatchingPipelineInstances_shouldShowExpectedNumberOfMatchesWhenThePipelineHasMultipleStagesAndJobs() { final int limit = 2; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfigWithStages("pipeline_name"); pipelineConfig.add(StageConfigMother.custom("stage-1", "job-1", "job-2", "job-3", "job-4")); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}"); Pipeline shouldMatch1 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "abc-revision-should-match", "comment", "committer"), new TimeProvider()); dbHelper.cancelStage(shouldMatch1.getStages().get(0)); Pipeline shouldMatch2 = dbHelper.schedulePipeline(pipelineConfig, ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "this-abc-revision-should-match-too", "another comment", "committer"), new TimeProvider()); dbHelper.cancelStage(shouldMatch2.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "abc", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat("size", actual.size(), is(2)); assertThat("first counter", actual.get(0).getCounter(), is(shouldMatch2.getCounter())); assertThat("second counter", actual.get(1).getCounter(), is(shouldMatch1.getCounter())); } @Test public void findMatchingPipelineInstances_shouldMatchBuildCauseMessage() { final int limit = 3; PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); pipelineConfig.setLabelTemplate("${COUNT}-ABC"); BuildCause buildCause = ModificationsMother.buildCauseForOneModifiedFile(pipelineConfig, "revision", "comment", "committer"); buildCause.setMessage("Triggered by USER some million years ago.. when dinosaurs ruled the world"); Pipeline shouldMatch1 = dbHelper.schedulePipeline(pipelineConfig, buildCause, new TimeProvider()); dbHelper.cancelStage(shouldMatch1.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "user", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat("size", actual.size(), is(1)); assertThat("first counter", actual.get(0).getCounter(), is(shouldMatch1.getCounter())); } @Test public void findMatchingPipelineInstances_shouldMatchUpStreamPipelineLabel() { final int limit = 3; PipelineConfig upstreamConfig = PipelineConfigMother.createPipelineConfig("upstream", "stage", "job"); upstreamConfig.setLabelTemplate("${COUNT}-hello-world-${COUNT}"); PipelineConfig downstreamConfig = PipelineConfigMother.createPipelineConfig("downstream", "stage", "job"); downstreamConfig.materialConfigs().clear(); DependencyMaterial dependencyMaterial = new DependencyMaterial(new CaseInsensitiveString("upstream"), new CaseInsensitiveString("stage")); downstreamConfig.addMaterialConfig(dependencyMaterial.config()); goConfigService.addPipeline(upstreamConfig, "pipeline-group"); goConfigService.addPipeline(downstreamConfig, "pipeline-group"); Pipeline upstreamPipeline = dbHelper.schedulePipeline(upstreamConfig, new TimeProvider()); dbHelper.passStage(upstreamPipeline.getStages().get(0)); Modification modification = new Modification(new Date(), DependencyMaterialRevision.create("upstream", 1, "1", "stage", 1).getRevision(), "1", upstreamPipeline.getId()); MaterialRevisions materialRevisions = new MaterialRevisions(new MaterialRevision(dependencyMaterial, modification)); Pipeline downstreamPipeline = dbHelper.schedulePipeline(downstreamConfig, BuildCause.createWithModifications(materialRevisions, "cruise"), new TimeProvider()); dbHelper.passStage(downstreamPipeline.getStages().get(0)); PipelineInstanceModels actual = pipelineHistoryService.findMatchingPipelineInstances("downstream", "hello-world", limit, new Username(new CaseInsensitiveString("user")), new HttpLocalizedOperationResult()); assertThat(actual.size(), is(1)); assertThat(actual.get(0).getCounter(), is(downstreamPipeline.getCounter())); } @Test public void findMatchingPipelineInstances_shouldReturnUnauthorizedWhenUserDoesNotHavePermission() { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); configHelper.addAuthorizedUserForPipelineGroup("valid-user"); HttpLocalizedOperationResult result = new HttpLocalizedOperationResult(); PipelineInstanceModels pipelineInstances = pipelineHistoryService.findMatchingPipelineInstances("pipeline_name", "ABCD", 1000, new Username(new CaseInsensitiveString("fraud-user")), result); assertThat(pipelineInstances.size(), is(0)); assertThat(result.isSuccessful(), is(false)); assertThat(result.httpCode(), is(401)); } @Test public void updateComment_shouldUpdateTheCommentInTheDatabase() throws Exception { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); configHelper.addAuthorizedUserForPipelineGroup("valid-user"); configHelper.setAdminPermissionForGroup("pipeline-group", "valid-user"); dbHelper.newPipelineWithAllStagesPassed(pipelineConfig); HttpLocalizedOperationResult result = new HttpLocalizedOperationResult(); pipelineHistoryService.updateComment("pipeline_name", 1, "test comment", new Username(new CaseInsensitiveString("valid-user")), result); PipelineInstanceModel pim = dbHelper.getPipelineDao().findPipelineHistoryByNameAndCounter("pipeline_name", 1); assertThat(pim.getComment(), is("test comment")); } @Test public void updateComment_shouldNotUpdateTheCommentInTheDatabaseIfTheUserIsUnauthorized() throws Exception { PipelineConfig pipelineConfig = PipelineConfigMother.createPipelineConfig("pipeline_name", "stage", "job"); goConfigService.addPipeline(pipelineConfig, "pipeline-group"); configHelper.addAuthorizedUserForPipelineGroup("valid-user"); dbHelper.newPipelineWithAllStagesPassed(pipelineConfig); HttpLocalizedOperationResult result = new HttpLocalizedOperationResult(); pipelineHistoryService.updateComment("pipeline_name", 1, "test comment", new Username(new CaseInsensitiveString("invalid-user")), result); PipelineInstanceModel pim = dbHelper.getPipelineDao().findPipelineHistoryByNameAndCounter("pipeline_name", 1); assertThat(pim.getComment(), is(nullValue())); assertThat(result.httpCode(), is(401)); assertThat(result.message(localizer), is("You do not have operate permissions for pipeline 'pipeline_name'.")); } private void assertPipeline(PipelineInstanceModel pipelineInstance, Pipeline instance, HttpOperationResult operationResult) { assertThat(operationResult.toString(), operationResult.canContinue(), is(true)); assertThat(pipelineInstance.getCounter(), is(instance.getCounter())); assertThat(pipelineInstance.getName(), is(instance.getName())); } }