@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)); }
@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())); }
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)); }
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 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)); }
@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 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 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 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)); }
@Test public void shouldSetAServerHealthMessageWhenMaterialForPipelineWithBuildCauseIsNotFound() throws IllegalArtifactLocationException, IOException { PipelineConfig pipelineConfig = PipelineConfigMother.pipelineConfig( "last", new StageConfig( new CaseInsensitiveString("stage"), new JobConfigs(new JobConfig("job-one")))); pipelineConfig.materialConfigs().clear(); SvnMaterialConfig onDirOne = MaterialConfigsMother.svnMaterialConfig( "google.com", "dirOne", "loser", "boozer", false, "**/*.html"); final P4MaterialConfig onDirTwo = MaterialConfigsMother.p4MaterialConfig( "host:987654321", "zoozer", "secret", "through-the-window", true); onDirTwo.setConfigAttributes(Collections.singletonMap(ScmMaterialConfig.FOLDER, "dirTwo")); pipelineConfig.addMaterialConfig(onDirOne); pipelineConfig.addMaterialConfig(onDirTwo); configHelper.addPipeline(pipelineConfig); Pipeline building = PipelineMother.building(pipelineConfig); final Pipeline pipeline = dbHelper.savePipelineWithMaterials(building); CruiseConfig cruiseConfig = configHelper.currentConfig(); PipelineConfig cfg = cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("last")); cfg.removeMaterialConfig(cfg.materialConfigs().get(1)); configHelper.writeConfigFile(cruiseConfig); assertThat( serverHealthService.filterByScope(HealthStateScope.forPipeline("last")).size(), is(0)); final long jobId = pipeline.getStages().get(0).getJobInstances().get(0).getId(); Date currentTime = new Date(System.currentTimeMillis() - 1); Pipeline loadedPipeline = (Pipeline) transactionTemplate.execute( new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { Pipeline loadedPipeline = null; try { loadedPipeline = loader.pipelineWithPasswordAwareBuildCauseByBuildId(jobId); fail( "should not have loaded pipeline with build-cause as one of the necessary materials was not found"); } catch (Exception e) { assertThat(e, is(instanceOf(StaleMaterialsOnBuildCause.class))); assertThat( e.getMessage(), is( "Cannot load job 'last/" + pipeline.getCounter() + "/stage/1/job-one' because material " + onDirTwo + " was not found in config.")); } return loadedPipeline; } }); assertThat(loadedPipeline, is(nullValue())); JobInstance reloadedJobInstance = jobInstanceService.buildById(jobId); assertThat(reloadedJobInstance.getState(), is(JobState.Completed)); assertThat(reloadedJobInstance.getResult(), is(JobResult.Failed)); assertThat( serverHealthService .filterByScope(HealthStateScope.forJob("last", "stage", "job-one")) .size(), is(1)); ServerHealthState error = serverHealthService .filterByScope(HealthStateScope.forJob("last", "stage", "job-one")) .get(0); assertThat( error, is( ServerHealthState.error( "Cannot load job 'last/" + pipeline.getCounter() + "/stage/1/job-one' because material " + onDirTwo + " was not found in config.", "Job for pipeline 'last/" + pipeline.getCounter() + "/stage/1/job-one' has been failed as one or more material configurations were either changed or removed.", HealthStateType.general(HealthStateScope.forJob("last", "stage", "job-one"))))); DateTime expiryTime = (DateTime) ReflectionUtil.getField(error, "expiryTime"); assertThat(expiryTime.toDate().after(currentTime), is(true)); assertThat( expiryTime.toDate().before(new Date(System.currentTimeMillis() + 5 * 60 * 1000 + 1)), is(true)); String logText = FileUtil.readToEnd(consoleService.findConsoleArtifact(reloadedJobInstance.getIdentifier())); assertThat( logText, containsString( "Cannot load job 'last/" + pipeline.getCounter() + "/stage/1/job-one' because material " + onDirTwo + " was not found in config.")); assertThat( logText, containsString( "Job for pipeline 'last/" + pipeline.getCounter() + "/stage/1/job-one' has been failed as one or more material configurations were either changed or removed.")); }