프로젝트 규모가 커질수록 빌드 시간도 길어진다. 빌드 시간이 길어지면 피드백도 늦어진다. 퇴근 시간 다 돼서 소스 코드를 커밋해놓고 빌드가 끝나길 기다린다. Rebuild하느라 5분을 기다렸는데, 빨간불이 들어온다. 새로운 소스 코드 파일을 추가(Add)하지 않은 게 문제였다. 부랴부랴 문제의 소스 코드를 올려놓고 다시 빌드 서버의 반응을 기다린다. 다시 5분을 기다렸는데 이번에도 빨간불이 들어온다. 문제의 소스 코드를 고치고 또 한번 커밋을 한다. 다행히 이번엔 반가운 녹색 불빛이 들어온다.
퇴근 시간이 15분이나 늦어졌으니 웬지 짜증이 밀려온다.
빌드 시간은 짧을수록 좋다. 프로젝트 구성을 잘 해서 컴파일 및 링크 시간을 줄이는 게 최선이지만, 빌드 서버의 관점에서도 개선할 여지는 있다. 매번 Rebuild를 하는 대신 Build를 하면 어떨까? 하지만 이렇게 하면 하루에 한번 정도는 소스 코드가 멀쩡한데도 빨간불이 들어오는 일이 벌어진다. 가장 좋은 방법은 Build를 해보고 실패했을 때만 Rebuild를 하는 것이다. 몇 가지 요구 사항을 정리해보면 이렇다.
-
Build가 성공하면 끝낸다.
-
Build가 실패하면 Rebuild를 한다.
-
Rebuild가 성공하면 오류 처리를 하지 않는다. 즉, 빨간불 대신 녹색불이 들어와야 한다.
-
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
까지 구현해봤지만 결국 실패했다.
문서를 보면 ContinueOnError
를 true
로 선언하면 실패(Error)가 경고(Warning)로 처리되고 빌드 수행을 계속한다고 나와 있다. 틀린 말은 아니지만 이는 빌드 엔진이 그렇게 처리한다는 뜻이지, 로거도 그렇게 동작한다는 뜻은 아니다. 적어도 CruiseControl .NET에서 쓰는 MSBuild 로거는 실패가 경고로 처리된 사실을 모르기 때문에 여전히 실패로 기록한다. 하여 새로운 Task를 구현하는 것만으론 문제가 해결되지 않는다.
해결책은 다음 편에….
음, 빌드를 실패했다고 해서(컴파일이나 링크 에러나 기타 리소스 카피나.. 등) 리빌드를 하실 필요가 있으신가요? 그냥 빌드 실패했다고 메일이나 메신저, 문자 등의 알림으로 충분할거 같은데;;;
일일빌드 실패했으면 실패한 원인 제공자 추적해서 그 날 점심 식사 쏘게 해야죠. ㅋㅋ (농담)
빌드 서버가 거의 분단위로 폴링하다가 소스 코드가 변경되면 빌드를 합니다. 리빌드로만 하자니 빌드 시간이 오래 걸리고, 빌드만 하자니 실제 소스 코드는 멀쩡한데 오류가 나는 경우가 있으니 절충하려는 겁니다.
흐음.. 빌드는 실패하고 리빌드는 성공한다고 하면 뭔가 소스의 디펜던시에 문제가 있는건 아닐까요? ^^
공유 라이브러리에 변경된 코드가 있으면 빌드가 실패하기도 합니다. 서버 구성요소를 각각 맡아서 진행하고 있기 때문에 자신이 필요해서 추가한 코드 때문에 다른 사람이 짠 코드가 망가질 수 있죠. 그렇다고 다른 쪽 컴포넌트까지 매번 확인하고 책 임지라고 하면 피곤하죠….