TeamCity에서 Azure WebJobs Deploy하기

Azure WebJobs는 Azure WebSites(이하 WebSites)를 이용한 백그라운드 워커입니다. WebSites의 설정에 종속적으로 구동되며 이로 인해 뚜렷한 장단점을 가집니다.

장점

  • 배포가 매우 빠르고 쉬움.
  • 다양한 언어(.net, .py, .sh 등)를 지원.

단점

  • 완벽히 신뢰하기엔 모호한 동작.
  • WebSites와의 자원 공유로 성능 저하.

추천하는 사용법은, 초기엔 가볍고 정확함이 크게 필요 없는 WebJobs로 빠르게 테스트하고, 중기에 보다 견고한 동작을 필요로 하면 WebRole로 이전하는 것입니다. 그리고 마지막에 로직이 완숙해지면(그럴 시기는 안오겠지만ㅋㅋ) 로그 등 상태확인 기능을 보다 충실히 넣고 WebJobs로 다시 빠른 배포의 장점을 얻는 것입니다.

이 글은 TeamCity CI(Continuous Integration)를 이용한 Azure WebJobs 배포 방법을 적었으며, 이전에 작성했던 TeamCity에서 Azure WebSites Deploy하기 글이 많은 도움이 되었습니다.

Azure WebJobs를 TeamCity로 배포하기 위해서는 다음의 과정을 거칩니다.

  1. Visual Studio에서 Azure 배포 프로필 생성
  2. Azure WebSites Deploy 비밀번호 가져오기
  3. 소스콘트롤에서 Pull
  4. Nuget Restore
  5. MSBuild 실행

1. Visual Studio에서 Azure 배포 프로필 생성

먼저 Visual Studio의 프로젝트에서 우클릭을 하여 GUI를 이용한 WebJobs로 배포를 합니다. 이를 통해 프로필이 생성될 것입니다.

Azure WebJob 배포는 이 메뉴를 누릅니다
Azure WebJob 배포는 이 메뉴를 누릅니다

위의 과정을 거쳐서 WebJobs를 성공적으로 배포하면, 프로젝트 아래 pubxml 파일이 생성됩니다.

이처럼 프로필 이름과 동일한 pubxml 파일이 만들어집니다
이처럼 프로필 이름과 동일한 pubxml 파일이 만들어집니다

2. Azure WebSites Deploy 비밀번호 가져오기

Azure 포털에 들어가서 배포한 WebJobs가 정상동작하는지 확인했으면 이제 TeamCity를 이용하여 자동화시켜도 될 것입니다.

먼저 배포용 비밀번호를 Azure 포털에서 다운받습니다.

배포용 Credential 파일 다운로드
배포용 Credential 파일 다운로드

그 다음, 다운 받은 PublishSettings 파일을 열어서 userPWD=”etxffzgX4wML0RQ43R2KR87pemoySuJva7Cs”와 같은 부분이 있는데 따옴표 안의 내용을 복사합니다. 복사한 내용은 나중에 사용되니 잠시 메모장에 붙여넣기로 보관해주세요.

3. 소스콘트롤에서 Pull

TeamCity에서 Version Control Settings 메뉴를 이용하여 소스콘트롤에서 다운로드 받는 설정을 합니다. 이것은 어렵지 않으니 생략하겠습니다. 저희는 GitHub Private Repository를 이용합니다. 저희는 Visual Studio 2013을 이용하여 개발된 닷넷 프로젝트 하나를 굽게 할 것입니다.

4. NuGet Restore

닷넷 세상의 maven이라 할 수 있는 NuGet을 안쓰는 프로젝트가 거의 없죠? TeamCity는 NuGet 지원이 좋아서 NuGet Restore도 간편하고, 그 자체로 NuGet 서버 기능을 할 뿐 아니라 NuGet.org 서버에 Push하는 기능까지 이미 탑재하고 있습니다.

주의: 만일 TeamCity에 NuGet 설정이 되어있지 않다면 TeamCity 우상단에 Administration을 클릭한 후, Integration > NuGet > NuGet.exe 탭에서 “Fetch NuGet”을 설정해주세요.

Build Steps 메뉴에서 Build Step 하나를 추가합니다. 우리는 소스콘트롤에서 다운 받은 폴더의 솔루션파일(.sln)을 지정하고 nuget restore를 할 것입니다. 설정은 다음과 같이 해주세요.

  • Runner Type: NuGet Installer
  • Nuget.exe: Default
  • Path to Solution File: 우측 트리 아이콘을 눌러서 .sln 파일을 지정해주세요. 소스콘트롤 셋팅이 이미 되었다면 다운로드 받은 폴더 구조가 나올 것입니다.
  • Restore Mode: Restore
  • Update Mode: Update via packages.config file

5. MSBuild

이제 Build하고 그 결과를 WebJobs에 배포합니다. 새 Build Step을 생성하고 아래와 같이 지정해주세요.

  • Runner Type: MSBuild
  • Build file path: .csproj 경로 (.sln 아님)
  • MSBuild version: Microsoft Bulid Tools 2013
  • MSBuild ToolsVersion: 12.0
  • Command line parameters: 아래 소스 참고

아래는 읽기편하게 줄바꿈을 했지만 설정시 꼭 한 줄로 적어주세요.

/p:Configuration=Release 
/p:DeployOnBuild=True 
/p:PublishProfile="bapul-cube" 
/p:ProfileTransformWebConfigEnabled=False 
/p:AllowUntrustedCertificate=true 
/p:_DestinationType=AzureWebSite 
/p:Password=etxffzgX4wML0RQ43R2KR87pemoySuJva7Cs

여기까지 하면 빌드 후 바로 WebJobs에 배포하는데요, 위의 /p: 부분에서 몇가지만 풀어보자면 아래와 같습니다.

  • Configuration=Release : 이건 쉽죠. Release 설정으로 빌드하겠다는겁니다.
  • DeployOnBuild=True : 말그대로 빌드 후 바로 배포 스크립트를 실행하는겁니다.
  • PublishProfile=”bapul-cube”: pubxml파일, 즉 Azure WebJobs 배포 프로필 이름입니다.
  • Password: publishsettings 파일에서 복사한 내용을 붙여넣어주세요.

여기까지가 끝입니다.
이제 코딩하고 Git push만 하면 TeamCity가 자동으로 배포까지 해줄 것입니다 🙂

TeamCity에서 안드로이드앱 배포하기

TeamCity는 제가 좋아하는 CI(Continuous Integration)툴, 다시 말해 소프트웨어 빌드 자동화 프로그램입니다. 몇 일 전에 버전 9이 나왔습니다. 무료로는 빌드설정 20개, 에이전트 3개의 제한된 수준으로 사용할 수 있으니 상당히 많은 혜택을 주는 셈입니다. 스타트업들에게는 뒤집어쓸만큼인거죠.

본론으로 들어가서, TeamCity에서 안드로이드 앱을 배포하는 방법을 알아봅시다. 다음의 상황을 가정합니다. 팀 내에서 알파버전 테스트, 즉 개밥주기(Dogfooding)를 할 때 두가지 방법을 사용할 수 있습니다.

  1. 구글 Play스토어가 제공하는 알파버전 배포방법을 이용.
  2. 빌드서버에서 직원들에게 이메일로 apk를 다운로드하도록 제공.
    • 오늘 설명할 방법.
    • 장점: 개발자가 소스코드 push만 하면 끝. 배포는 즉시.
    • 단점: 받는 사람이 매번 새로 깔아줘야 함.
  3. 매번 동료들 핸드폰 똥구멍에 선꽂고 구워주기 (이런건 이제 그만~)

즉, 빌드서버를 이용하는 방법은 양해를 구할 수 있는 팀 내에서 빠른 배포 사이클을 원할 경우 절대적인 장점을 지닙니다. Play스토어를 이용하는 방법은 외부인이 개입되는 클로즈베타에 유용합니다.

이제 다음의 과정을 거쳐서 설정할 것입니다.

  1. git에서 소스 다운로드 및 실행
  2. Build Step 작성: gradle부터 파일정리까지 (총 4단계)
  3. apk를 artifact로 인식
  4. 빌드 성공시 이메일로 알림
  5. 이메일에 원클릭 다운로드 링크 제공

참고: 제 TeamCity 및 안드로이드는 모두 윈도우 기반셋팅입니다. 윈도우에서 안드로이드 코딩하고 윈도우서버용 TeamCity를 설치했으니 다른 플랫폼은 경로나 소소한 셋팅이 다를 수 있습니다.

1. git에서 소스 다운로드 및 실행

자세한 설명은 생략합니다. Version Control Setting에서 git 주소를 연결하시면 됩니다. 또한, Triggers 메뉴에서 VCS Trigger를 만들어서 git이 갱신될 때마다 구동되도록 합니다.

저는 Trigger에 Quiet Period: 180초를 걸어서 push하고 가끔 파일 빼먹을 때가 있어서 급히 넣곤 하니까 3분 후 굽도록 했습니다.

2. Build Step 작성: gradle부터 파일정리까지

2.1 Clean

Build Step의 첫번째로, Gradle Clean을 합니다. 이전에 빌드한 데이터와 꼬일 수 있으니 비워주면 좋습니다.

  • Runner type: Gradle
  • Gradle tasks: clean
  • Additional Gradle command line parameters: --info
  • Gradle Wrapper: Use gradle wrapper to build project → 체크합니다.
  • Stacktrace: Print stacktract → 체크합니다.

설정 스크린샷은 아래와 같습니다. “어? 나보다 항목이 많은데?”라고 하시는 분은 제일 아래 노란색 “Show advanced options”를 클릭하세요. 중간에 Working directory는 git 다운로드 폴더를 임의로 지정했을 경우이며 취향일 뿐입니다.
캡처e1

2.2 gradle assembleRelease

소스를 컴파일하고 apk로 만들기 위한 assembleRelease 명령을 실행합니다. “2.1 Clean”과 거의 유사하며 다음만 다릅니다.

  • Gradle tasks: assembleRelease

센스있는 분이라면, 첫번째 스텝을 실행해보시고 성공하면 Build Steps 표에 나오는 “Copy build steps” 버튼을 이용해서 복사하시면 됩니다.

여기까지 하고 일단 한 번 Run 해서 확인합니다. 빌드 결과를 다음 스텝에서 인식하면 편하기 때문입니다.
여기까지 성공하면 80% 완료한겁니다.

2.3 unaligned 파일 삭제하기

assembleRelease를 하면 apk파일이 두 개 나옵니다- aligned, unaligned. 둘의 차이는 제가 올린 stackoverflow 질답글에서 알 수 있습니다. 결론은 unaligned는 지워도 되는 파일입니다.

  • Runner type: Command LIne
  • Working directory: apk나오는 경로 지정. Working Directory는 우측에 트리 아이콘을 눌러서 지정하세요. 제 경우 project/build/outputs/apk이지만 경우에 따라 다릅니다.
  • Run: Command Executable with parameters 선택.
  • Command executable: del
  • Command parameters: *unaligned.apk

참고: 리눅스나 맥OS용 TeamCity는 다르겠지요. 목적은 같을테니 내용을 파악하여 적용하시면 됩니다.

2.4 Rename (옵션)

다운받는 사람들에게 버전을 명확히 인식시키기 위해 빌드버전이 파일명에 나타나도록 합니다. 그래야 나중에 메신저로 “15버전 받으세요~”라는 식으로 말할 수도 있으니까요.

TeamCity는 한 번 구울 때마다 build.counter라는 값이 1씩 올라가니까 이걸 이용합니다. 위에 2.3과 거의 동일하니 역시 Copy Build Step을 이용해서 복사합니다.

  • Runner type: Command Line
  • Working directory: 2.3과 동일
  • Command executable: rename
  • Command parameters: bapul-release.apk bapul-release-%build.counter%.apk

물론 Command parameter는 맘에 드는 이름으로 지으세요. 저희 회사 이름 그대로 넣지 마시고요.

최종적으로, 빌드스텝 4개는 아래와 같아집니다.
캡처

3. apk를 artifact로 인식

Artifact가 사전에서는 말이 어려운데, 흔히 말하는 “산출물”입니다.
캡처

간단히 한 줄 설정이며, General Settings 메뉴에 들어가서 다음을 설정합니다.

  • Artifact paths: project\build\outputs\apk\bapul-release-%build.counter%.apk

역시 마찬가지로 우측 폴더트리 아이콘을 클릭하여 Step 2.4에 있던 경로를 참고하여 적어줍니다. 이러면 해당 apk 파일이 최종 산출물로 인식되어 원클릭 다운로드가 되도록 할 수 있습니다.

4. 빌드 성공시 이메일로 다운로드 링크 전송

빌드 성공시 서버가 Email을 보내려면 SMTP 설정이 되어있어야 겠지요. SMTP 설정은 사용하시는 메일서비스마다 다르겠고요. 저희는 구글앱스를 쓰는데 다음과 같습니다. 이 메뉴는 Administration > Email Notifier에 있습니다.
캡처

SMTP 설정은 했다치고, Notification은 개인마다 또는 그룹마다로 지정할 수 있습니다. 본인에게 먼저 테스트해보려면, 우상단 자기 profile을 들어간 후, Email Notifier에 “Add New Rule” 버튼을 클릭합니다.

“Builds from the selected build configurations”를 체크한 후 트리에서 원하는 프로젝트를 선택한 후, 우측 체크박스에서는 빌드 성공했을 때만 보내야 하니까 “Build is successful”에만 체크합니다.

아마도 메일이 잘 갈텐데 메일 받는건 다음과 같이 갑니다.

2014-12-13-14-01-25

위에 #15라는 링크를 클릭하면 브라우저가 뜨고 로그인을 하면 teamcity의 프로젝트 화면으로 갑니다. 거기서 Artifacts 탭에 간 후 파일을 선택하고 다운로드를 클릭하면 받아지지요.
그룹이나 특정 사람에게 보내려면 Administration > Users > 특정 사람 또는 Groups에서 해당 소속에게 일괄전송이 가능합니다.

5. 이메일에 원클릭 다운로드 링크 제공 (옵션)

TeamCity에 로그인은 한 번만 하면 그 후엔 자동로그인이 되니까 양해를 구할 수 있지만, 뭔지 알 수도 없는 프로젝트 화면을 팀원들이 보도록 하는건 어쩐지 불친절합니다. 받은 이메일에서 원클릭으로 apk를 받을 수 있도록 해야 할겁니다.

저는 TeamCity에 대해 무한히 좋아하는 마음을 가지고 있지만, 단 하나 부족한게 이메일 템플릿이 고정적이라는겁니다. 즉, Successful 메시지는 하나의 템플릿 파일에만 의존합니다. 그러므로, 이메일 템플릿을 요리하려면, 해당 템플릿에 if문을 넣어서 특정 프로젝트 결과에 대해서만 처리를 해줘야 합니다.

해당 이메일 템플릿 파일은 TeamCity 서버에 다음의 경로에 있습니다.
ProgramData라는 폴더는 숨김폴더임을 주의하세요.
Untitled-1

스크린샷에서 보이는 build_successful.ftl 파일을 수정합니다. 이 템플릿은 “FreeMaker”라는 자바기반 템플릿 언어에 기반합니다. 전체 파일은 제가 gist(클릭:열기)에 올려놓았습니다.

보면 아래와 같은 부분이 추가되었습니다. (제 프로젝트에 맞게 if문을 수정했습니다)

<#-- MODIFICATION START -->
  <#if buildType.externalId = "Android_BapulCube">
    <br>
    <a href='http://www.your-company.net/repository/download/${buildType.externalId}/.lastSuccessful/bapul-release-${build.buildNumber}.apk'>Click here to download APK.</a>
    <br>
  </#if>
<#-- MODIFICATION END -->

참고로, buildType.externalId는 해당 Build Configuration의 ID입니다. 해당 빌드셋팅가서 볼 수도 있고, 주소창에 http://www.your-company.com/viewType.html?buildTypeId=Android_BapulCube 형태로 보이기도 합니다. 빌드셋팅의 고유ID니까 특정 빌드 결과에 대한 것만 받는 경우이며, 다른 센스를 부리자면 project.name=”Android”와 같이 할 경우 Android라고 이름지은 프로젝트의 모든 빌드 결과에 대해 받게 되겠지요.

더 멋지게 꾸밀 분은 TeamCity Notification 설명서를 참고하세요.

여하간, 이렇게 설정하면 아래와 같이 소박하게 다운로드 링크가 나옵니다. “Click here to download APK.”라는 부분 보이시죠? 이제 팀원들은 (로그인을 했다면) 원클릭으로 apk를 다운받고 앱을 테스트할 수 있겠지요.

2014-12-13-14-00-36

더 센스를 부리자면 앱에 업데이트 프로그램을 구동시켜서 할 수도 있을겁니다. 그에 대한 방법은 여기서 다루지는 않겠습니다.

휴~ 끝났습니다.

TeamCity에서 Azure Worker Role Deploy하기

파워셸을 처음 써보느라 거의 5시간 걸려서 해냈네요. 프로그래밍의 재미란 역시 이런것….은 개뿔 옳지 않습니다.

이전 글 TeamCity에서 Azure WebSites Deploy하기에 이은 이번엔 Azure Cloud Worker Role로 Deploy하는 법을 알아봅시다.

Azure Worker Role은 백그라운드 작업에 유용한 것으로, 단점은 지극히 느린 Deploy 시간입니다. 대략 짧게는 4분, 길게는 10분 가량의 시간이 소요되는데, 이렇게 오래 걸리는 이유는 수많은 과정을 거치기 때문이랍니다. 그러니 Visual Studio만 쳐다볼게 아니라 이런건 빌드서버에 맡겨두고 아이돌 음악 두세곡이 흐를 때 즈음 알림을 받는게 더 고상한 삶입니다.

빌드서버란 보통 이런 일을 합니다
빌드서버란 보통 이런 입장입니다

참고로 이 글은 srkirkland의 포스트를 참고했으며, 최근 주요 변경점을 반영했고, 삽질 오류 상황을 덧붙여서 업데이트한 글입니다.

필자가 이미 충분히 인생을 허비했으니 이 글을 따라하는 분들은 영생을 얻길 바랍니다.

Azure Worker Role을 Deploy하기 위해서는 총 3개의 빌드스텝이 필요합니다.
이 글은 TeamCity에서 배포하는 방법에 대한 가이드이며, 다음의 과정을 거칩니다.

  1. 로컬에서 배포테스트
  2. 소스콘트롤에서 Pull / Nuget Restore
  3. MSBuild
  4. 인증파일(.publishsettings) 설정
  5. 파워셸 스크립트
  6. 에러체크
  7. 트리거 설정 (옵션)

사실 빌드서버라는게 하는 일이 뻔합니다. 소스받아 컴파일하고 압축된 결과를 업로드하고 초기구동 스크립트를 실행하는거죠.

1. 로컬에서 배포테스트

로컬 컴퓨터에서 돌리는 Visual Studio의 클라우드 프로젝트에 우클릭하여 Publish를 클릭합니다. 많은 셋팅은 이에 기반하므로 먼저 성공하는지 점검해봅니다. 특히 Worker Role은 소스에 문제가 있는 경우 무한대기에 빠지는 경우도 있으니 일단 가장 기본 소스로 배포 자체가 성공하는지를 점검하는 것이 중요합니다.

2. 소스콘트롤에서 Pull / Nuget Restore

이전 글의 과정 1번, 2번과 동일합니다. 그대로 따라서 첫번째 Build Step인 Nuget Restore까지 만들어주세요.

3. MSBuild

먼저 주의할 점은, 빌드 서버에 동일 버전의 Azure SDK, Azure Cmdlet이 설치되어있어야 합니다. 설치는 Platform Installer를 이용하시면 편합니다.
빌드스텝 하나를 만들고 다음과 같이 설정해주세요.

  • Runner Type: MSBuild
  • Bulid File path: 솔루션 파일
  • MSBuild version: Microsoft Build Tools 2013
  • MSBuild ToolsVersion: 12.0
  • Run platform: x86 (다를 수 있음)
  • Targets: Publish (중요)
  • Command line parameters: /p:Configuration=teamcity_worker

마지막 줄에 /p:Configuration=teamcity_worker란? 이것은 아래 그림과 같이 Start 버튼 옆에 Solution Configuration이라는 콤보박스에 있는 것입니다. 저처럼 한 솔루션에 백그라운드와 상관없는 프로젝트가 있는 경우 괜히 빌드 에러가 날 수 있으므로 Dependency를 확인하고 꼭 필요한 것들만 컴파일 하도록 체크해줍니다.

캡처3

4. 인증파일(.publishsettings) 설정

이게 재미난데, 빌드서버에서 Microsoft Azure PowerShell을 실행하고 아래와 같이 Get-AzurePublishSettingsFile이라고 입력하면, 뜬금없이 브라우저가 뜨더니 로그인을 하라고 합니다. 로그인을 하면 Azure의 구독(subscription)을 선택하게 되고 .publishsettings 파일을 다운받게 해줍니다. 콘솔공포증인 저는 처음에 콘솔입력에 쫄았지만 다행이었습니다.

캡처5

이 파일을 “C:\teamcity\”에 파일명을 짧게 고쳐서 넣습니다. 보안이 걱정되면 보안이 좀 더 좋은 어딘가에 넣어놓으세요. 참고로 빌드서버는 외부접속이 안되도록 하는 경우가 대부분입니다.

5. 파워셸 스크립트

파워셸 스크립트로 Azure에 업로드를 합니다.
우린 지금까지 Nuget restore, MSBuild 빌드스텝을 만들었고, 이제 세번째가 되는 새 빌드스텝을 만들어서 다음의 값을 입력합니다.

  • Runner Type: Powershell
  • Powershell run mode: Any / Bitness: x86 (이건 만든 프로젝트에 따라 맞추세요)
  • Error Output: error (중요)
  • Script: Source Code
  • Script source: 아래 코드를 복사붙이기 한 후 […] 부분을 바꿔주세요. gist에도 올려놨습니다.
  • Script execution mode: Put script into PowerShell stdin with “-Command -” arguments

파워셸 스크립트

$ErrorActionPreference = "Stop"
$subscription = "[Your Subscription Name]"
$service = "[Your Azure Service Name]"
$slot = "staging" #staging or production
$package = "[ProjectName]bin[BuildConfigName]app.publish[ProjectName].cspkg"
$configuration = "[ProjectName]bin[BuildConfigName]app.publishServiceConfiguration.Cloud.cscfg"
$timeStampFormat = "g"
$deploymentLabel = "ContinuousDeploy to $service v%build.number%"

Write-Output "Running Azure Imports"
Import-AzurePublishSettingsFile "C:TeamCity[Your PublishSettings Filename].publishsettings"

function Publish(){
 Write-Output "$(Get-Date -f $timeStampFormat) - Publising Azure Deployment..."
 $deployment = Get-AzureDeployment -ServiceName $service -Slot $slot -ErrorVariable a -ErrorAction silentlycontinue 

 if ($a[0] -ne $null) {
    Write-Output "$(Get-Date -f $timeStampFormat) - No deployment is detected. Creating a new deployment. "
 }

 if ($deployment.Name -ne $null) {
    #Update deployment inplace (usually faster, cheaper, won't destroy VIP)
    Write-Output "$(Get-Date -f $timeStampFormat) - Deployment exists in $service.  Upgrading deployment."
    UpgradeDeployment
 } else {
    CreateNewDeployment
 }
}

function CreateNewDeployment()
{
    write-progress -id 3 -activity "Creating New Deployment" -Status "In progress"
    Write-Output "$(Get-Date -f $timeStampFormat) - Creating New Deployment: In progress"

    $opstat = New-AzureDeployment -Slot $slot -Package $package -Configuration $configuration -label $deploymentLabel -ServiceName $service

    $completeDeployment = Get-AzureDeployment -ServiceName $service -Slot $slot
    $completeDeploymentID = $completeDeployment.deploymentid

    write-progress -id 3 -activity "Creating New Deployment" -completed -Status "Complete"
    Write-Output "$(Get-Date -f $timeStampFormat) - Creating New Deployment: Complete, Deployment ID: $completeDeploymentID"
}

function UpgradeDeployment()
{
    write-progress -id 3 -activity "Upgrading Deployment" -Status "In progress"
    Write-Output "$(Get-Date -f $timeStampFormat) - Upgrading Deployment: In progress"

    # perform Update-Deployment
    $setdeployment = Set-AzureDeployment -Upgrade -Slot $slot -Package $package -Configuration $configuration -label $deploymentLabel -ServiceName $service -Force

    $completeDeployment = Get-AzureDeployment -ServiceName $service -Slot $slot
    $completeDeploymentID = $completeDeployment.deploymentid

    write-progress -id 3 -activity "Upgrading Deployment" -completed -Status "Complete"
    Write-Output "$(Get-Date -f $timeStampFormat) - Upgrading Deployment: Complete, Deployment ID: $completeDeploymentID"
}

#Azure Publish Execution
try{
    Set-AzureSubscription -CurrentStorageAccount [Your Storage Account Name] -SubscriptionName $subscription
    Publish
}catch{
    throw #Rethrow to detect failed build status.
    Break
}

하단의 [Your Storage Account Name]까지 꼼꼼하게 바꿔주세요. 바꿀 값들은 로컬에서 Publish할 때 나오는 창의 Summary에 대부분의 내용이 있습니다.

여기까지 하고 일단 Run을 실행해서 잘 되는지 확인해봅니다.

6. 에러 체크

TeamCity는, PowerShell 스크립트를 실행할 때 오류가 나도 success라고 되는 문제가 있습니다. 하지만, 저는 그 문제를 스크립트 마지막에 throw를 넣는 처리를 했고, 이제 teamcity가 이것을 통해 error라고 인식하게 해야 합니다.

말은 복잡하지만 아래처럼 간단히 체크 하나만 해주면 됩니다.
캡처3

끝났습니다.

7. 보너스: 트리거

저는 이전에 올린 Azure WebSites와 같은 솔루션을 사용하고 있으므로, VCS에서 Worker 프로젝트만 수정해도 WebSites가 구워지고, WebSites만 수정해도 8분가량 걸리는 Worker가 수정되는 문제가 있었습니다.

이를 해결하기 위해서는 Build Trigger Rule을 설정해줍니다.
캡처3
Trigger Rules의 기본규칙은, +는 Include, -는 Exclude이며, 위 그림의 설정을 보건데, /BapulServer/BapulSpreadWorker, /BapulServer/BapulCloudApiService 라는 폴더의 하부에 변화가 생겼을 때만 빌드를 수행합니다. 반대는 -:/폴더경로 식으로 해주면 ‘그 폴더에 대한 변화는 무시한다’는 뜻이 되므로 적절히 조합해서 사용하시면 되겠습니다. 자세한 규칙은 공식문서를 참고하세요.

최종적으로는, 아래 그림과 같이 셋팅이 되어 있을겁니다.
캡처4

그럼 즐거운 하루 보내세요.
레알 끝!

TeamCity에서 Azure WebSites Deploy하기

JetBrains TeamCity는 훌륭한 CI(Continuous Integration) 소프트웨어로, 자바기반으로 만들어져서 거의 모든 OS를 지원하며 무료 사용으로도 어느정도 풍부한 기능을 사용할 수 있다. 적어도 꼬꼬마 스타트업은 뒤집어쓸 정도로 여유롭다.

특히 Jenkins를 쓰는 회사들은 어지간해서는 TeamCity로 교체하길 추천한다. 그 이유는 Jenkins는 정말 눈물이 나고 손가락이 오그라들 정도로 민망하고 불편한 UI/UX를 가지고 있기 때문이다. 개발자도 예쁜거 좋아한다.

각설하고, 원래 Azure WebSites는 Git에서 바로 배포가 가능하다. 하지만 프로젝트가 복잡해지면 기본 기능만으론 부족해진다.

Azure WebSites를 TeamCity로 배포하기 위해서는 다음의 과정을 거치면 된다.

  1. 소스콘트롤에서 Pull
  2. Nuget Restore
  3. 빌드+배포 (빌드하자마자 바로 publish 가능하도록 되어 있다)
  4. Azure WebSites Deploy 비밀번호 적용

1. 소스콘트롤에서 Pull

TeamCity의 Project 하나를 만들면 좌측 메뉴 중 Version Control Settings 메뉴가 있다. master 브랜치로 하든 release 브랜치로하든, 이 글의 주제 밖이며 설정에 어려움이 딱히 없다.

2. Nuget Restore

Build Steps에서 하나를 추가한 후 아래와 같이 설정한다.

  • Runner Type: NuGet Installer
  • NuGet.exe: Default (2.8.3) 버전명은 다를 수 있다
  • Path To Solution File: 옆에 트리를 눌러서 .sln 파일을 지정한다.
  • Restore Mode: Restore

나머지는 딱히 할 것이 없다.

만일 Nuget 버전이 안나온다면 Teamcity에 Nuget설치가 안된 것이다. 걱정마시라. TeamCity의 NuGet 설정은 클릭 몇 번에 끝난다. 설정법은 우상단 Administration > Integration 섹션에 NuGet > Nuget.exe 탭의 Fetch Nuget 버튼만 누르면 버전별로 골라가져올 수 있다. TeamCity 자체가 NuGet서버로 사용될 수도 있고 빌드시에는 자신한테 있는 NuGet.exe를 이용해 패키지를 다운받아서 restore시 적용한다.

가히 멋지고 인텔리전트하고 판타스틱하다.

3. 빌드+배포

이에 대해서는 두가지 방법이 있다. (1) Solution Build를 하는 것, (2) MSBuild를 이용하는 것. 필자처럼 솔루션에 꼭 WebSites에 올릴 것만 있는게 아니라 다른 프로젝트(백그라운드작업 등)가 같이 있다면 MSBuild를 이용한다. (Solution Build만으로 문제없으면 그냥 Azure WebSites에서 제공하는 기본 배포 기능 이용해도 된다.)

  • Solution Build를 이용할 분들은 다음을 참고한다 => 링크
  • 보너스: Azure WebRole로 배포하길 원하면 다음을 참고한다 => 링크

MSBuild로 설정할 경우 다음과 같이 설정한다.

  • Runner Type: MSBuild
  • Build file path: 앞서 NuGet에서 지정한 것과 동일한 .sln 파일 지정.
  • MSBuild Version: Microsoft Build Tools 2013
  • MSBuild ToolsVersion: 12.0
  • Run platform: 12.0
  • Targets: Rebuild
  • Command line parameters
/p:Configuration=teamcity_server
/p:DeployOnBuild=true
/p:PublishProfile=teamcity
/p:ProfileTransformWebConfigEnabled=False
  • Reduce test failure feedback time: 체크하세요.

위의 /p: 중에 알아야할게 있다.

  • Configuration=teamcity_server: teamcity_server는 무엇인가? 이것은, 아래의 Configuration Manager의 설정 이름으로 여러 프로젝트 중 관련 없는 것을 무시하도록 설정한 이름이다. 보면 체크가 빠진 것들이 보일 것이다.

  • DeployOnBuild=true: 이것이 멋진 기능인데 Build하면 바로 Publish하는 것이다. 패키지 zip으로 만들고 업로드하고 명령어 날리는 것을 알아서 다 해준다.
  • PublishProfile=teamcity: 이게 어디있는 이름이냐면 아래 그림과 같은거다. 우리가 프로젝트에 우클릭하고 Publish 누르면 Publish Web이라는 창이 뜨고 여기서 Publish를 누르면 Azure WebSites에 올라가는데 그 설정 이름이다. 여기서는 teamcity라고 하나 만들었다.


이 창은 Publish라고 부르지만 기술적으로는 MSDeploy라고도 한다.

여기까지 하면 대략 TeamCity Build Steps 설정은 아래 그림과 같아진다.


세번째 행에 disable된 것은 무시하자. 실험하느라 만들었던거다.

이제 여기서 성급하게 우상단에 Run을 누르면 Authentication error가 발생한다. 이유는 Azure WebSites Deploy용 비밀번호를 안넣었기 때문이다. 이제 마지막 설정이 남았다.

Azure WebSites Deploy 비밀번호 적용

Azure 포탈에 접속해서 배포용 PublishSettings 파일을 받는다.


위 그림에 노란색 표시한 버튼이다.

받아서 메모장으로 열면 userPWD=”etxffzgX4wML0RQ43R2KR87pemoySuJva7Cs”와 같은 부분이 보일 것이다. 따옴표 안의 내용을 복사한다.

프로젝트 우클릭으로 Publish를 클릭해서 만들었던 teamcity.pubxml이라는 파일을 수정할거다. 더블클릭으로 열면 된다. 위치는 프로젝트>Properties>PublishProfiles>teamcity.pubxml 이다.

<PropertyGroup>
    ....
    <Password>etxffzgX4wML0RQ43R2KR87pemoySuJva7Cs</Password>
</PropertyGroup>

위와 같이 Password라는 태그를 만들어 넣는다.

됐다!

이제 TeamCity에 Run을 눌러서 Success가 되는지 확인해보자. 에러가 나면 여기에 물어보지 말고 직접 해결하자!

보너스

지금은 21세기이므로 git push를 하면 바로 굽는 설정을 하자. master branch로 push만하면 몇 분 후 알아서 구워주고, 결과는 아래 그림처럼 Visual Studio에서도 확인할 수 있다.
캡처4

방법은 간단하다. TeamCity에서 아래와 같이 Triggers 설정 하나만 해주면 된다.

VisualStudio에서 받아보는건, 우상단 자기 ID를 클릭하면 IDE플러그인을 받을 수 있는 메뉴가 뜨며, Notification Rules탭에서 IDE, Email 등으로 빌드 결과를 볼 수 있게 되어 있는데 IDE Notifier의 Add New Rule을 눌러서 원하는 프로젝트에 빌드 성공/실패에 대한 체크박스만으로 설정하면 된다.

레알 끝이다.