MSBuild로 똑똑하게 빌드하기 - 실패하다

프로젝트 규모가 커질수록 빌드 시간도 길어진다. 빌드 시간이 길어지면 피드백도 늦어진다. 퇴근 시간 다 돼서 소스 코드를 커밋해놓고 빌드가 끝나길 기다린다. Rebuild하느라 5분을 기다렸는데, 빨간불이 들어온다. 새로운 소스 코드 파일을 추가(Add)하지 않은 게 문제였다. 부랴부랴 문제의 소스 코드를 올려놓고 다시 빌드 서버의 반응을 기다린다. 다시 5분을 기다렸는데 이번에도 빨간불이 들어온다. 문제의 소스 코드를 고치고 또 한번 커밋을 한다. 다행히 이번엔 반가운 녹색 불빛이 들어온다.

퇴근 시간이 15분이나 늦어졌으니 웬지 짜증이 밀려온다.

빌드 시간은 짧을수록 좋다. 프로젝트 구성을 잘 해서 컴파일 및 링크 시간을 줄이는 게 최선이지만, 빌드 서버의 관점에서도 개선할 여지는 있다. 매번 Rebuild를 하는 대신 Build를 하면 어떨까? 하지만 이렇게 하면 하루에 한번 정도는 소스 코드가 멀쩡한데도 빨간불이 들어오는 일이 벌어진다. 가장 좋은 방법은 Build를 해보고 실패했을 때만 Rebuild를 하는 것이다. 몇 가지 요구 사항을 정리해보면 이렇다.

  1. Build가 성공하면 끝낸다.

  2. Build가 실패하면 Rebuild를 한다.

  3. Rebuild가 성공하면 오류 처리를 하지 않는다. 즉, 빨간불 대신 녹색불이 들어와야 한다.

  4. Rebuild가 실패하면 오류 처리를 한다. 이때 Build 때 난 오류와 Rebuild 때 난 오류는 내용이 동일할 테니, Rebuild 때 발생한 오류만 로그로 남긴다.

이걸 제대로 구현하느라 애먹었는데, 1번과 2번 요구사항까지는 쉽다. 아래와 같이 MSBuild Task를 작성하면 된다.

<Target Name="BuildForCI">
	<Error Text="Build가 실패했습니다. Rebuild를 시도합니다." ContinueOnError="true" />
	<MSBuild
	   Projects = "@(ProjectReferences)"
	   Properties = "Configuration=Debug"
	   Targets = "Build"
	   StopOnFirstFailure = "true"
	   ContinueOnError="false">
	</MSBuild>
	<OnError ExecuteTargets="Rebuild" />
</Target>

하지만 이래선 요구사항 3번과 4번은 충족되지 않는다. 이를 해결하려고 Microsoft.Build.Tasks.MSBuild를 상속 받은 새로운 Task 클래스 SKimediaMSBuild까지 구현해봤지만 결국 실패했다.

문서를 보면 ContinueOnErrortrue로 선언하면 실패(Error)가 경고(Warning)로 처리되고 빌드 수행을 계속한다고 나와 있다. 틀린 말은 아니지만 이는 빌드 엔진이 그렇게 처리한다는 뜻이지, 로거도 그렇게 동작한다는 뜻은 아니다. 적어도 CruiseControl .NET에서 쓰는 MSBuild 로거는 실패가 경고로 처리된 사실을 모르기 때문에 여전히 실패로 기록한다. 하여 새로운 Task를 구현하는 것만으론 문제가 해결되지 않는다.

해결책은 다음 편에….

Advertisements

최 재훈

블로그, 페이스북, 트위터 고성능 서버 엔진, 데이터베이스, 지속적인 통합 등 다양한 주제에 관심이 많다.
Close Menu