04 3月 2013

buildnumber-maven-plugin

專案開始進入測試階段時,每次提供給測試人員或客戶測試時,若有問題要回報時,我比較希望除了問題的描述之外,還能有目前測試的版本版次的資訊,因為用不同的版本,不一定能測出相同的問題。
當然每次release時加上tag是個好習慣,但在專案後半期會大量進行build->testing的循環,每次build都要加上tag可能不是很容易。
所以我們簡單一點想,如果在build完產生的war或jar這類的檔案,能自行包含這些資訊是不是比較好些?

buildnumber-maven-plugin提供了三個變數讓我們取得這些資訊

  • buildNumber : repository的版本,SVN就是目前的版本,像是22013,而Git就是Head的revision.
  • scmBranch : repository的Branch名稱,SVN的值會像是brunch/developer,而Git則不支援,會顯示UNKNOWN
  • timestamp : 此次Build的時間

我們可以在pom.xml中利用上列三個變數,加諸在檔名或是MANIFEST.MF中,以便識別這個檔案的相關版本資料。
再來就簡單示範如何使用這個plugin

首先一定要加入scm的設定,讓plugin辨別是要怎麼讀取Buildnumber與Branch.

<scm>
	<connection>scm:git:git://github.com/ElliotChen/buildDemo.git</connection>
</scm>

第二步就是加入buildnumber-maven-plugin,並要求在validate這個phase時執行create這個command,也就是在validate這個phase之後,我們就可以使用上列三個變數了。

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>buildnumber-maven-plugin</artifactId>
	<version>1.2</version>
	<executions>
		<execution>
			<phase>validate</phase>
			<goals>
				<goal>create</goal>
			</goals>
		</execution>
	</executions>
</plugin>


再來可以在MANIFEST.MF中加入相關的資訊,下面是在war檔案裡加入相關資訊的方法。

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-war-plugin</artifactId>
	<version>2.3</version>
	<configuration>
		<archive>
			<manifestEntries>
				<buildNumber>${buildNumber}</buildNumber>
				<branch>${scmBranch}</branch>
				<buildTime>${timestamp}</buildTime>
			</manifestEntries>
		</archive>
	</configuration>
</plugin>

這樣輸出的MANIFEST.MF中就會有包含有下列的資訊

buildTime: 1362382356069
branch: UNKNOWN
buildNumber: 7b9aa85d

這樣可能還不夠,因為包在war檔裡沒人看得見,所以系統裡應該有個簡單的讀取MANIFEST.MF的功能,然後以JSP,或是其他方式做為顯示的媒介。
提供一個簡單的Servlet給大家參考

public class SystemInfoServlet extends HttpServlet {
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		HashMap<Object, Object> map = new HashMap<Object, Object>();
		ServletContext application = getServletConfig().getServletContext();

		Manifest manifest = new Manifest(application.getResourceAsStream("/META-INF/MANIFEST.MF"));
		Attributes attr = manifest.getMainAttributes();
		for (Object key : attr.keySet()) {
			map.put(key, attr.get(key));
		}

		request.setAttribute("infoMap", map);
		request.getRequestDispatcher("/SystemInfo.jsp").forward(request,response);
	}
}

JSP裡只要用下列的程式就能呈現MANIFEST.MF資料

<body>
	<c:forEach items="${infoMap}" var="info">
		${info.key} : ${info.value} <br/>
	</c:forEach>
</body>

另外,若是在Eclipse中有安裝Maven Plugin,那它會在每次pom.xml修改時自動產生MANIFEST.MF,但是因為沒有執行validate的關係,所以上列三項參數不會正常顯示在MANIFEST.MF裡;但是在Build完成時是會正確崁入war檔裡的,所以如果看到Eclipse Project中的MANIFEST.MF與你想像不同時,別擔心,這是正常的。