1 | package org.apache.maven.continuum.buildcontroller; |
2 | |
3 | /* |
4 | * Licensed to the Apache Software Foundation (ASF) under one |
5 | * or more contributor license agreements. See the NOTICE file |
6 | * distributed with this work for additional information |
7 | * regarding copyright ownership. The ASF licenses this file |
8 | * to you under the Apache License, Version 2.0 (the |
9 | * "License"); you may not use this file except in compliance |
10 | * with the License. You may obtain a copy of the License at |
11 | * |
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
13 | * |
14 | * Unless required by applicable law or agreed to in writing, |
15 | * software distributed under the License is distributed on an |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
17 | * KIND, either express or implied. See the License for the |
18 | * specific language governing permissions and limitations |
19 | * under the License. |
20 | */ |
21 | |
22 | import java.util.ArrayList; |
23 | import java.util.Iterator; |
24 | import java.util.List; |
25 | import java.util.Map; |
26 | |
27 | import org.apache.continuum.dao.BuildDefinitionDao; |
28 | import org.apache.continuum.dao.BuildResultDao; |
29 | import org.apache.continuum.dao.ProjectDao; |
30 | import org.apache.continuum.dao.ProjectScmRootDao; |
31 | import org.apache.continuum.model.project.ProjectScmRoot; |
32 | import org.apache.continuum.utils.ContinuumUtils; |
33 | import org.apache.maven.continuum.core.action.AbstractContinuumAction; |
34 | import org.apache.maven.continuum.core.action.ExecuteBuilderContinuumAction; |
35 | import org.apache.maven.continuum.execution.ContinuumBuildExecutor; |
36 | import org.apache.maven.continuum.execution.ContinuumBuildExecutorConstants; |
37 | import org.apache.maven.continuum.execution.manager.BuildExecutorManager; |
38 | import org.apache.maven.continuum.model.project.BuildDefinition; |
39 | import org.apache.maven.continuum.model.project.BuildResult; |
40 | import org.apache.maven.continuum.model.project.Project; |
41 | import org.apache.maven.continuum.model.project.ProjectDependency; |
42 | import org.apache.maven.continuum.model.scm.ChangeFile; |
43 | import org.apache.maven.continuum.model.scm.ChangeSet; |
44 | import org.apache.maven.continuum.model.scm.ScmResult; |
45 | import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher; |
46 | import org.apache.maven.continuum.project.ContinuumProjectState; |
47 | import org.apache.maven.continuum.store.ContinuumObjectNotFoundException; |
48 | import org.apache.maven.continuum.store.ContinuumStoreException; |
49 | import org.apache.maven.continuum.utils.WorkingDirectoryService; |
50 | import org.apache.maven.scm.ScmException; |
51 | import org.apache.maven.scm.repository.ScmRepositoryException; |
52 | import org.codehaus.plexus.action.ActionManager; |
53 | import org.codehaus.plexus.action.ActionNotFoundException; |
54 | import org.codehaus.plexus.taskqueue.execution.TaskExecutionException; |
55 | import org.slf4j.Logger; |
56 | import org.slf4j.LoggerFactory; |
57 | |
58 | /** |
59 | * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> |
60 | * @version $Id: DefaultBuildController.java 793475 2009-07-13 07:37:50Z ctan $ |
61 | * @plexus.component role="org.apache.maven.continuum.buildcontroller.BuildController" role-hint="default" |
62 | */ |
63 | public class DefaultBuildController |
64 | implements BuildController |
65 | { |
66 | private static final Logger log = LoggerFactory.getLogger( DefaultBuildController.class ); |
67 | |
68 | /** |
69 | * @plexus.requirement |
70 | */ |
71 | private BuildDefinitionDao buildDefinitionDao; |
72 | |
73 | /** |
74 | * @plexus.requirement |
75 | */ |
76 | private BuildResultDao buildResultDao; |
77 | |
78 | /** |
79 | * @plexus.requirement |
80 | */ |
81 | private ProjectDao projectDao; |
82 | |
83 | /** |
84 | * @plexus.requirement |
85 | */ |
86 | private ProjectScmRootDao projectScmRootDao; |
87 | |
88 | /** |
89 | * @plexus.requirement |
90 | */ |
91 | private ContinuumNotificationDispatcher notifierDispatcher; |
92 | |
93 | /** |
94 | * @plexus.requirement |
95 | */ |
96 | private ActionManager actionManager; |
97 | |
98 | /** |
99 | * @plexus.requirement |
100 | */ |
101 | private WorkingDirectoryService workingDirectoryService; |
102 | |
103 | /** |
104 | * @plexus.requirement |
105 | */ |
106 | private BuildExecutorManager buildExecutorManager; |
107 | |
108 | // ---------------------------------------------------------------------- |
109 | // BuildController Implementation |
110 | // ---------------------------------------------------------------------- |
111 | |
112 | /** |
113 | * @param projectId |
114 | * @param buildDefinitionId |
115 | * @param trigger |
116 | * @throws TaskExecutionException |
117 | */ |
118 | public void build( int projectId, int buildDefinitionId, int trigger, ScmResult scmResult ) |
119 | throws TaskExecutionException |
120 | { |
121 | log.info( "Initializing build" ); |
122 | BuildContext context = initializeBuildContext( projectId, buildDefinitionId, trigger, scmResult ); |
123 | |
124 | // ignore this if AlwaysBuild ? |
125 | if ( !checkScmResult( context ) ) |
126 | { |
127 | log.info( "Error updating from SCM, not building" ); |
128 | return; |
129 | } |
130 | |
131 | log.info( "Starting build of " + context.getProject().getName() ); |
132 | startBuild( context ); |
133 | |
134 | try |
135 | { |
136 | checkProjectDependencies( context ); |
137 | |
138 | if ( !shouldBuild( context ) ) |
139 | { |
140 | return; |
141 | } |
142 | |
143 | Map<String, Object> actionContext = context.getActionContext(); |
144 | |
145 | try |
146 | { |
147 | performAction( "update-project-from-working-directory", context ); |
148 | } |
149 | catch ( TaskExecutionException e ) |
150 | { |
151 | updateBuildResult( context, ContinuumUtils.throwableToString( e ) ); |
152 | |
153 | //just log the error but don't stop the build from progressing in order not to suppress any build result messages there |
154 | log.error( "Error executing action update-project-from-working-directory '", e ); |
155 | } |
156 | |
157 | performAction( "execute-builder", context ); |
158 | |
159 | performAction( "deploy-artifact", context ); |
160 | |
161 | context.setCancelled( ExecuteBuilderContinuumAction.isCancelled( actionContext ) ); |
162 | |
163 | String s = AbstractContinuumAction.getBuildId( actionContext, null ); |
164 | |
165 | if ( s != null && !context.isCancelled() ) |
166 | { |
167 | try |
168 | { |
169 | context.setBuildResult( buildResultDao.getBuildResult( Integer.valueOf( s ) ) ); |
170 | } |
171 | catch ( NumberFormatException e ) |
172 | { |
173 | throw new TaskExecutionException( "Internal error: build id not an integer", e ); |
174 | } |
175 | catch ( ContinuumObjectNotFoundException e ) |
176 | { |
177 | throw new TaskExecutionException( "Internal error: Cannot find build result", e ); |
178 | } |
179 | catch ( ContinuumStoreException e ) |
180 | { |
181 | throw new TaskExecutionException( "Error loading build result", e ); |
182 | } |
183 | } |
184 | } |
185 | finally |
186 | { |
187 | endBuild( context ); |
188 | } |
189 | } |
190 | |
191 | /** |
192 | * Checks if the build should be marked as ERROR and notifies the end of the build. |
193 | * |
194 | * @param context |
195 | * @throws TaskExecutionException |
196 | */ |
197 | private void endBuild( BuildContext context ) |
198 | throws TaskExecutionException |
199 | { |
200 | Project project = context.getProject(); |
201 | |
202 | try |
203 | { |
204 | if ( project.getState() != ContinuumProjectState.NEW && |
205 | project.getState() != ContinuumProjectState.CHECKEDOUT && |
206 | project.getState() != ContinuumProjectState.OK && project.getState() != ContinuumProjectState.FAILED && |
207 | project.getState() != ContinuumProjectState.ERROR && !context.isCancelled() ) |
208 | { |
209 | try |
210 | { |
211 | String s = AbstractContinuumAction.getBuildId( context.getActionContext(), null ); |
212 | |
213 | if ( s != null ) |
214 | { |
215 | BuildResult buildResult = buildResultDao.getBuildResult( Integer.valueOf( s ) ); |
216 | project.setState( buildResult.getState() ); |
217 | projectDao.updateProject( project ); |
218 | } |
219 | } |
220 | catch ( ContinuumStoreException e ) |
221 | { |
222 | throw new TaskExecutionException( "Error storing the project", e ); |
223 | } |
224 | } |
225 | } |
226 | finally |
227 | { |
228 | if ( !context.isCancelled() ) |
229 | { |
230 | notifierDispatcher.buildComplete( project, context.getBuildDefinition(), context.getBuildResult() ); |
231 | } |
232 | } |
233 | } |
234 | |
235 | private void updateBuildResult( BuildContext context, String error ) |
236 | throws TaskExecutionException |
237 | { |
238 | BuildResult build = context.getBuildResult(); |
239 | |
240 | if ( build == null ) |
241 | { |
242 | build = makeAndStoreBuildResult( context, error ); |
243 | } |
244 | else |
245 | { |
246 | updateBuildResult( build, context ); |
247 | |
248 | build.setError( error ); |
249 | |
250 | try |
251 | { |
252 | buildResultDao.updateBuildResult( build ); |
253 | |
254 | build = buildResultDao.getBuildResult( build.getId() ); |
255 | |
256 | context.setBuildResult( build ); |
257 | } |
258 | catch ( ContinuumStoreException e ) |
259 | { |
260 | throw new TaskExecutionException( "Error updating build result", e ); |
261 | } |
262 | } |
263 | |
264 | context.getProject().setState( build.getState() ); |
265 | |
266 | try |
267 | { |
268 | projectDao.updateProject( context.getProject() ); |
269 | } |
270 | catch ( ContinuumStoreException e ) |
271 | { |
272 | throw new TaskExecutionException( "Error updating project", e ); |
273 | } |
274 | } |
275 | |
276 | private void updateBuildResult( BuildResult build, BuildContext context ) |
277 | { |
278 | if ( build.getScmResult() == null && context.getScmResult() != null ) |
279 | { |
280 | build.setScmResult( context.getScmResult() ); |
281 | } |
282 | |
283 | if ( build.getModifiedDependencies() == null && context.getModifiedDependencies() != null ) |
284 | { |
285 | build.setModifiedDependencies( context.getModifiedDependencies() ); |
286 | } |
287 | } |
288 | |
289 | private void startBuild( BuildContext context ) |
290 | throws TaskExecutionException |
291 | { |
292 | |
293 | Project project = context.getProject(); |
294 | |
295 | project.setOldState( project.getState() ); |
296 | |
297 | project.setState( ContinuumProjectState.BUILDING ); |
298 | |
299 | try |
300 | { |
301 | projectDao.updateProject( project ); |
302 | } |
303 | catch ( ContinuumStoreException e ) |
304 | { |
305 | throw new TaskExecutionException( "Error persisting project", e ); |
306 | } |
307 | |
308 | notifierDispatcher.buildStarted( project, context.getBuildDefinition() ); |
309 | |
310 | } |
311 | |
312 | /** |
313 | * Initializes a BuildContext for the build. |
314 | * |
315 | * @param projectId |
316 | * @param buildDefinitionId |
317 | * @param trigger |
318 | * @return |
319 | * @throws TaskExecutionException |
320 | */ |
321 | protected BuildContext initializeBuildContext( int projectId, int buildDefinitionId, int trigger, |
322 | ScmResult scmResult ) |
323 | throws TaskExecutionException |
324 | { |
325 | BuildContext context = new BuildContext(); |
326 | |
327 | context.setStartTime( System.currentTimeMillis() ); |
328 | |
329 | context.setTrigger( trigger ); |
330 | |
331 | try |
332 | { |
333 | Project project = projectDao.getProject( projectId ); |
334 | |
335 | context.setProject( project ); |
336 | |
337 | BuildDefinition buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinitionId ); |
338 | |
339 | context.setBuildDefinition( buildDefinition ); |
340 | |
341 | BuildResult oldBuildResult = |
342 | buildResultDao.getLatestBuildResultForBuildDefinition( projectId, buildDefinitionId ); |
343 | |
344 | context.setOldBuildResult( oldBuildResult ); |
345 | |
346 | context.setScmResult( scmResult ); |
347 | |
348 | // CONTINUUM-1871 olamy if continuum is killed during building oldBuildResult will have a endTime 0 |
349 | // this means all changes since the project has been loaded in continuum will be in memory |
350 | // now we will load all BuildResult with an Id bigger or equals than the oldBuildResult one |
351 | //if ( oldBuildResult != null ) |
352 | //{ |
353 | // context.setOldScmResult( |
354 | // getOldScmResults( projectId, oldBuildResult.getBuildNumber(), oldBuildResult.getEndTime() ) ); |
355 | //} |
356 | } |
357 | catch ( ContinuumStoreException e ) |
358 | { |
359 | throw new TaskExecutionException( "Error initializing the build context", e ); |
360 | } |
361 | |
362 | Map<String, Object> actionContext = context.getActionContext(); |
363 | |
364 | AbstractContinuumAction.setProjectId( actionContext, projectId ); |
365 | |
366 | AbstractContinuumAction.setProject( actionContext, context.getProject() ); |
367 | |
368 | AbstractContinuumAction.setBuildDefinitionId( actionContext, buildDefinitionId ); |
369 | |
370 | AbstractContinuumAction.setBuildDefinition( actionContext, context.getBuildDefinition() ); |
371 | |
372 | AbstractContinuumAction.setTrigger( actionContext, trigger ); |
373 | |
374 | AbstractContinuumAction.setScmResult( actionContext, context.getScmResult() ); |
375 | |
376 | if ( context.getOldBuildResult() != null ) |
377 | { |
378 | AbstractContinuumAction.setOldBuildId( actionContext, context.getOldBuildResult().getId() ); |
379 | } |
380 | |
381 | return context; |
382 | } |
383 | |
384 | private void performAction( String actionName, BuildContext context ) |
385 | throws TaskExecutionException |
386 | { |
387 | String error; |
388 | TaskExecutionException exception; |
389 | |
390 | try |
391 | { |
392 | log.info( "Performing action " + actionName ); |
393 | actionManager.lookup( actionName ).execute( context.getActionContext() ); |
394 | return; |
395 | } |
396 | catch ( ActionNotFoundException e ) |
397 | { |
398 | error = ContinuumUtils.throwableToString( e ); |
399 | exception = new TaskExecutionException( "Error looking up action '" + actionName + "'", e ); |
400 | } |
401 | catch ( ScmRepositoryException e ) |
402 | { |
403 | error = getValidationMessages( e ) + "\n" + ContinuumUtils.throwableToString( e ); |
404 | |
405 | exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e ); |
406 | } |
407 | catch ( ScmException e ) |
408 | { |
409 | error = ContinuumUtils.throwableToString( e ); |
410 | |
411 | exception = new TaskExecutionException( "SCM error while executing '" + actionName + "'", e ); |
412 | } |
413 | catch ( Exception e ) |
414 | { |
415 | exception = new TaskExecutionException( "Error executing action '" + actionName + "'", e ); |
416 | error = ContinuumUtils.throwableToString( exception ); |
417 | } |
418 | |
419 | // TODO: clean this up. We catch the original exception from the action, and then update the buildresult |
420 | // for it - we need to because of the specialized error message for SCM. |
421 | // If updating the buildresult fails, log the previous error and throw the new one. |
422 | // If updating the buildresult succeeds, throw the original exception. The build result should NOT |
423 | // be updated again - a TaskExecutionException is final, no further action should be taken upon it. |
424 | |
425 | try |
426 | { |
427 | updateBuildResult( context, error ); |
428 | } |
429 | catch ( TaskExecutionException e ) |
430 | { |
431 | log.error( "Error updating build result after receiving the following exception: ", exception ); |
432 | throw e; |
433 | } |
434 | |
435 | throw exception; |
436 | } |
437 | |
438 | protected boolean shouldBuild( BuildContext context ) |
439 | throws TaskExecutionException |
440 | { |
441 | BuildDefinition buildDefinition = context.getBuildDefinition(); |
442 | if ( buildDefinition.isBuildFresh() ) |
443 | { |
444 | log.info( "FreshBuild configured, building" ); |
445 | return true; |
446 | } |
447 | if ( buildDefinition.isAlwaysBuild() ) |
448 | { |
449 | log.info( "AlwaysBuild configured, building" ); |
450 | return true; |
451 | } |
452 | if ( context.getOldBuildResult() == null ) |
453 | { |
454 | log.info( "The project was never be built with the current build definition, building" ); |
455 | return true; |
456 | } |
457 | |
458 | Project project = context.getProject(); |
459 | |
460 | //CONTINUUM-1428 |
461 | if ( project.getOldState() == ContinuumProjectState.ERROR || |
462 | context.getOldBuildResult().getState() == ContinuumProjectState.ERROR ) |
463 | { |
464 | log.info( "Latest state was 'ERROR', building" ); |
465 | return true; |
466 | } |
467 | |
468 | if ( context.getTrigger() == ContinuumProjectState.TRIGGER_FORCED ) |
469 | { |
470 | log.info( "The project build is forced, building" ); |
471 | return true; |
472 | } |
473 | |
474 | boolean shouldBuild = false; |
475 | |
476 | boolean allChangesUnknown = true; |
477 | |
478 | if ( project.getOldState() != ContinuumProjectState.NEW && |
479 | project.getOldState() != ContinuumProjectState.CHECKEDOUT && |
480 | context.getTrigger() != ContinuumProjectState.TRIGGER_FORCED && |
481 | project.getState() != ContinuumProjectState.NEW && project.getState() != ContinuumProjectState.CHECKEDOUT ) |
482 | { |
483 | // Check SCM changes |
484 | if ( context.getScmResult() != null ) |
485 | { |
486 | allChangesUnknown = checkAllChangesUnknown( context.getScmResult().getChanges() ); |
487 | } |
488 | |
489 | if ( allChangesUnknown ) |
490 | { |
491 | if ( context.getScmResult() != null && !context.getScmResult().getChanges().isEmpty() ) |
492 | { |
493 | log.info( |
494 | "The project was not built because all changes are unknown (maybe local modifications or ignored files not defined in your SCM tool." ); |
495 | } |
496 | else |
497 | { |
498 | log.info( |
499 | "The project was not built because no changes were detected in sources since the last build." ); |
500 | } |
501 | } |
502 | |
503 | // Check dependencies changes |
504 | if ( context.getModifiedDependencies() != null && !context.getModifiedDependencies().isEmpty() ) |
505 | { |
506 | log.info( "Found dependencies changes, building" ); |
507 | shouldBuild = true; |
508 | } |
509 | } |
510 | |
511 | // Check changes |
512 | if ( !shouldBuild && ( ( !allChangesUnknown && context.getScmResult() != null && !context.getScmResult().getChanges().isEmpty() ) || |
513 | project.getExecutorId().equals( ContinuumBuildExecutorConstants.MAVEN_TWO_BUILD_EXECUTOR ) ) ) |
514 | { |
515 | try |
516 | { |
517 | ContinuumBuildExecutor executor = buildExecutorManager.getBuildExecutor( project.getExecutorId() ); |
518 | |
519 | if ( executor == null ) |
520 | { |
521 | log.warn( "No continuum build executor found for project " + project.getId() + |
522 | " with executor '" + project.getExecutorId() + "'" ); |
523 | } |
524 | else if ( context.getScmResult() != null ) |
525 | { |
526 | shouldBuild = executor.shouldBuild( context.getScmResult().getChanges(), project, |
527 | workingDirectoryService.getWorkingDirectory( project ), |
528 | context.getBuildDefinition() ); |
529 | } |
530 | } |
531 | catch ( Exception e ) |
532 | { |
533 | updateBuildResult( context, ContinuumUtils.throwableToString( e ) ); |
534 | throw new TaskExecutionException( "Can't determine if the project should build or not", e ); |
535 | } |
536 | } |
537 | |
538 | if ( shouldBuild ) |
539 | { |
540 | log.info( "Changes found in the current project, building" ); |
541 | } |
542 | else |
543 | { |
544 | project.setState( project.getOldState() ); |
545 | |
546 | project.setOldState( 0 ); |
547 | |
548 | try |
549 | { |
550 | projectDao.updateProject( project ); |
551 | } |
552 | catch ( ContinuumStoreException e ) |
553 | { |
554 | throw new TaskExecutionException( "Error storing project", e ); |
555 | } |
556 | log.info( "No changes in the current project, not building" ); |
557 | |
558 | } |
559 | |
560 | return shouldBuild; |
561 | } |
562 | |
563 | private boolean checkAllChangesUnknown( List<ChangeSet> changes ) |
564 | { |
565 | for ( ChangeSet changeSet : changes ) |
566 | { |
567 | List<ChangeFile> changeFiles = changeSet.getFiles(); |
568 | |
569 | for ( ChangeFile changeFile : changeFiles ) |
570 | { |
571 | if ( !"unknown".equalsIgnoreCase( changeFile.getStatus() ) ) |
572 | { |
573 | return false; |
574 | } |
575 | } |
576 | } |
577 | |
578 | return true; |
579 | } |
580 | |
581 | private String getValidationMessages( ScmRepositoryException ex ) |
582 | { |
583 | List<String> messages = ex.getValidationMessages(); |
584 | |
585 | StringBuffer message = new StringBuffer(); |
586 | |
587 | if ( messages != null && !messages.isEmpty() ) |
588 | { |
589 | for ( Iterator<String> i = messages.iterator(); i.hasNext(); ) |
590 | { |
591 | message.append( i.next() ); |
592 | |
593 | if ( i.hasNext() ) |
594 | { |
595 | message.append( System.getProperty( "line.separator" ) ); |
596 | } |
597 | } |
598 | } |
599 | return message.toString(); |
600 | } |
601 | |
602 | protected void checkProjectDependencies( BuildContext context ) |
603 | { |
604 | if ( context.getOldBuildResult() == null ) |
605 | { |
606 | return; |
607 | } |
608 | |
609 | try |
610 | { |
611 | Project project = projectDao.getProjectWithDependencies( context.getProject().getId() ); |
612 | List<ProjectDependency> dependencies = project.getDependencies(); |
613 | |
614 | if ( dependencies == null ) |
615 | { |
616 | dependencies = new ArrayList<ProjectDependency>(); |
617 | } |
618 | |
619 | if ( project.getParent() != null ) |
620 | { |
621 | dependencies.add( project.getParent() ); |
622 | } |
623 | |
624 | if ( dependencies.isEmpty() ) |
625 | { |
626 | return; |
627 | } |
628 | |
629 | List<ProjectDependency> modifiedDependencies = new ArrayList<ProjectDependency>(); |
630 | |
631 | for ( ProjectDependency dep : dependencies ) |
632 | { |
633 | Project dependencyProject = |
634 | projectDao.getProject( dep.getGroupId(), dep.getArtifactId(), dep.getVersion() ); |
635 | |
636 | if ( dependencyProject != null ) |
637 | { |
638 | long nbBuild = buildResultDao.getNbBuildResultsInSuccessForProject( dependencyProject.getId(), |
639 | context.getOldBuildResult().getEndTime() ); |
640 | if ( nbBuild > 0 ) |
641 | { |
642 | log.debug( "Dependency changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + |
643 | dep.getVersion() ); |
644 | modifiedDependencies.add( dep ); |
645 | } |
646 | else |
647 | { |
648 | log.debug( "Dependency not changed: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + |
649 | dep.getVersion() ); |
650 | } |
651 | } |
652 | else |
653 | { |
654 | log.debug( "Skip non Continuum project: " + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + |
655 | dep.getVersion() ); |
656 | } |
657 | } |
658 | |
659 | context.setModifiedDependencies( modifiedDependencies ); |
660 | AbstractContinuumAction.setUpdatedDependencies( context.getActionContext(), modifiedDependencies ); |
661 | } |
662 | catch ( ContinuumStoreException e ) |
663 | { |
664 | log.warn( "Can't get the project dependencies", e ); |
665 | } |
666 | } |
667 | |
668 | // ---------------------------------------------------------------------- |
669 | // |
670 | // ---------------------------------------------------------------------- |
671 | |
672 | private BuildResult makeAndStoreBuildResult( BuildContext context, String error ) |
673 | throws TaskExecutionException |
674 | { |
675 | // Project project, ScmResult scmResult, long startTime, int trigger ) |
676 | // project, scmResult, startTime, trigger ); |
677 | |
678 | BuildResult build = new BuildResult(); |
679 | |
680 | build.setState( ContinuumProjectState.ERROR ); |
681 | |
682 | build.setTrigger( context.getTrigger() ); |
683 | |
684 | build.setStartTime( context.getStartTime() ); |
685 | |
686 | build.setEndTime( System.currentTimeMillis() ); |
687 | |
688 | updateBuildResult( build, context ); |
689 | |
690 | build.setScmResult( context.getScmResult() ); |
691 | |
692 | build.setBuildDefinition( context.getBuildDefinition() ); |
693 | |
694 | if ( error != null ) |
695 | { |
696 | build.setError( error ); |
697 | } |
698 | |
699 | try |
700 | { |
701 | buildResultDao.addBuildResult( context.getProject(), build ); |
702 | |
703 | build = buildResultDao.getBuildResult( build.getId() ); |
704 | |
705 | context.setBuildResult( build ); |
706 | |
707 | return build; |
708 | } |
709 | catch ( ContinuumStoreException e ) |
710 | { |
711 | throw new TaskExecutionException( "Error storing build result", e ); |
712 | } |
713 | } |
714 | |
715 | /** |
716 | * Check to see if there was a error while checking out/updating the project |
717 | * |
718 | * @param context The build context |
719 | * @return true if scm result is ok |
720 | * @throws TaskExecutionException |
721 | */ |
722 | private boolean checkScmResult( BuildContext context ) |
723 | throws TaskExecutionException |
724 | { |
725 | Project project = context.getProject(); |
726 | |
727 | int projectGroupId = project.getProjectGroup().getId(); |
728 | |
729 | List<ProjectScmRoot> scmRoots = projectScmRootDao.getProjectScmRootByProjectGroup( projectGroupId ); |
730 | |
731 | for ( ProjectScmRoot projectScmRoot : scmRoots ) |
732 | { |
733 | if ( project.getScmUrl().startsWith( projectScmRoot.getScmRootAddress() ) ) |
734 | { |
735 | if ( projectScmRoot.getState() == ContinuumProjectState.UPDATED ) |
736 | { |
737 | return true; |
738 | } |
739 | |
740 | break; |
741 | } |
742 | } |
743 | |
744 | return false; |
745 | } |
746 | } |