Magic of Love

팁 - 웹어플리케이션에 Subversion Revision과 Jenkins 빌드번호 보여주기 본문

Software

팁 - 웹어플리케이션에 Subversion Revision과 Jenkins 빌드번호 보여주기

NYA 2015.09.19 02:35

구글링하면 많이 나오는 내용을 조합하여 활용하기. 

예전에 만들었던건데 정리해서 올려봅니다.


예제 환경은 Subversion, Jenkins, Maven, Spring webmvc. 

(..이지만, 다른 도구를 쓰더라도 잘 조합하면 가능하겠죠..)



1. Jenkins Job 수정


이미 메이븐 빌드를 잘 하고 있는 Jenkins job 을 열어서 Goal 을 수정한다.

아마 Maven Goal 에는 clean install war:war 정도만 넣어서 쓰고 있겠지만 아래와 같이 -D 옵션을 넣는다.


clean install war:war -DBUILD_NUMBER=${BUILD_NUMBER} -DBUILD_ID=${BUILD_ID} -DSVN_REVISION=${SVN_REVISION}


Jenkins 에서는 빌드 시 여러 변수 값을 사용할 수 있다.

혹시나 하고 찾아보니, SVN 외에도 CVS, GIT 정보도 변수로 가져올 수 있다.

* Jenkins 위키 참고 : https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-JenkinsSetEnvironmentVariables



2. Maven 프로젝트의 pom.xml 수정


Jenkins 빌드 시 변수를 넘기도록 해두었으니, 이제 받은 변수를 MANIFEST 파일로 만들면 된다.

pom.xml 의 <build> <plugins> 에 있는 maven-war-plugin 설정에 manifestEntries 설정에 넣어주면 된다.

(넣는 김에 pom.xml에 정의된 해당 프로젝트 버전도 넣어봄)


<plugin>

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

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

<version>2.4</version>

<configuration>

<warName>${project.build.finalName}</warName>

<manifest>

     <addDefaultImplementationEntries>true</addDefaultImplementationEntries>

</manifest>

<archive>

<manifestEntries>

<Version>${project.version}</Version>

<Build-Number>${env.BUILD_NUMBER}</Build-Number>

<Build-Id>${env.BUILD_ID}</Build-Id>

<Svn-Revision>${env.SVN_REVISION}</Svn-Revision>

</manifestEntries>

</archive>

</configuration>

</plugin>



3. MANIFEST 파일을 읽는 기능 만들기 


MANIFEST 파일은 war 안에 묶여있을 수 있으므로 File 이 아닌 Resource 의 InputStream 으로 읽으면 된다. 


아래는 Spring bean 의 Service 로 작성해본 내용이다. (Resource 도 spring 쪽 클래스임에 주의)


WAS가 시작되어서 아래 서비스 Bean 객체가 생성되면 readManifestData() 메서드가 호출되어 MANIFEST.MF 파일의 내용을 읽는다. 여기에 쓴 MANIFEST 항목들은 Maven 빌드 시 추가되며, 특히 아래 3개 항목은 Jenkins 빌드 시 넘어가는 변수이므로 로컬 빌드 시에는 해당 값이 없다.


import java.io.IOException;

import java.util.jar.Attributes;

import java.util.jar.Manifest;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.core.io.Resource;

import org.springframework.stereotype.Service;


@Service(value = "manifestReadSVC")

public class ManifestReadSVC {

private static final Log LOG = LogFactory.getLog(ManifestReadSVC.class);


private String version = null; // null 인 경우 manifest 파일을 찾을 수 없음

private String buildNumber = null; // null 인 경우 local build

private String buildId = null; // null 인 경우 local build

private String svnRevision = null; // null 인 경우 local build


@Value("classpath:../../META-INF/MANIFEST.MF")

private Resource manifestResource;


@PostConstruct

public void readManifestData() {

try {

Manifest manifest = new Manifest(manifestResource.getInputStream());

Attributes attributes = manifest.getMainAttributes();

version = attributes.getValue("Version");

buildNumber = attributes.getValue("Build-Number");

buildId = attributes.getValue("Build-Id");

svnRevision = attributes.getValue("Svn-Revision");

LOG.debug("* Manifest : Version=" + version + ", Build-Number=" + buildNumber + ", Build-Id=" + buildId + ", Svn-Revision=" + svnRevision);

} catch (IOException e) {

LOG.debug("* Cannot read manifest file.");

}

}


public String getVersion() {

return version;

}

public String getBuildNumber() {

return buildNumber;

}

public String getBuildId() {

return buildId;

}

public String getSvnRevision() {

return svnRevision;

}

}



4. 화면에 보여주기


1) 컨트롤러

@Controller

@RequestMapping("/")

public class PageController {


@Resource(name = "manifestReadSVC")

ManifestReadSVC manifestReadSVC;


@RequestMapping(value = "/", method = RequestMethod.GET)

public String home(HttpServletRequest request, Model model) {


// set version (request)
request.setAttribute("version", manifestReadSVC.getVersion());
if (manifestReadSVC.getBuildNumber() != null) {
request.setAttribute("buildNumber", manifestReadSVC.getBuildNumber());
request.setAttribute("buildId", manifestReadSVC.getBuildId());
request.setAttribute("svnRevision", manifestReadSVC.getSvnRevision());
}

return "home";
}
}


2) JSP

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<div id="buildNumber" title="${buildId}">

<c:if test="${buildNumber != null && buildNumber != ''}">

Build Number : ${buildNumber} <br/>

Revision : ${svnRevision}<br/>

</c:if>

<c:if test="${buildNumber == null || buildNumber == ''}">

** Local Build **

</c:if>

</div>




끝!


0 Comments
댓글쓰기 폼