버전관리 시스템 연동은 이슈 관리 시스템의 가장 유용하고 중요한 기능중 하나이다.


먼저 왜 이 기능이 유용한지 알아보자.

전 절의 프로젝트 관리 항목에서 버전 관리 시스템과 연결하기 위한 저장소 설정을 마쳤으니 실제로 버전 관리 시스템과 연동해 보자. 기본 연동 방식은 레드마인이 정해진 시간마다 저장소에 연결하여 커밋 내역을 가져오는 방식으로 동작하고 있으며 이는 커맨드에서 다음 명령어를 실행한 것과 동일하다.


./script/rails runner "Repository.fetch_changesets" -e production


커밋 내역을 가져온 후에는 커밋 메시지에 사전에 정의한 키워드가 있으면 이슈와 연결하거나 이슈의 상태를 변경한다.

다음은 "25번 이슈를 해결됨으로 상태를 변경하고 21 번 이슈와 연결하는 커밋 메시지로 fixed 와 refs 는 "관리" -> "설정" ->"저장소" 에서 설정한 키워드들이다.

"fixed #25, 관련 내용은 refs #21 참고"

테스트 프로젝트 생성

레드마인과 버전 관리 시스템을 연동해 보기 위해 버전 관리 시스템에 추가할 예제 프로젝트를 생성해 보자. 예로 프로젝트는 간단한 웹 개발 프로젝트이며 템플릿에서 프로젝트를 만들 수 있는 메이븐 아키타입을 사용할 것이니 메이븐이 설치되어 있어야 한다.

mvn archetype:generate -B -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.example -DartifactId=hello-webapp -Dversion=1.0

정상적으로 종료되었다면 hello-webapp 라는 디렉터리가 생성되었을 것이다. 이제 이 디렉토리를 버전 관리 시스템에 임포트 해 보자. 

 

서브버전에 추가

서브 버전 저장소 구조의 모범 사례에 따라 다음 구조로 프로젝트를 만들어 보자. 프로젝트의 트렁크 URL 은 http://svn.example.com/hello-webapp/trunk 이다.

- hello-webapp
	- branches
	- tags
	- trunk
		pom.xml
		src

먼저 hello-webapp 디렉터리로 이동하자. 그리고 svn 명령어를 이용하여 원격지에 디렉터리를 만들어 보자. 다음 명령어로 svn mkdir 명령어를 여러 번 치지 않고 기본 디렉터리 구조를 만들수 있다.

--parents 는 부모 디렉터리가 없을 경우 생성하는 옵션이고 {trunk,tags, branches} 는 bash 항목에서 설명한 특수 기능인 brace expansion 기능을 사용한 것이다.

svn mkdir --parents  https://svn.example.com/repos/hello-webapp/{trunk,tags,branches} -m "프로젝트 디렉터리 생성"

정상적으로 동작했다면 프로젝트 디렉터리 구성은 끝났으니 trunk 에 소스를 임포트 해 보자. 

svn import . https://svn.example.com/repos/hello-webapp/trunk -m "first commit"

이제 서브버전에서 프로젝트 설정이 끝났다. 다음은 gitlab 사용자 설정을 알아 보자.

gitlab 에 추가

git 은 gitlab 을 사용한다고 가정하고 진행해 보자. 먼저 gitlab 에서 "New Project" 를 클릭하여 "hello-webapp" 프로젝트를 생성하면 아래와 같이 git 으로 저장소를 만드는 방법에 대해서 표시된다.

아직 git 저장소를 만들지 않았으니 "Create Repository" 에서 있는 절차를 따라하면 된다.

cd hello-webapp
git init
git add pom.xml src
git commit -m "first commit"
git remote add origin git@gitlab.example.com:lesstif/hello-webapp.git
git push -u origin master


서브버전과 git 프로젝트가 생성 및 설정이 완료되었으니 레드마인과 저장소를 연결하기 위한 이슈를 하나 등록해 보자.


pom.xml 에 등록된 junit 은 버전 3으로 버전 4가 더 사용이 편리하므로 "junit 4.x 로 업그레이드"  이슈를 하나 등록하고 부여된 이슈 번호를 잘 기억해 두자. (예제에서는 15번 이슈라고 하겠다)

이제 프로젝트의 pom.xml 을 열어서 junit 의 버전 항목을 3.8.1에서 4.11 로 변경해 보자.

서브 버전과 연계

이제 중앙 저장소에 커밋할 때 다음과 같이 커밋 메시지를 입력하면 레드마인에서 저장소의 커밋 내역을 분석하여 이슈와 연결해 준다.

svn ci -m "fixed #18 junit4 upgrade"

어느 정도 시간이 흐른후에 15번 이슈의 상세 보기를 하면 다음과 같이 이슈가 연결된 것을 확인할 수 있으며 링크를 클릭하면 해당 이슈와 관련된 변경 소스를 볼 수 있으므로 이슈 관점에서 소스의 변경 내역을 파악할 수 있다.

 

서브버전 훅과 연계

레드마인은 커밋 메시지를 통해 이슈와 버전 관리를 연계하므로 커밋 메시지 정책은 매우 중요하며 개발자가 실수로 커밋 메시지에 이슈 번호를 누락하지 않도록 전 장의 서브버전 항목에서 설명한 pre-commit 훅을 설치하면 정책으로 관리할 수 있으니 필요에 따라 반영하면 된다.

 

하지만 레드마인은 정해진 시간마다 서브버전 저장소에 연결하여 커밋 내역을 가져오므로 커밋된 내역을 바로 확인할 수 없는 단점이 있다.

 

 

이 문제를 레드마인의 REST API 와 서브버전의 post-commit 훅을 이용하여 커밋후 바로 확인이 가능하도록 설정해 보자.

먼저  "11.3.2.8 저장소" 부분에 언급한 "관리"-> "설정" -> "저장소" 메뉴에서  "저장소 관리에 WS를 사용" 을 체크하고 "API 키" 를 생성해 두어야 한다.

 

WS 를 사용하도록 설정했다면 레드마인에 저장소 관련 API URL(https://redmine.example.com/sys/fetch_changesets) 이 생성되며 이 URL 을 api key 와 같이 호출하면 레드마인이 저장소에 연결하여 커밋 내역을 가져오게 된다.

동작 확인을 위해 핵심 유틸리티에서 설명한 curl 명령어를 사용해 보자.

다음 명령어는 레드마인이 저장소에 연결하여 커밋 내역을 가져가도록 API 호출하는 예제이다. -w "%{http_code}\n"  은 HTTP 의 응답 코드만 출력하는 옵션이다. 예제처럼 응답 코드로 200 이 오면 정상 호출된 것이며 403 이 떨어지면 API 접근이 거부된 것이므로 api 키가 맞는지 확인해 보자. 404 일 경우 "저장소 관리에 WS를 사용" 이 체크되지 않거나 URL 이 잘못된 것이다.

curl -w "%{http_code}\n" -L -k https://redmine.example.com/sys/fetch_changesets?key=OuitU7kCFmBcLktY9mZZ

200

레드마인쪽 로그는 log/production.log 파일에서 다음과 같이 API 의 정상 호출을 확인할 수 있다.

Started GET "/sys/fetch_changesets?key=OuitU7kCFmBcLktY9mZZ" for 127.0.0.1 at 2014-10-06 00:17:55 +0900
Processing by SysController#fetch_changesets as */*
Parameters: {"key"=>"OuitU7kCFmBcLktY9mZZ"}
Rendered text template (0.0ms)
Completed 200 OK in 379.9ms (Views: 0.6ms | ActiveRecord: 2.0ms)

 

이제 정상 동작을 확인했다면 서브 버전에 post-commit 훅을 설치하고 위 curl 명령어를 넣으면 된다. 다음 절차에 따라 수행하자. 

  1. 서브버전 서버의 저장소에서 hooks 폴더로 이동한다.
  2. 선호하는 에디터로 post-commit 파일을 연다.
  3. 다음 내용을 추가한다. URL과 key 는 독자의 환경에 따라 다를 수 있다.

    #!/bin/sh
     
    curl -L -k https://redmine.example.com/sys/fetch_changesets?key=OuitU7kCFmBcLktY9mZZ
    CODE
  4. 저장한 후에 실행 가능하게 실행 속성을 부여한다.

    chmod +x post-commit

  5. 정상적으로 동작하는지 명령행에서 실행해 본다.

    ./post-commit

  6. SELinux 는 아파치 httpd 를 엄격하게 통제하므로 정해진 포트만 사용 가능하며 외부 네트워크에는 연결할 수 없다. 서브버전이 아파치에서 구동되므로 post-commit 훅도 아파치의 권한으로 실행되며 SELinux 의 정책에 의해 네트워크를 사용하는 명령어인 curl은 네트워크에 접근이 차단된다. 이로 인해 명령행에서는 잘 동작하는 훅 스크립트가 아파치에서는 동작하지 않으므로 SELinux boolean 설정을 변경하여 아파치가 네트워크에 연결할 수 있도록 수정하자.

    setsebool -P httpd_can_network_connect 1

  7. 서브버전 커밋을 실행하여 커밋하면 바로 레드마인에서 보이는지 확인해 보자.

 

이제 서브버전과 레드마인의 모든 연계가 끝났으니 개발과 이슈 관리를 통합하여 관리하고 확인할 수 있다. 이제 레드마인과 git 과의 연계를 알아 보자.

git 과 연계

레드마인의 git 연계는 ssh 나 http/https 를 지원하지 않으므로 서브버전보다는 설정이 번거로운 편이며 연계용 git 저장소를 별도로 만들고 주기적으로 cron 명령어로 git fetch 를 하는 방법으로 설정해야 한다.

 

다음 절차에 따라 git 연계용 저장소를 만들어 보자. 저장소의 위치는 전 절 프로젝트 관리에서 "설정" -> "저장소" 에 설정한 경로인 /var/redmine/git-repos/hello-webapp 라고 가정한다.

  1. /var/redmine/git-repos 디렉터리를 생성한다. (사전에 /var/redmine 이 생성되어 있고 소유자가 redmine 이어야 한다. 안 되어 있다면 /var/redmine 생성 작업은 루트로 실행해야 하므로 sudo 명령어로 실행하자.)

    mkdir /var/redmine/git-repos

    cd /var/redmine/git-repos

  2. git fetch 명령시 암호를 입력하지 않아도 되도록 레드마인 계정에 gitlab 에 등록한 공개키(id_rsa.pub)와 개인키(id_rsa)를 복사한다. 키가 윈도 시스템에 있다면 scp 클라이언트로 레드마인을 구동하는 서버의 레드마인 홈 디렉터리의 .ssh 디렉터리에 복사해 주자. 복사된 키는 .ssh/id_rsa 와 .ssh/id_rsa.pub 이어야 한다.

  3. 개인키는 소유자만 읽을 수 있도록 설정 되어 있어야 ssh 클라이언트가 에러를 발생시키지 않으므로 chmod 로 변경해 주어야 한다.

    chmod 600 ~/.ssh/id_rsa

  4. 연계용 저장소는 bare 저장소이어야 하므로 --mirror 옵션을 주고 복제해야 하며 원격 저장소의 URL 은 독자의 환경에 따라 다를수 있으니 환경에 맞게 수정하자. 정상적으로 SSH 개인키가 설정되었다면 저장소가 복제될 것이며 git 계정의 암호를 묻는 프롬프트가 뜬 다면 2, 3번을 다시 한 번 확인해 보자.

    git clone --mirror git@gitlab.example.com:lesstif/hello-webapp.git

  5. 저장소의 모든 브랜치를 가져 온다.

    git fetch -q --all -p

로컬 git 저장소 설정이 끝났으니 이제 주기적으로 중앙 저장소에서 로컬 git 저장소로 변경 내역을 가져오도록 해야 한다. 일정 시간 주기로 가져오게 하려면 crontab 과 연결하는게 효과적이다;

crontab -e 로 redmine 계정의 크론 스케줄러를 열고 다음 내용을 입력해 보자.

*/5 * * * * /home/redmine/git-fetch.sh

위 설정은 5분마다 git-fetch.sh 스트립트를 실행하는 설정으로 독자들의 환경에 따라 실행 주기를 더 줄이거나 늘려 보자. 

이제 레드마인의 홈 디렉터리에 git-fetch.sh 라는 스크립트를 만들고 다음 내용을 입력하자. .

#!/bin/sh

cd /var/redmine/git-repos/hello-webapp.git
git fetch -q --all -p
cd ~/redmine
./script/rails runner "Repository.fetch_changesets" -e production

스크립트의 내용은 로컬 저장소로 이동하여 중앙 저장소의 모든 브랜치의 변경 내역을 가져온 후에 레드마인이 저장소를 인덱싱하는 명령어이다.

이제 chmod +x git-fetch.sh 를 실행 가능하게 만들면 git 쪽 작업은 모두 마쳤다.

이제 레드마인을 설정할 차례이므로 hello-webapp 프로젝트로 들어가서 "설정" -> "저장소" 의 git 저장소를 "11.5.6 저장소"  항목대로 설정했는지 확인해 보자.

이제 설정이 끝났다면 소스를 커밋해서 확인할 차례이다. /var/redmine/git-repos/hello-webapp 는 읽기 전용이므로 여기에서 소스를 수정하지 말고 원래 소스를 체크아웃 받은 디렉터리에서 커밋해야 한다.

커밋 메시지는 다음과 같이 레드마인 이슈 번호를 포함시키고 커밋후에는 중앙 저장소에 푸시하자.

git add pom.xml
git commit -m "fixed #18 junit4 upgrade"
git push origin master 

정상적으로 푸시까지 끝났다면 5분이 지나면 레드마인에 이슈 상세 보기에서 "관련된 개정판" 항목에 커밋 내역이 보일 것이다.

 

이슈별이 아닌 전체 이력을 보고 싶다면 "저장소" 메뉴를 클릭하면 이력 목록을 확인할 수 있다.