블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 

'빌드 자동화'에 해당되는 글 3

  1. 2018.03.01 gitHub와 Jenkins 연결하기
  2. 2013.04.15 maven으로 환경별도 다르게 패키징 하기 & RPM 패키징 #2/2 (1)
  3. 2008.02.12 빌드 자동화 업체
 

Jenkins와 gitHub 연동


조대협 (http://bcho.tistory.com)


가장 널리 사용하는 Jenkins와, 소스 코드 리포지토리 서비스인 GitHub를 연동하는 방법에 대해서 알아본다. 시나리오는 gitHub에 코드를 푸쉬하면 Jenkins가 이를 인지해서 자동으로 코드를 내려 받아서 빌드 스크립트를 실행하는 순서로 한다.


GitHub에서 Credential 생성


gitHub 자신의 계정으로 로그인 한 후 우측 상단의 자신의 사진이 있는 아이콘을 누르면 메뉴가 나오는데, 여기서 Setting > Developer settings 메뉴로 들어간 후에 아래와 같이 Personal access tokens 메뉴로 들어간다.

다음 우측 상단의 Generate new token 메뉴를 선택한다.



다음 토큰으로, 접근할 수 있는 범위를 설정한다. 접근 범위는 “repo”와 “admin:repo_hook” 을 선택한다.




선택이 끝나고 토큰을 생성하면 문자열로 된 토큰이 생성된다.


Jenkins에서 GitHub 연결 설정

앞에서 생성된 토큰을 Jenkin의 GitHub 연결 부분에 설정하도록 하겠다.

Jenkins 초기화면에서 Jenkins > Manage Jenkins > Configure System 메뉴로 들어가면 GitHub 계정을 설정하는 부분이 있다.



Name은 이 GitHub 연결 설정을 구별할 이름으로 정의하고 API URL은 default로 https://api.github.com 으로 설정되어 있는데 default 값을 사용한다.

다음 접속 credential을 설정해야 하는데, credentials 부분에서 Add 버튼을 눌러서 Credential 설정 메뉴를 실행한다.




위와 같은 메뉴가 나오면 Kind는 “Secret text”를 선택하고 Secret 에 앞에 gitHub에서 생성한 키를 입력한다. ID에는 본인 gitHub ID를 입력한다.  Credential 입력이 끝나면,  아래 그림과 같이 Credentials 메뉴 아래에 Test Connection 버튼이 있는데, 이 버튼을 눌러서 제대로 github와 연결이 되는지를 테스트 한다.




Jenkins 프로젝트 생성 및 설정

Jenkins와 gitHub 연결 설정이 끝났으면, Jenkins에서 프로젝트를 생성한다.

Git 연결 설정

프로젝트 설정에서 아래와 같이 Git 메뉴로 이동한다.



여기서 Repository URL을 입력한다. Repository URL은 본인 gitHub Repository에서 우측 상단의 녹색 “Clone or download” 버튼을 누르면 HTTPS 로 된 URL이 나온다. 이 URL을 입력하면 된다.



다음 이 repository에 연결할 연결 정보를 입력해야 하는데, Jenkins에서 credentials 메뉴로 들어간다.

이 메뉴에서 Kind를 “Username with password” 를 선택하고 Username에는 본인의 github id, Password에는 github 비밀번호를 입력한다.



빌드 트리거 설정

다음 어떤 조건에서 Jenkins 빌드를 실행할지를 설정하는데, GitHub에 코드가 푸쉬되면 빌드를 트리거링 하도록 설정을 할것이다. 아래 그림과 같이 Build Triggers 메뉴에서 GitHub hook trigger for GitScm Polling을 선택한다.




이렇게 설정하면 GitHub에서 코드 푸쉬가 될때 webHook 메세지를 Jenkins에 보내주는데, 이 WebHook 메세지를 받을 때마다 빌드를 하게 된다.


GitHub에서 WebHook 설정

Jenkins 가 GitHub 에서 보내는 WebHook에 의해서 Triggering이 되도록 설정했으면, 이제 GitHub에서 코드가 푸쉬 될때 마다 WebHook을 Jenkins에 보내도록 설정해야 한다.




GitHub Repository로 들어가면 우측 상단에 Settings라는 메뉴가 있다.

이 메뉴에 들어가서 좌즉에 Integration & Service 라는 메뉴를 선택한다.


Services 메뉴에서 “Add service” 버튼을 클릭한 후에 “Jenkins (GitHub plugin)” 을 선택한다.



다음 플러그인 설정에 Jenkins hook url에 Jenkins가 WebHook을 받을 HTTP 경로를 입력한다.

일반적으로 http://{Jenkins server의 URL}/github-webhook 이 된다.




이제 모든 설정이 끝났다.

제대로 작동하는 것을 확인하기 위해서 코드를 commit 한 후에 Push를 해보면 빌드가 자동으로 진행이 된다.

Jenkins의 해당 project에서 좌측의 “GitHub Hook Log”를 보면 WebHook을 잘 받았는지 확인이 가능하다. 아래는 실제로 WebHook이 발생한 내용을 확인한 화면이다.




Plug in 을 통한 maven 빌드 확장


앞글에서 http://bcho.tistory.com/739 maven을 이용한 가장 기본적인 빌드 시나리오에 대해서 살펴보았다.

maven plug in이라는 기능을 통해서, 여러 기능 들을 추가로 빌드 프로세스내에 추가할 수 있는데, 여기서는 빌드에서 확장하여, 배포 환경 별로 패키징 하는 시나리오를 추가해보기로 한다.

 

다음과 같은 시나리오를 생각해보자, 빌드에 의해서 생성된 웹 애플리케이션은 내 local PC에서도 돌아가야 하며, 다른 개발자와 협업하는 서버의 개발환경에서도 돌아야 하고, 개발 주기마다 주기적으로 QA환경에서 테스트를 받은 후, staging 환경을 거쳐서 최종적으로 production 환경에 배포 되어야 한다고 가정하자.

 

Java Version 지정하기

먼저 대상 환경에 맞는 컴파일 run time시에 소스 코드에 대한 java 버전과, target compiler java 버전을 지정할 있다. 아주 기본적인 내용인것 같지만, 실제 빌드 과정에서 java 버전을 명시적으로 지정하지 않아서 run time등에서 문제가 생기는 경우가 의외로 많다. 예를 들어 runtime jvm 버전이 1.5인데, 최신 버전으로만 컴파일을 하는 것을 정책으로 잡아놓고 1.7로만 컴파일이 되게 하면, 빌드 스크립트에 의해서 컴파일된 바이너리는 run time에서 작동하지 않는다.

 

             <!--  compiler plug in -->

             <plugin>

                <artifactId>maven-compiler-plugin</artifactId>

                       <version>3.0</version>

                <configuration>

                    <source>1.5</source>

                    <target>1.5</target>

                </configuration>

              </plugin>

 

개발환경 별로 컴파일 하기

이를 지원하는 배포 프로세스는 뒤에서 다시 설명하기로 하고, 여기서는 이러한 다중 환경을 지원하기 위해서 같은 소스 코드로 어떻게 다르게 packaging을 할 것인가에 대해서 고민해보자, 각 환경이 다르면, dbms를 접근하기 위한 db url, id,password도 다를 것이며, 기타 디렉토리 구조나, 다른 서버의 ip등이 모두 다를 것이다.

즉 배포 target에 따라서 다른 빌드 프로세스를 타야 한다는 것이다.

 


이를 maven에서는 profile이라는 것으로 지원할 수 있다.

지금 소개하는 Sample 시나리오는 이러한 설정 정보를 WEB-INF/config/config.properties에 정의했다고 하고, 빌드 target에 따라 각각 다른 config.properties 파일을 패키징 하는 시나리오이다.

각각 다른 환경의 config 파일을 저장하기 위해서 ${basedir} 아래에 다음과 같은 이름으로 디렉토리를 만든다.

 

${basedir}/resource-local     : PC 용 설정 정보

${basedir}/resource-dev               : 공용 개발 서버용 설정 정보

${basedir}/resource-qa        : QA 환경용 설정 정보

${basedir}/resource-stage     : Staging 환경용 설정 정보

그리고 각 디렉토리 아래 WEB-INF/config/config.property를 각 환경에 맞게 정의한다.
다음 예제는 dev 환경용 설정 파일이다.

mybatis.jdbc.driverclass=com.mysql.jdbc.Driver

mybatis.jdbc.url=jdbc:mysql://localhost:3306/development

mybatis.jdbc.username=developer

mybatis.jdbc.password=developer

 

s3.url=developer_s3

이렇게 설정한 디렉토리는 다음과 같은 구조를 가지게 된다.

 


 

다음으로, maven pom.xml에서 환경에 맞게 위에 지정한 파일들을 포함해서 패키징 하게 해야 한다. 이를 maven에서는 profile이라고 하고, 다음과 같이 정의한다. 각 빌드 환경마다 여기서는 <environment> 라는 환경 변수를 지정하게 하였다.

<!--  profile definition -->

    <profiles>

        <profile>

               <id>local</id>

               <properties>

                       <environment>local</environment>

               </properties>

        </profile>

        <profile>

               <id>dev</id>

               <properties>

                       <environment>dev</environment>

               </properties>

        </profile>

        <profile>

               <id>qa</id>

               <properties>

                       <environment>qa</environment>

               </properties>

        </profile>

        <profile>

               <id>stage</id>

               <properties>

                       <environment>stage</environment>

               </properties>

        </profile>

  </profiles>

 

그리고 빌드시 ${basedir}/resource-{environment} 디렉토리를  webapp/ 아래에 복사하도록 하고자 한다. 이를 위해서는 war를 패키징 하는 war 플러그인의 속성세 web-resource (WEB-INF 디렉토리)를 빌드 타겟에 맞게 선택이 되도록 다음과 같이 지정한다.

환경에 맞게 정의한다.
다음 예제는 dev 환경용 설정 파일이다.

             <!--  war plug in  -->

             <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                       <artifactId>maven-war-plugin</artifactId>

                       <version>2.3</version>

                       <configuration>

                               <warSourceDirectory>${basedir}/src/main/webapp</warSourceDirectory>

                              <webResources>

                                      <webResource>

                                                     <directory>${basedir}/src/main/resources-${environment}</directory>

                                      </webResource>

                              </webResources>

                       </configuration>

               </plugin>

 

여기 까지 진행한 후에, 각 환경에 맞게 packaging을 하기 위해서는 mvn에서 -P{environment} 이름을 적어주면 된다.

예를 들어 qa환경용으로 war 파일을 만들기 위해서는

 

% mvn -Pqa package

 

와 같이 명령을 실행하면 된다.

 

RPM으로 패키징 및 배포 하기

maven의 빌드 패키징의 문제가 java에 관련된 jar, ear 또는 war 파일만 딱 생성하고 패키징을 한다. 그러나 서버를 배포하기 위해서는 이런 jar형태의 파일 뿐만 아니라 애플리케이션 들이 참고하는 각종 설정 파일들을 함께 배포해야 할 필요가 있다. 운이 좋게 모든 파일들이 jar,ear,war등에 함께 패키징 되면 좋겠지만, 애플리케이션이 어느정도 규모가 되면 함께 패키징이 되지 않는 파일들이 발생한다.

이런 문제를 해결하기 좋은 방법으로는 linux에서 제공하는 rpm 패키징을 이용하는 방법이 있다.

maven에서는 이 rpm 패키징을 플러그인으로 제공한다.

(http://mojo.codehaus.org/rpm-maven-plugin/ )

사용법도 상당히 간단하기 때문에 추천한다. 플러그인은 linux 명령어인 rpmbuild 내부적으로 수행하기 때문에, 반드시 windows 아닌 linux machine에서만 사용이 가능하다.

 

rpm package 여러가지 기능을 수행할 있지만, 여기서 설명하는 것은 기본적으로 file copy 이다.

 

              <!--  rpm plug in -->

              <plugin>

                <groupId>org.codehaus.mojo</groupId>

                <artifactId>rpm-maven-plugin</artifactId>

                <version>2.0-beta-2</version>

                <configuration>

                        <copyright>2013 - Terry Cho</copyright>

                        <group>terry/example</group>

                        <mappings>

                        <mapping>

                               <directoryIncluded>false</directoryIncluded>

                                 <directory>${rpm.install.webapps}</directory>

                                <username>bwcho</username>

                                <groupname>bwcho</groupname>                            

                                 <sources>

                                         <source>

                                                 <location>${basedir}/target/${artifactId}.war</location>

                                         </source>

                                 </sources>

                        </mapping>

                        </mappings>

                    </configuration>

              </plugin>

 

설정을 제공하는 <configuration> 부분을 보자

rpm 패키지에 대한 관리를 위해서 rpm 그룹핑을 제공하는데, <group> rpm 패키지의 그룹을 정의한다. group 여러개의 컴포넌트를 함께 배포할때 매우 유용하게 사용될 있다. 예를 들어 비디오 인코딩 애플리케이션이 있고, 애플리케이션이 upload, download,encoding 컴포넌트 3개로 구성되어 있고, 각각 배포 되어야 한다면 그룹명을 videoencoding/upload, videoencoding/download, videoencoding/encoding 등으로 지정하여 구별할 있다.

다음으로 <mappings> 엘리먼트에서는 복사할 파일 리스트를 지정할 있다. 하위 엘리먼트로 <mapping>이라는 엘리먼트에서 개개별의 디렉토리나 파일을 지정하면 된다.

<sources><source> 엘리먼트에서 복사할 원본 파일 리스트를 지정하고,

<directory> 엘리먼트에서 복사될 타겟 디렉토리를 지정한다.

그리고 <username> <groupname> 파일이 복사될때 (생성되는 파일의) user id group (unix) 정의한다.

위의 예제는 war 파일을 ${rpm.install.webapps} 복사하는 rpm 파일을 생성하는 스크립트이다.

이렇게 생성된 스크립트는

 

% mvn package rpm:rpm  으로 수행될 있다.

앞서 설명한, profile 함께 사용하면, dev rpm 패키지 생성은

% man -Pdev package rpm:rpm

으로 하면된다.

 

이렇게 생성된 rpm 파일들은 대상 시스템으로 복사되서 rpm 수행하는 것만으로도, 모든 의존성을 가진 파일들을 함께 설치할 있다.

아울러 rpm 가지고 있는 고유한 기능으로, 특정 버전으로의 roll back등이 가능하다.

rpm 파일들을 대상 시스템으로 자동으로 복사 실행 하는 부분에 대해서는 뒤에서 다시 살펴 보도록 하자

빌드 자동화 업체

ALM/Build Automation (빌드 자동화) | 2008.02.12 14:25 | Posted by 조대협
Clover,JiRA, CI 툴등. 이런거 수입해서 국내에서 팔았으면 좋겠다 생각했는데..
벌써 하는 업체가 있었네.. 반갑기도 하고.. ^^
역시 사람들 빠르다는 생각도 들고...

마침 업체가 최종명 선배가 있는 업체기도 해서 기술에 신뢰도 간다...
기회가 되면 프로젝트 초반에 같이 한번 일해보고 싶은 업체.

Architecture Group http://www.arctgroup.com
555-4847