@Test public void shouldScheduleIfAgentMatchingResources() throws Exception { JobConfig plan = evolveConfig .findBy(new CaseInsensitiveString(STAGE_NAME)) .jobConfigByInstanceName("unit", true); plan.addResource("some-resource"); scheduleHelper.schedule(evolveConfig, modifySomeFiles(evolveConfig), DEFAULT_APPROVED_BY); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-resource")); buildAssignmentService.onTimer(); Work work = buildAssignmentService.assignWorkToAgent(agent(agentConfig)); assertThat(work, is(not((Work) BuildAssignmentService.NO_WORK))); Pipeline pipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(evolveConfig.name())); JobInstance job = pipeline.findStage(STAGE_NAME).findJob("unit"); JobPlan loadedPlan = jobInstanceDao.loadPlan(job.getId()); assertThat(loadedPlan.getResources(), is((List<Resource>) plan.resources())); assertThat(job.getState(), is(JobState.Assigned)); assertThat(job.getAgentUuid(), is(agentConfig.getUuid())); }
public Stage saveBuildingStage(String pipelineName, String stageName) throws SQLException { Pipeline pipeline = saveTestPipeline(pipelineName, stageName); Stage stage = saveBuildingStage(pipeline.getStages().byName(stageName)); for (JobInstance job : stage.getJobInstances()) { job.setIdentifier(new JobIdentifier(pipeline, stage, job)); } return stage; }
public Stage saveBuildingStage(Stage stage) { for (JobInstance jobInstance : stage.getJobInstances()) { JobInstanceMother.setBuildingState(jobInstance); jobInstance.setAgentUuid(AGENT_UUID); jobInstanceDao.updateAssignedInfo(jobInstance); } return stage; }
public void buildingBuildInstance(Stage stage) { if (!stage.getJobInstances().isEmpty()) { JobInstance jobInstance = stage.getJobInstances().get(0); jobInstance.setAgentUuid(AGENT_UUID); jobInstance.changeState(JobState.Building); jobInstanceDao.updateAssignedInfo(jobInstance); } }
public void cancelStage(Stage stage) { for (JobInstance job : stage.getJobInstances()) { job.cancel(); jobInstanceDao.updateStateAndResult(job); } stage.calculateResult(); updateResultInTransaction(stage, StageResult.Cancelled); }
private void verifyMingleScheduledWithModifications() { Pipeline scheduledPipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(mingleConfig.name())); BuildCause buildCause = scheduledPipeline.getBuildCause(); assertThat(buildCause.getMaterialRevisions().totalNumberOfModifications(), is(3)); JobInstance instance = scheduledPipeline.getFirstStage().getJobInstances().first(); assertThat(instance.getState(), is(JobState.Scheduled)); }
public void failStage(Stage stage, Date completionDate) { for (JobInstance job : stage.getJobInstances()) { job.completing(Failed, completionDate); job.completed(completionDate); jobInstanceDao.updateStateAndResult(job); } stage.calculateResult(); updateResultInTransaction(stage, StageResult.Failed); }
private void logIfJobIsCompleted(JobInstance jobInstance) { JobState currentState = getCurrentState(jobInstance.getId()); if (currentState.isCompleted()) { String message = String.format( "State change for a completed Job is not allowed. Job %s is currently State=%s, Result=%s", jobInstance.getIdentifier(), jobInstance.getState(), jobInstance.getResult()); LOG.warn(message, new Exception().fillInStackTrace()); } }
private JobInstance job(long buildId, String queryName) { JobInstance instance = (JobInstance) getSqlMapClientTemplate().queryForObject(queryName, buildId); if (instance == null) { throw new DataRetrievalFailureException("Could not load build with id " + buildId); } if (instance.getIdentifier() == null) { throw new RuntimeException("Identifier must not be null!"); } return instance; }
public JobInstance save(long stageId, JobInstance jobInstance) { jobInstance.setStageId(stageId); getSqlMapClientTemplate().insert("insertBuild", jobInstance); updateStateAndResult(jobInstance); JobPlan plan = jobInstance.getPlan(); if (plan != null) { save(jobInstance.getId(), plan); } return jobInstance; }
private void saveTransitions(JobInstance jobInstance) { for (JobStateTransition transition : jobInstance.getTransitions()) { if (!transition.hasId()) { saveTransition(jobInstance, transition); } } if (jobInstance.getIdentifier() != null) { String pipelineName = jobInstance.getIdentifier().getPipelineName(); String stageName = jobInstance.getIdentifier().getStageName(); cache.flushEntry(jobInstance.getBuildDurationKey(pipelineName, stageName)); } }
private void assertPipelinesScheduled() { Pipeline minglePipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(mingleConfig.name())); Stage mingleStage = minglePipeline.getFirstStage(); assertThat(mingleStage.getName(), is(STAGE_NAME)); assertThat(mingleStage.getJobInstances().size(), is(2)); JobInstance mingleJob = mingleStage.getJobInstances().first(); assertThat(mingleJob.getState(), is(JobState.Scheduled)); assertPipelineScheduled(evolveConfig); assertPipelineScheduled(goConfig); }
@Test public void shouldCancelOutOfDateBuilds() throws Exception { fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removeStage(fixture.pipelineName, fixture.devStage); buildAssignmentService.onConfigChange(goConfigService.getCurrentConfig()); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); }
private Pipeline scheduleJobInstancesAndSavePipeline(Pipeline pipeline) { assertNotInserted(pipeline.getId()); for (Stage stage : pipeline.getStages()) { for (JobInstance jobInstance : stage.getJobInstances()) { jobInstance.schedule(); } } this.savePipelineWithStagesAndMaterials(pipeline); long pipelineId = pipeline.getId(); assertIsInserted(pipelineId); return pipeline; }
@Before public void setUp() { MaterialRevisions materialRevisions = multipleModifications(); stage = StageMother.withOneScheduledBuild("stage", "job-that-will-fail", "job-that-will-pass", 1); modifications = BuildCause.createWithModifications(materialRevisions, ""); pipeline = new Pipeline("pipeline", PipelineLabel.COUNT_TEMPLATE, modifications, stage); stage.setIdentifier(new StageIdentifier(pipeline, stage)); for (JobInstance job : stage.getJobInstances()) { job.setIdentifier(new JobIdentifier(pipeline, stage, job)); } pipeline.setId(PIPELINE_ID); pipeline.updateCounter(9); }
@Test public void shouldCancelBuildBelongingToNonExistentPipelineWhenCreatingWork() throws Exception { fixture.createPipelineWithFirstStageScheduled(); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); ScheduledPipelineLoader scheduledPipelineLoader = mock(ScheduledPipelineLoader.class); when(scheduledPipelineLoader.pipelineWithPasswordAwareBuildCauseByBuildId( pipeline.getFirstStage().getJobInstances().first().getId())) .thenThrow(new PipelineNotFoundException("thrown by mockPipelineService")); GoConfigService mockGoConfigService = mock(GoConfigService.class); CruiseConfig config = configHelper.currentConfig(); configHelper.removePipeline(fixture.pipelineName, config); when(mockGoConfigService.getCurrentConfig()).thenReturn(config); buildAssignmentService = new BuildAssignmentService( mockGoConfigService, jobInstanceService, scheduleService, agentService, environmentConfigService, timeProvider, transactionTemplate, scheduledPipelineLoader, pipelineService, builderFactory, agentRemoteHandler); buildAssignmentService.onTimer(); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-other-resource")); try { buildAssignmentService.assignWorkToAgent(agent(agentConfig)); fail("should have thrown PipelineNotFoundException"); } catch (PipelineNotFoundException e) { // ok } pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); Stage stage = stageDao.findStageWithIdentifier(job.getIdentifier().getStageIdentifier()); assertThat(stage.getState(), is(StageState.Cancelled)); assertThat(stage.getResult(), is(StageResult.Cancelled)); }
@Test public void buildByIdWithTransitions_shouldCacheWhenQueriedFor() { jobInstanceDao.setSqlMapClientTemplate(mockTemplate); JobInstance job = JobInstanceMother.assigned("job"); job.setId(1L); when(mockTemplate.queryForObject("buildByIdWithTransitions", 1L)).thenReturn(job); JobInstance actual = jobInstanceDao.buildByIdWithTransitions(1L); assertThat(actual, is(job)); assertThat(actual == job, is(false)); jobInstanceDao.buildByIdWithTransitions(1L); verify(mockTemplate, times(1)).queryForObject("buildByIdWithTransitions", 1L); }
@Test public void shouldSaveBuildStateCorrectly() throws Exception { PipelineConfig cruisePlan = configHelper.addPipeline("cruise", "dev", repository); goConfigService.forceNotifyListeners(); autoSchedulePipelines("mingle", "evolve", "cruise"); Stage cruise = stageDao.mostRecentWithBuilds( CaseInsensitiveString.str(cruisePlan.name()), cruisePlan.findBy(new CaseInsensitiveString("dev"))); System.out.println("cruise = " + cruise); JobInstance instance = cruise.getJobInstances().first(); System.out.println("instance = " + instance); assertThat(instance.getState(), is(JobState.Scheduled)); }
@Test public void shouldEncodeBuildLocator() throws Exception { JobInstance job = JobInstanceMother.assigned("job-%"); Stage stage1 = new Stage( "stage-c%d", new JobInstances(job), GoConstants.DEFAULT_APPROVED_BY, "manual", new TimeProvider()); stage1.setIdentifier(new StageIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1")); job.setIdentifier( new JobIdentifier("pipeline-a%b", 1, "label-1", "stage-c%d", "1", "job-%", 0L)); StageJsonPresentationModel presenter = new StageJsonPresentationModel(pipeline, stage1, null, new Agents()); Map json = presenter.toJson(); assertThat( JsonUtils.from(json).getString("builds", 0, "buildLocator"), is("pipeline-a%25b/1/stage-c%25d/1/job-%25")); }
@Test public void buildByIdWithTransitions_shouldClearFromCacheOnUpdateStatusOfJob() { jobInstanceDao.setSqlMapClientTemplate(mockTemplate); JobInstance job = JobInstanceMother.assigned("job"); job.setId(1L); when(mockTemplate.queryForObject("buildByIdWithTransitions", 1L)).thenReturn(job); JobInstance actual = jobInstanceDao.buildByIdWithTransitions(1L); assertThat(actual, is(job)); assertThat(actual == job, is(false)); jobInstanceDao.updateStateAndResult(job); // Must clear cahced job instance jobInstanceDao.buildByIdWithTransitions(1L); verify(mockTemplate, times(2)).queryForObject("buildByIdWithTransitions", 1L); }
@Test public void shouldNotAssignCancelledJob() throws Exception { AgentIdentifier instance = agent(AgentMother.localAgent()); Pipeline pipeline = instanceFactory.createPipelineInstance( evolveConfig, modifyNoFiles(evolveConfig), new DefaultSchedulingContext(DEFAULT_APPROVED_BY), md5, new TimeProvider()); dbHelper.savePipelineWithStagesAndMaterials(pipeline); buildAssignmentService.onConfigChange(goConfigService.getCurrentConfig()); JobInstance job = buildOf(pipeline); job.cancel(); jobInstanceDao.updateStateAndResult(job); assertThat( buildAssignmentService.assignWorkToAgent(instance), is((Work) BuildAssignmentService.NO_WORK)); }
@Test public void shouldNotScheduleIfAgentDoesNotHaveResources() throws Exception { JobConfig plan = evolveConfig .findBy(new CaseInsensitiveString(STAGE_NAME)) .jobConfigByInstanceName("unit", true); plan.addResource("some-resource"); scheduleHelper.schedule(evolveConfig, modifySomeFiles(evolveConfig), DEFAULT_APPROVED_BY); Work work = buildAssignmentService.assignWorkToAgent(agent(AgentMother.localAgent())); Pipeline pipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(evolveConfig.name())); JobInstance job = pipeline.findStage(STAGE_NAME).findJob("unit"); assertThat(work, is((Work) BuildAssignmentService.NO_WORK)); assertThat(job.getState(), is(JobState.Scheduled)); assertThat(job.getAgentUuid(), is(nullValue())); }
@Test public void shouldCancelBuildBelongingToNonExistentPipeline() throws Exception { fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removePipeline(fixture.pipelineName); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-other-resource")); assertThat( (NoWork) buildAssignmentService.assignWorkToAgent(agent(agentConfig)), Matchers.is(BuildAssignmentService.NO_WORK)); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance job = pipeline.getFirstStage().getJobInstances().first(); assertThat(job.getState(), is(JobState.Completed)); assertThat(job.getResult(), is(JobResult.Cancelled)); Stage stage = stageDao.findStageWithIdentifier(job.getIdentifier().getStageIdentifier()); assertThat(stage.getState(), is(StageState.Cancelled)); assertThat(stage.getResult(), is(StageResult.Cancelled)); }
@Test public void shouldCancelBuildsForDeletedJobsWhenPipelineConfigChanges() throws Exception { fixture = new PipelineWithTwoStages(materialRepository, transactionTemplate).usingTwoJobs(); fixture.usingConfigHelper(configHelper).usingDbHelper(dbHelper).onSetUp(); fixture.createPipelineWithFirstStageScheduled(); buildAssignmentService.onTimer(); configHelper.removeJob(fixture.pipelineName, fixture.devStage, fixture.JOB_FOR_DEV_STAGE); buildAssignmentService.onPipelineConfigChange( goConfigService .getCurrentConfig() .getPipelineConfigByName(new CaseInsensitiveString(fixture.pipelineName)), "g1"); Pipeline pipeline = pipelineDao.mostRecentPipeline(fixture.pipelineName); JobInstance deletedJob = pipeline.getFirstStage().getJobInstances().getByName(fixture.JOB_FOR_DEV_STAGE); assertThat(deletedJob.getState(), is(JobState.Completed)); assertThat(deletedJob.getResult(), is(JobResult.Cancelled)); JobInstance retainedJob = pipeline.getFirstStage().getJobInstances().getByName(fixture.DEV_STAGE_SECOND_JOB); assertThat(retainedJob.getState(), is(JobState.Scheduled)); assertThat(retainedJob.getResult(), is(JobResult.Unknown)); }
public StageResult completeAllJobs(Stage stage, JobResult jobResult) { for (JobInstance job : stage.getJobInstances()) { JobInstanceMother.setBuildingState(job); job.setAgentUuid(AGENT_UUID); job.completing(jobResult); job.completed(new DateTime().plusMinutes(5).toDate()); jobInstanceDao.updateAssignedInfo(job); } StageResult stageResult; switch (jobResult) { case Failed: stageResult = StageResult.Failed; break; case Cancelled: stageResult = StageResult.Cancelled; break; default: stageResult = StageResult.Passed; } stage.calculateResult(); return stageResult; }
@Test public void shouldRescheduleAbandonedBuild() throws SQLException { AgentIdentifier instance = agent(AgentMother.localAgent()); Pipeline pipeline = instanceFactory.createPipelineInstance( evolveConfig, modifyNoFiles(evolveConfig), new DefaultSchedulingContext(DEFAULT_APPROVED_BY), md5, new TimeProvider()); dbHelper.savePipelineWithStagesAndMaterials(pipeline); buildAssignmentService.onConfigChange(goConfigService.getCurrentConfig()); buildAssignmentService.onTimer(); buildAssignmentService.assignWorkToAgent(instance); long firstAssignedBuildId = buildOf(pipeline).getId(); // somehow agent abandoned its original build... buildAssignmentService.assignWorkToAgent(instance); JobInstance reloaded = jobInstanceDao.buildByIdWithTransitions(firstAssignedBuildId); assertThat(reloaded.getState(), is(JobState.Rescheduled)); assertThat(reloaded.isIgnored(), is(true)); }
public void onefailAndOnePassedBuildInstances(Stage instance) { final JobInstance first = instance.getJobInstances().get(0); final JobInstance second = instance.getJobInstances().get(1); first.completing(Failed); second.completing(Failed); first.completed(new Date()); second.completed(new Date()); jobInstanceDao.updateStateAndResult(first); jobInstanceDao.updateStateAndResult(second); }
public void buildInstanceWithDiscontinuedState(Stage instance) { final JobInstance first = instance.getJobInstances().get(0); final JobInstance second = instance.getJobInstances().get(1); first.completing(JobResult.Passed); second.changeState(JobState.Discontinued); second.setResult(JobResult.Passed); first.completed(new Date()); jobInstanceDao.updateStateAndResult(first); jobInstanceDao.updateStateAndResult(second); updateResultInTransaction(instance, StageResult.Passed); }
@Test public void shouldReScheduleToCorrectAgent() throws Exception { JobConfig plan = evolveConfig .findBy(new CaseInsensitiveString(STAGE_NAME)) .jobConfigByInstanceName("unit", true); plan.addResource("some-resource"); scheduleHelper.schedule(evolveConfig, modifySomeFiles(evolveConfig), DEFAULT_APPROVED_BY); buildAssignmentService.onTimer(); AgentConfig agentConfig = AgentMother.localAgent(); agentConfig.addResource(new Resource("some-resource")); Work work = buildAssignmentService.assignWorkToAgent(agent(agentConfig)); assertThat(work, is(not((Work) BuildAssignmentService.NO_WORK))); Pipeline pipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(evolveConfig.name())); JobInstance job = pipeline.findStage(STAGE_NAME).findJob("unit"); JobInstance runningJob = jobInstanceDao.buildByIdWithTransitions(job.getId()); scheduleService.rescheduleJob(runningJob); pipeline = pipelineDao.mostRecentPipeline(CaseInsensitiveString.str(evolveConfig.name())); JobInstance rescheduledJob = pipeline.findStage(STAGE_NAME).findJob("unit"); assertThat(rescheduledJob.getId(), not(runningJob.getId())); buildAssignmentService.onTimer(); Work noResourcesWork = buildAssignmentService.assignWorkToAgent( agent(AgentMother.localAgentWithResources("WITHOUT_RESOURCES"))); assertThat(noResourcesWork, is((Work) BuildAssignmentService.NO_WORK)); buildAssignmentService.onTimer(); Work correctAgentWork = buildAssignmentService.assignWorkToAgent(agent(agentConfig)); assertThat(correctAgentWork, is(not((Work) BuildAssignmentService.NO_WORK))); }
public void assignToAgent(JobInstance jobInstance, String agentId) { jobInstance.setAgentUuid(agentId); jobInstance.changeState(JobState.Assigned); jobInstanceDao.updateAssignedInfo(jobInstance); }