2011년 12월 1일 목요일

SCM - 외래 코드 관리


스트림 셋업

추천하는 셋업은 사용할 제3자(벤더) 코드 콤포넌트에 대한 스트림을 하나 생성하는 겁니다. 만약 같은 벤더로 부터 여러 서브시스템을 받게 되고, 각 서브시스템별로 릴리즈가 된다면 각각의 콤포넌트로 구성해야 합니다. 생성된 스트림은 제3자 코드의 원래 버전을 추적하기 위한 용도입니다. 릴리즈가 새로 도착하면, 이 스트림으로 전달할겁니다. 편의상 "벤더 스트림"이라 부르겠습니다.
우리가 개발 중인 애플리케이션 또한 별개 콤포넌트에 넣고 별개 스트림을 갖고 있습니다. 이 스트림에는 제3자 콤포넌트가 추가되어 있습니다. 제3자 코드에 대한 추가적인 수정 사항은 이 스트림에 전달할 겁니다.  다시말해, 이 스트림에는 제3자 릴리즈와 애플 개발에 필요한 추가한 변경 세트가 들어 있습니다. 편의상 "벤더 스트림"과 구별하기 위해 "개발 스트림"이라 부르겠습니다.
다음 예제에서는, JUnit 팀이 JUnit의 결과를 복잡한 report로 보여주는 기능을 추가할려고 합니다. 이를 위해 제3자로 부터 Sweet Reporter 기능을 도입해 활용할려고 합니다. 스트림 셋업은 다음과 같습니다.
Sweet Reporter 벤더/제3자 코드를 위한 Sweet Reporter "벤더 스트림"이 있습니다. 여기엔 특별한 수정사항 없이, 릴리즈 버전만 담고 있습니다. Markus는 새로 릴리즈되는 Sweet Reporter를 벤더 스트림에 넣기 위한 저장소 작업공간을 갖고 있습니다.
여기엔 또한 JUnit 프로젝트를 위한 "개발 스트림"이 있습니다. 물론 Sweet Reporter 콤포넌트가 이 스트림에 추가되어 있습니다.  JUnit "개발 스트림"의 Sweet Reporter 콤포넌트는 애플관련 수정 사항을 포함할 수 있습니다. Markus는 또한 Sweet Report 스트림에 있는 새로운 Sweet Reporter 릴리즈와 JUnit 스트림상에서 애플 개발팀이 Sweet Reporter에 수정한 변경 사항을 통합하기 위한 저장소 작업공간을 갖고 있습니다. 통합된 결과는 JUnit 스트림으로 전달하게 됩니다.


벤더/제3자 코드를 RTC 소스제어에 반입하기

벤더 코드 프로젝트를 저장소 작업공간으로 팀 > 프로젝트 공유...합니다. 공유 후에는 새로 작성 > 기준선...을 실행하여 베이스라인을 벤더 스트림으로 전달합니다. 베이스라인에 레이블을 붙이고 릴리즈 정보를 설명에 입력할 수 있습니다. 
아래 예에서 JUnit 팀의 Markus는 Sweet Reporter에 대한 zip 파일을 받습니다.
Initial delivery of vendor code
먼저 소스 코드를 RTC 소스제어에 공유한 뒤(공유시 Sweet Reporter용 콤포넌트를 추가했다고 가정), 해당 콤포넌트에 대해 베이스 라인 Beta 1.0을 만들고 나서, 벤더용 저장소 작업공간에서 Sweet Reporter (벤더) 스트림으로 전달합니다. 반입 끝.
RTC에 벤더/제3자 코드가 반입되면, 다음으로 할일은 모든 팀원들이 사용할 수 있도록 하는 겁니다. 여러가지 방법이 있습니다. 
방법1. 벤더용 저장소 작업공간을 이용해 개발팀과 공유하는 방법 : 벤더용 저장소 작업공간의 소스가 로드된 상태에서, 플로우 대상을 팀의 개발 스트림으로 변경한 후, 콤포넌트 추가사항을 전달할 수 있습니다.
Option 1 : Deliver directly to development stream 

Sweet Reporter 콤포넌트는 JUnit 개발 스트림에 추가되기 위해 전송가능합니다. JUnit 콤포넌트는 수신가능한데, 이는 작업중인 벤더용 저장소 작업공간에 JUnit 콤포넌트가 추가되어 있지 않기 때문입니다. Markus는 Sweet Reporter 콤포넌트를 전송만 합니다. 방법1 끝.
방법2. 개발용 저장소 작업공간을 이용해 개발 팀과 공유하는 방법 : 보다 조심스러운 방법으로 먼저 애플리케이션 코드와 잘 맞는 지 먼저 확인해 봅니다. 먼저 빌드를 해볼 수도 있습니다. 이 경우, 애플리케이션 코드가 로드된 개발용 저장소 작업공간의 플로우 대상을 벤더 스트림으로 바꿉니다. 제3자 코드 콤포넌트 추가를 수신합니다. 
Option 2 : Accept component from vendor stream
Markus의 개발용 저장소 작업공간에는 벤더 스트림에서 추가된 Sweet Reporter 콤포넌트는 수신가능 형태로 나타나고, 벤더 스트림 상에는 없는 JUnit 콤포넌트는 전송가능 형태로 나타납니다. Markus는 벤더 콤포넌트를 수신합니다 (JUnit 콤포넌트는 벤더코드가 아니므로 전송하지 않습니다).
콤포넌트 추가를 수신한 뒤, 플로우 대상을 다시 개발용 스트림으로 변경합니다. 개인 빌드를 실행하고, 필요한 통합 변경 작업을 즉시합니다. 이제 팀과 공유할 준비를 마쳤으면, 벤더용 콤포넌트 추가를 개발용 스트림으로 전달합니다.
Deliver to development stream 
Markus는 SweetReporter 콤포넌트를 JUnit 개발 스트림으로 전달합니다. 방법2 끝.


애플리케이션에 필요한 벤더/제3자코드 수정하기

제3자 코드를 이용한 기능을 개발용 콤포넌트에 별개 프로젝트로 개발합니다. 그렇지만, 어느 시점에 제3자 코드에 변경이 필요하다는 것을 알게됩니다.
작업 공간에 있는 제3자 코드를 애플리케이션 코드를 변경하던 것처럼 수정할 수 있습니다. 이상적으론 코드 버그 수정 및 개선을 잘 기술한 작업 항목을 변경 세트와 연계합니다. 물론 당장은 변경에 대한 내용을 정확히 알 수 있지만, 나중에 벤더 코드의 새로운 릴리즈에 포팅할 경우를 고려해서 상세히 기록해 두는 것이 도움이 됩니다. 변경 작업을 마친 뒤에는 팀의 개발용 스트림으로 전달합니다. 벤더용 스트림으로 전달하면 안됩니다. 벤더용 스트림은 벤더로 부터 받은 버전만을 관리하기 위한 용도입니다.
당신은 왜 벤더용 스트림과 개발용 스트림 간에 콤포넌트 구성을 달리 가져가는 지 궁금할 겁니다. 주된 이유는 애플리케이션에 특정된 변경을 간단히 구별하기 위한 겁니다. 벤더용 스트림과 작업할 경우는 오직 제3자 코드의 새 릴리즈를 수신할 때 뿐입니다.


벤더/제3자 코드의 새로운 릴리즈와 통합하기

벤더/제3자 코드의 새로운 릴리즈와 통합하는 단계는 다음 두가지 단계입니다. 첫단계는 제3자 코드의 새로운 릴리즈를 반입하는 단계이고, 두번째 단계는 제3자 코드의 새로운 릴리즈를 개발 스트림으로 통합하는 단계입니다.

단계1. 제3자 코드의 새로운 릴리즈를 반입하기


벤더용 스트림의 최신 내용과 동기화되어 있는 벤더용 저장소 작업공간(전송 및 수신할 변경사항이 없는 상황)에서 로드해제한 상태로 만듭니다. 비어 있는 샌드박스(로컬 작업공간)에 제3자 코드의 새로운 릴리즈를 복사합니다. 다시 말해, 로드된 저장소 작업공간이 없어야 합니다. 이제 벤더용 저장소 작업공간의 벤더용 콤포넌트로 프로젝트들을 공유합니다. 때때로 이를 일컬어 "재공유"라고 합니다.


Re-sharing new vendor release
Markus는 Sweet Reporter 새로운 릴리즈를 이클립스 작업공간에 압축해제합니다. 공유 마법사를 통해서 벤더용 작업공간의 Sweet Reporter 콤포넌트로 프로젝트들을 공유합니다.

이 과정을 통해 아직 체크인되지 않은 변경사항들이 만들어 집니다. 이러한 변경사항들은 이전 릴리즈로 부터 새로운 릴리즈를 만들기 위한 변경 사항을 나타냅니다. 해당 변경사항들을 저장소로 체크인합니다. 본 과정은 삭제된 프로젝트들을 식별할 순 없습니다. 벤더용 저장소 작업공간에서 해당 프로젝트들을 로드하고 나서, 프로젝트 탐색기에서 해당 프로젝트들을 선택하고, 팀 > 저장소에서 삭제...를 실행하여 프로젝트를 삭제하는 변경 작업을 수행합니다.
변경 세트는 릴리즈 간의 차이를 포함하고 있어서, 변경 세트를 통해 새로운 릴리즈에 대한 전반적인 변경 내역을 알 수 있고, 상세 변경 내역도 탐색할 수 있습니다. 게다가, 지난 시간 동안의 파일의 이력을 볼 수 있고, 주석 달기를 통해 언제 어떻게 변경되었는 지 확인할 수 있습니다.

Beta 2 changes
Markus는 Sweet Reporter Beta 1.0 릴리즈에 가해진 (Beta 2.0 릴리즈를 형성케한) 변경 내역을 알수 있는 변경 세트를 갖게 되었습니다. 공개 API에 몇개의 파일이 추가되었다는 걸 알수 있고, API 변경 사항을 알아보기 위해 비교편집기를 사용할 수 있습니다.
모든 변경사항들을 체크인한 뒤에는, 새 릴리즈에 대한 새로운 베이스라인을 만들고 전달합니다. Markus는 Beta 2 베이스라인을 Sweet Reporter 벤더용 스트림으로 전달합니다.

단계2. 개발용 스트림과 통합하기

애플리케이션 특화된 변경이 없다면 이 단계는 간단합니다. 애플리케이션 특화된 변경을 했다면, 새로운 릴리즈에 필요한 변경사항을 재적용해야 합니다. 필요한 변경 사항을 포워드 포팅하는 과정을 수반합니다.
아래 예는 가장 간단한 경우부터 매우 복잡한 경우까지를 다루고 있습니다. RTC 소스 제어의 다양한 기능을 활용해서 변경사항을 포워드 포팅하는 방법을 보여주고자 합니다.

경우1. 애플리케이션 특화된 변경사항이 없을 때 통합하기


로드된 개발용 저장소 작업공간에서, 플로우 대상을 벤더용 스트림으로 변경합니다. 벤더용 스트림으로 부터 베이스라인 수신을 허용합니다. 다시 플로우대상을 개발용 스트림으로 변경합니다. 새로운 릴리즈와 모두 잘 동작한다면, 개발용 스트림으로 베이스라인을 전달하여 팀원과 새로운 릴리즈를 공유합니다.

Accept baseline for new release
Markus는 벤더용 스트림으로부터 새로운 릴리즈(베이스라인 수신)을 허용합니다. Markus가 플로우 대상을 변경시 전제 저장소 작업공간의 플로우 대상 변경 대신 Sweet Reporter 콤포넌트의 플로우 대상만을 변경함을 주의하기 바랍니다.

Deliver Beta 2 release to development stream
Markus는 플로우 대상을 다시 JUnit으로 바꾸고, 새로운 릴리즈(베이스라인 송신)을 개발용 스트림으로 전달합니다.

경우2. 애플리케이션 특화된 변경사항이 있을 때 통합하기

당신은 애플리케이션에 특화된 변경사항을 살펴보고 더 이상 필요없는 변경사항을 결정합니다. 새로운 릴리즈에 포함된 버그 수정때문에 필요없는 변경사항이 있을 수 있습니다.
어떻게 통합할 지는 변경사항의 양에 따라, 새로운 릴리즈에도 변경된 같은 리소스인지, 더이상 필요없는 변경사항에 기초한 변경사항인지 등등에 달려있습니다. These are general issues that apply with any forward porting that has to happen. RTC Source Control provides features for helping you work through it. We will go through some of the situations that you might encounter and how you could work through them. It is strongly recommended that you read the articles on Multi-stream development (porting in particular) and Conflicts first.
경우2-1. 모든 애플리케이션 특화된 변경사항을 포팅해야 할 경우 - 겹치는 자원이 없을 때

Markus는 Sweet Reporter의 새 릴리즈에 몇몇 개선사항을 발견했지만, JUnit 팀이 관심있는 이슈는 해결되지 않았다는 것을 알았습니다. JUnit 팀이 변경한 모든 사항이 모두 필요합니다. 운좋게도, 새로운 Sweet Reporter 릴리즈의 변경 사항은 JUnit 팀이 변경한 사항들에 영향을 주지 않습니다. 보류 중인 변경사항 보기에서 어떤 잠재적인 충돌도 찾아볼 수 없습니다.

Markus는 개발용 저장소 작업공간을 로드합니다. 보류중인 변경사항 보기에서 Sweet Reporter 콤포넌트의 플로우 대상을 벤더용 스트림으로 변경합니다. 새로운 릴리즈에 대한 베이스라인이 수신 폴더에 나타납니다. 전송 폴더에는 JUnit 팀이 Sweet Reporter 콤포넌트에 가한 버그수정 변경사항이 나타납니다.

Accept baseline for new release
Markus는 저장소 작업공간으로 새로운 릴리즈를 수신하고 테스트를 마칩니다. Markus는 Sweet Reporter 콤포넌트의 플로우 대상을 개발용 스트림으로 변경합니다.

Deliver Beta 2 release to development stream
Markus는 개발용 스트림으로 새로운 릴리즈를 전달합니다. 이 스트림에는 새로운 릴리즈와 작업 항목 61에 대한 버그 수정을 포함하고 있습니다.
경우2-2. 모든 애플리케이션 특화된 변경사항을 포팅해야할 경우 - 몇몇 자원이 겹칠 때

Markus는 Sweet Reporter의 새로운 릴리즈에서 몇몇 개선사항을 발견했지만, JUnit 팀이 수정한 변경사항은 포함된 것이 없습니다. JUnit 팀이 가한 모든 변경 사항이 여전히 필요합니다. 새로운 릴리즈에서 수정한 몇몇 자원은 JUnit 팀이 버그 수정을 위해 수정한 자원과 같은 자원들입니다.
Potential conflicts accepting new release
Markus는 개발용 저장소 작업공간을 로드합니다. 보류중인 변경사항 보기에서 Sweet Reporter 콤포넌트의 플로우대상을 Sweet Reporter 벤더용 스트림으로 변경합니다. 새 릴리즈에 대한 베이스라인 수신이 나타납니다. 송신 폴더에는 JUnit팀이 Sweet Reporter 콤포넌트에 가한 수정 사항들이 나타납니다. 그는 Data와 ReportDefinition 파일에 잠재적인 충돌이 있음을 발견합니다.

Markus는 Sweet Reporter의 새 릴리즈에 팀에서 수정한 버그 수정 사항을 병합해야 합니다. Markus는 conflicts tutorial를 읽고 난후, JUnit 팀의 변경사항을 가장 잘 알고 있으므로, 역 병합(inverse merge)을 하기로 합니다. 즉 새로운 릴리즈에 JUnit 팀에서 만든 변경사항을 병합하고자 합니다.

Markus는 개발용 저장소 작업공간 상의 Sweet Reporter 콤포넌트를 Sweet Report 벤더용 스트림의 최신 내용으로 바꿉니다. 그리곤, Sweet Reporter 콤포넌트의 플로우 대상을 다시 개발용 스트림으로 변경합니다.
Accept fixes from development

Markus가 개발용 스트림으로 부터 버그 수정 사항들을 수신하고 나서,  충돌을 해결해야 합니다. 병합할 충돌있는 변경 사항은 JUnit 팀에서 변경한 것들입니다. 변경 사항들에 대해 이해를 하고(or 작업항목으로 부터 상세 내용을 파악하고) 제3자 코드로 변경 내역을 재작업합니다.
Resolve conflict with grouping support
충돌이 해결된 뒤에, Markus는 JUnit 애플리케이션을 빌드 및 테스트를 합니다. 새로운 릴리즈에 만족하면, 개발용 스트림으로 전달합니다.
Deliver new release + merges

경우2-3. 일부 애플리케이션 특화된 변경사항을 포팅해야 할 경우 - 몇몇 자원이 겹칠 때

Markus는 Sweet Reporter의 새 릴리즈에 중요한 개선사항이 포함되었다는 알게됩니다. 몇부분은 완전히 재작성되었던 겁니다. JUnit팀의 일부 이슈는 해결되었고, 해결되지 않는 것도 있습니다. JUnit 팀이 Sweet Reporter에 여러개의 버그 수정을 했는 데, 이번의 새로운 릴리즈로 인해 몇몇 변경사항만 포팅하면 됩니다.
New release causes conflicts
Markus는 conflicts tutorial와 multi-stream development guide에서 특히 포팅에 관련된 부분을 읽었습니다. 그는 역병합 방안과 필요한 변경 세트를 골라내는 방안에 대해 계획합니다. 변경 사항을 검사한 후 작업 항목 64 관련 변경 사항은 더 이상 필요없다고 결정합니다. 해당 문제는 새로운 릴리즈에서 해결되었습니다. 작업 항목 61 및 62 관련 변경 사항들은 새로운 릴리즈에 포함되지 않았습니다.

Markus는 개발용 저장소 작업공간 상의 Sweet Reporter 콤포넌트를 벤더용 스트림 상의 최신 내용으로 바꾼 후 Sweet Reporter의 콤포넌트의 플로우 대상을 다시 개발용 스트림으로 변경합니다.
Only 2 change sets are needed

지금까지는 이전 예제들과 같은 셋업입니다. 다른 점은 새 릴리즈에 모든 변경 세트를 다 포워드 포팅하지 않는 다는 점입니다.
Markus는 작업 항목 61 및 62 관련 버그 수정은 필요하고 작업 항목 64 관련 버그 수정은 필요하지 않습니다. 작업 항목 61 관련 버그 수정은 독립적입니다. 작업 항목 62 관련 버그 수정은 작업 항목 64 관련 버그 수정과 자원이 겹칩니다. 근본적으로 그에게 필요한 것은 작업 항목 64와 관련된 변경 세트를 버리는 것입니다. Markus는 FAQ에서 how to discard from a stream에 관해 일고 몇가지 선택이 있음을 알게됩니다.
선택1. Markus는 작업 항목 64와 관련된 변경 세트를 되돌리기를 하고 모든 변경 세트(61, 64, 62, "64:되돌리기")를 새로운 릴리즈에 병합할 수 있습니다. 아래와 같은 경우 가장 효과적입니다:
  • 다른 팀원들이 현 릴리즈의 또 다른 이슈를 해결하기 위해 현재 작업 중인데, 자원이 겹치며, 새 릴리즈와 버그 수정 사항을 통합할 가능성이 있음.
  • 작업 항목 64 관련 변경 세트에서 수정한 자원에 기초해 작성된 많은 변경 세트가 여전히 필요함.

이 작업을 위해선, Sweet Reporter 콤포넌트를 새로운 릴리즈로 바꾸기 전에, Markus는 변경 세트 64에 대한 되돌리기를 하고, 해당 패치를병합한 뒤에, 보류 중인 변경사항을 새 변경 세트로 체크인합니다. 이 변경 세트는 되돌리기 변경세트 입니다. Markus는 해당 변경 세트를 완료하지만, 개발용 스트림에 전달할 준비는 안된까닭에, 해당 변경 세트를 일시중단합니다. 그리고 나서, Sweet Report 콤포넌트를 새 릴리즈의 베이스라인으로 바꾸기를 합니다.
Accept incoming changes and reversal

Markus는 JUnit 팀이 작성한 모든 변경 세트(버그 수정)을 수신합니다. 그리고 되돌리기 변경 세트를 재개합니다. 새로운 릴리즈에 팀에서 작업한 변경사항을 병합하면서 충돌을 해결합니다. 결과에 만족하면, 새로운 릴리즈, 되돌리기 변경세트, 병합을 개발용 스트림으로 전달합니다.
Deliver new release, reversal and merges

선택2. Markus는 작업 항목 61 관련 변경 세트를 수신할 수 있습니다. 작업 항목 62와 관련된 변경 세트를 수신할 땐, (작업 항목 64와 관련된 변경 세트를 수신하지 않아서) 해당 변경 세트에 이르는 모든 변경 세트가 없는 까닭에 패치를 생성할 것인지 묻게 됩니다. 패치를 작업 공간으로 병합하고 변경 사항을 새로운 변경 세트로 체크인합니다. 다음과 같은 경우 가장 효과적입니다:
  • 팀에서 작성한 변경 사항의 대부분이 더이상 필요없음. Sweet Reporter의 새로운 릴리즈를 받을 때, 변경 사핟 없는 병합하기를 원치않음(변경사항이 없는 경우 자동 해결될 수도 있지만).

Replacing baseline in JUnit stream
Markus는 통합된 버그 수정을 포함한 릴리즈의 베이스라인으로 JUnit 개발용 스트림에서 바꾸기를 합니다. 팀 동료들에게 "전달 후에는 전송 폴더에 작업 항목 62 및 64가 나타날 수 있으며, Sweet Reporter 콤포넌트를 개발용 스트림의 최신내용으로 바꾸기를 하면 된다"고 알립니다. 선택2 끝. 


Answering the concerns about Vendor code

Back at the start we identified some concerns about making use of vendor code. In summary we will illustrate how the concerns are covered with the use of RTC Source Control features.

Know what version of the vendor code was used in a particular release of our application

The vendor code is isolated within a component in the development stream. When the release is declared and you create a snapshot of the development stream, the snapshot will contain a baseline for the vendor component. You can compare that baseline against the vendor baseline and see exactly what additional changes were made as well.

Make sure all our team mates are using the right version of the third-party code

The vendor code is in the development stream. All our team mates will see incoming changes from that stream when new releases are made available. They work with the vendor component in the same way as they work with the development components (except most will likely never have to deliver changes to it).

Be able to fix/extend the third-party code and manage those changes

Changes made to the third-party code are checked into change sets. The change sets can be tracked via work items, reviewed, etc. The original vendor code releases are tracked by baselines. We can easily compare a configuration to a baseline to determine the changes made.

Integrate newer releases of third-party code easily

RTC provides functionality that synchronizes with other SCM systems. It also provides a way to re-share resources with an existing component. Once the new third-party code release is in a workspace, you can test; run personal builds; etc. prior to sharing the release with your team. Integrating a new release can be as easy as accept, change flow target, deliver.

Integrate newer releases even when we have fixed/extended the earlier version of the third-party code.

The new releases of the third-party code added to RTC as a set of change sets that describe the delta between the releases. The result is we have a history of changes made to the third-party code. The application changes made are also recorded in change sets. This allows the merging, conflict resolution and patch creation to be done against third-party code, the same way as you would with application code. The third-party code is not treated as a second class citizen in Rational Team Concert.

댓글 없음:

댓글 쓰기