programing

Java 프로젝트용 빌드 및 버전 번호 부여(ant, cvs, hudson)

bestcode 2023. 1. 12. 22:13
반응형

Java 프로젝트용 빌드 및 버전 번호 부여(ant, cvs, hudson)

Java 프로젝트에서 체계적인 빌드 번호 부여 및 버전 번호 관리를 위한 현재 모범 사례는 무엇입니까?구체적으로는:

  • 분산 개발 환경에서 빌드 번호를 체계적으로 관리하는 방법

  • 소스 또는 런타임 응용 프로그램에서 사용 가능한 버전 번호를 유지하는 방법

  • 소스 저장소와의 적절한 통합 방법

  • 버전 번호와 저장소 태그를 보다 자동으로 관리하는 방법

  • 지속적인 구축 인프라스트럭처와의 통합 방법

사용할 수 있는 툴은 매우 많은데, 개미(당사가 사용하는 빌드 시스템)는 빌드 번호를 유지하는 태스크를 가지고 있지만 CVS, svn 등을 사용하여 여러 개발자를 동시에 사용하여 이를 관리하는 방법은 명확하지 않습니다.

[편집]

아래에 몇 가지 유용한 부분적 또는 구체적인 답변이 나와 있으므로 그 중 몇 가지를 요약해 보겠습니다.여기에는 실제로 강력한 "베스트 프랙티스"가 없는 것처럼 들리고, 오히려 중복되는 아이디어의 집합체라고 할 수 있습니다.아래에서는 사람들이 후속 조치로 대답할 수 있는 제 요약과 그에 따른 질문을 찾아보세요.[스택오버플로우 신규...]제가 잘못하고 있다면 댓글을 달아주세요.]

  • SVN을 사용하는 경우 탑승 시 특정 체크아웃 버전이 제공됩니다.빌드 번호는 이를 이용하여 특정 체크아웃/리비전을 식별하는 고유한 빌드 번호를 생성할 수 있습니다.[기존의 이유로 사용되고 있는 CVS는 이 정도의 통찰력은 제공하지 않습니다.태그에 의한 수동 조작으로 실현됩니다.]

  • maven을 빌드시스템으로 사용하는 경우 SCM에서 버전 번호 생성과 릴리즈 자동 생성용 릴리스 모듈이 지원됩니다.[다양한 이유로 메이븐을 사용할 수 없지만 사용할 수 있는 사람에게 도움이 됩니다.[마셀로 모랄레스 덕분]

  • ant를 빌드 시스템으로 사용하는 경우 다음 작업 설명은 빌드 정보를 캡처하는 Java .properties 파일을 생성하는 데 도움이 될 수 있습니다. 이 파일은 여러 가지 방법으로 빌드에 접을 수 있습니다.[고맙게도 이 아이디어를 허드슨에서 파생된 정보를 포함하도록 확장했습니다.]

  • 앤트와 메이븐(및 허드슨과 크루즈 컨트롤)은 빌드 번호를 .properties 파일 또는 .txt/.html 파일로 쉽게 가져올 수 있습니다.의도적 또는 우발적으로 조작되는 것을 막을 수 있을 정도로 안전한가?빌드 시 "버전" 클래스로 컴파일하는 것이 좋습니까?

  • 어설션:빌드 번호는 허드슨과 같은 연속적인 통합 시스템에서 정의/실현해야 합니다.[marcelo-morales 덕분에]이 제안을 받아들였습니다만, 릴리스 엔지니어링에 관한 의문이 풀렸습니다.릴리스는 어떻게 이루어집니까?하나의 릴리스에 여러 빌드 번호가 있습니까?서로 다른 릴리스의 빌드 번호 사이에 의미 있는 관계가 있습니까?

  • 질문:.빌드 번호의 목적은 무엇입니까?QA에 사용됩니까? 어떻게 사용합니까?개발자가 개발 중에 여러 빌드를 명확히 하기 위해 주로 사용합니까? 아니면 QA가 최종 사용자가 어떤 빌드를 얻었는지 결정하기 위해 더 많이 사용합니까?재현성이 목표인 경우, 이론적으로는 릴리스 버전 번호가 제공하는 것입니다.왜 안 되는가?(아래의 답변의 일부로서 답변해 주십시오.이것에 의해, 지금까지의 선택/제안한 내용이 밝혀집니다).

  • 질문:.수동 빌드에는 빌드 번호를 사용할 수 있는 장소가 있습니까?모든 사람이 CI 솔루션을 사용해야 할 정도로 문제가 많은가요?

  • 질문:.빌드 번호를 SCM에 체크인해야 합니까?특정 빌드를 확실하고 명확하게 특정하는 것이 목표인 경우, 크래시/재기동할 가능성이 있는 다양한 연속 빌드 또는 수동 빌드 시스템에 대처하는 방법...

  • 질문:.빌드 번호가 짧고 단조로운(즉, 정수가 단조롭게 증가하는 등) 아카이브를 위해 파일 이름을 쉽게 사용하거나 통신에서 참조할 수 있도록 하는 경우또는 사용자 이름, 데이터 스탬프, 머신 이름 등으로 길고 꽉 차야 합니다.

  • 질문: 빌드 번호 할당이 대규모 자동 릴리스 프로세스에 어떻게 적합한지 자세히 알려 주십시오.그래, 사랑하는 사람들, 우린 이미 끝난 일이라는 걸 알지만, 우리 모두가 아직 쿨에이드를 마셔본 건 아니야...

적어도 cvs/ant/hudson 설정의 구체적인 예에 대해서는 이 질문을 바탕으로 완전한 전략을 구축할 수 있도록 이 답변을 구체화하고 싶습니다.이 특정 케이스에 대한 자세한 설명을 할 수 있는 모든 사용자(cvs 태그 지정 방식, 관련 CI 구성 항목 및 빌드 번호를 프로그래밍 방식으로 액세스할 수 있도록 릴리스에 접는 릴리스 절차 포함)는 "The Answer"로 표시합니다.다른 설정(예를 들어 svn/maven/cruise control)에 대해 질문/답변을 원하는 경우 여기에서 질문으로 링크합니다. --JA

[편집 23일 09년 10월 23일]가장 많이 투표된 답변은 합리적인 해결책이라고 생각하기 때문에 받아들였습니다.다른 답변에는 좋은 아이디어가 포함되어 있습니다.마티 과 합성하고 싶은 사람이 있다면 다른 것을 받아들이는 것을 검토해 보겠습니다.marty-lamb의 유일한 관심사는 신뢰성 있는 시리얼화된 빌드 번호가 생성되지 않는다는 것입니다.빌더 시스템의 로컬 클럭에 따라 명확한 빌드 번호가 제공되는데, 이는 그다지 좋은 일이 아닙니다.

[7월 10일 편집]

현재는 다음과 같은 클래스가 포함되어 있습니다.이를 통해 버전 번호를 최종 실행 파일로 컴파일할 수 있습니다.로그 데이터, 장기간 아카이브된 출력 제품에서는 다양한 형식의 버전 정보가 출력되며 출력 제품에 대한 분석을 특정 빌드로 추적하는 데 사용됩니다.

public final class AppVersion
{
   // SVN should fill this out with the latest tag when it's checked out.

   private static final String APP_SVNURL_RAW = 
     "$HeadURL: svn+ssh://user@host/svnroot/app/trunk/src/AppVersion.java $";
   private static final String APP_SVN_REVISION_RAW = "$Revision: 325 $";  

   private static final Pattern SVNBRANCH_PAT = 
     Pattern.compile("(branches|trunk|releases)\\/([\\w\\.\\-]+)\\/.*");
   private static final String APP_SVNTAIL = 
     APP_SVNURL_RAW.replaceFirst(".*\\/svnroot\\/app\\/", "");

  private static final String APP_BRANCHTAG;
  private static final String APP_BRANCHTAG_NAME;
  private static final String APP_SVNREVISION = 
    APP_SVN_REVISION_RAW.replaceAll("\\$Revision:\\s*","").replaceAll("\\s*\\$", "");


  static {
    Matcher m = SVNBRANCH_PAT.matcher(APP_SVNTAIL);
    if (!m.matches()) {
      APP_BRANCHTAG = "[Broken SVN Info]";
      APP_BRANCHTAG_NAME = "[Broken SVN Info]";
    } else {
      APP_BRANCHTAG = m.group(1);
      if (APP_BRANCHTAG.equals("trunk")) {
        // this isn't necessary in this SO example, but it 
        // is since we don't call it trunk in the real case
        APP_BRANCHTAG_NAME = "trunk";
      } else {
        APP_BRANCHTAG_NAME = m.group(2);
      }
    }
  }

  public static String tagOrBranchName()
  { return APP_BRANCHTAG_NAME; }

  /** Answers a formatter String descriptor for the app version.
   * @return version string */
  public static String longStringVersion()
  { return "app "+tagOrBranchName()+" ("+
    tagOrBranchName()+", svn revision="+svnRevision()+")"; }

  public static String shortStringVersion()
  { return tagOrBranchName(); }

  public static String svnVersion()
  { return APP_SVNURL_RAW; }

  public static String svnRevision()
  { return APP_SVNREVISION; }

  public static String svnBranchId()
  { return APP_BRANCHTAG + "/" + APP_BRANCHTAG_NAME; } 

  public static final String banner()
  {
    StringBuilder sb = new StringBuilder();
    sb.append("\n----------------------------------------------------------------");
    sb.append("\nApplication -- ");
    sb.append(longStringVersion());
    sb.append("\n----------------------------------------------------------------\n");
    return sb.toString();
  }
}

이것이 위키 토론이 될 자격이 있다면 댓글을 남겨주세요.

프로젝트 중 몇 가지에서는 서브버전 리비전 번호, 시간, 빌드를 실행한 사용자 및 시스템 정보를 캡처하여 응용 프로그램 jar에 포함된 .properties 파일에 저장하고 실행 시 해당 jar를 읽습니다.

개미 코드는 다음과 같습니다.

<!-- software revision number -->
<property name="version" value="1.23"/>

<target name="buildinfo">
    <tstamp>
        <format property="builtat" pattern="MM/dd/yyyy hh:mm aa" timezone="America/New_York"/>
    </tstamp>        
    <exec executable="svnversion" outputproperty="svnversion"/>
    <exec executable="whoami" outputproperty="whoami"/>
    <exec executable="uname" outputproperty="buildsystem"><arg value="-a"/></exec>

    <propertyfile file="path/to/project.properties"
        comment="This file is automatically generated - DO NOT EDIT">        
        <entry key="buildtime" value="${builtat}"/>
        <entry key="build" value="${svnversion}"/>
        <entry key="builder" value="${whoami}"/>
        <entry key="version" value="${version}"/>
        <entry key="system" value="${buildsystem}"/>
    </propertyfile>
</target>

추가할 수 있는 모든 정보를 포함하도록 확장하면 됩니다.

사용자의 build.xml

...
<property name="version" value="1.0"/>
...
<target name="jar" depends="compile">
    <buildnumber file="build.num"/>
    <manifest file="MANIFEST.MF">
        ...
        <attribute name="Main-Class" value="MyClass"/>
        <attribute name="Implementation-Version" value="${version}.${build.number}"/>
        ...
    </manifest>
</target>
...

자바 코드

String ver = MyClass.class.getPackage().getImplementationVersion();
  • 빌드 번호는 허드슨 의 연속적인 통합 서버에 관련지어야 합니다.지점/팀/배포마다 다른 작업을 사용합니다.
  • 최종 빌드에서 버전 번호를 유지하려면 빌드 시스템에 maven만 사용하는 것이 좋습니다.그러면 마지막 .jar/.war/.war/.wall-ar에 아카이브된 .properties 파일이 생성됩니다.META-INF/maven/<project group>/<project id>/pom.properties됩니다.성질
  • maven을 추천하기 때문에 릴리스 플러그인을 체크하여 소스 저장소에 릴리스를 준비하고 버전을 동기화해 둘 것을 권장합니다.

소프트웨어:

  • SVN
  • 개미.
  • 허드슨, 지속적인 통합을 위해
  • svntask, SVN 리비전을 검색하기 위한 Ant 태스크:http://code.google.com/p/svntask/

허드슨에는 세 가지 빌드/작업이 있습니다.Continuous, Nightly 및 Release.

연속/야간 빌드의 경우:빌드 번호는 SVN 리비전으로, svntask를 사용하여 검색됩니다.

릴리스 빌드/작업의 경우: 빌드 번호는 속성 파일에서 읽어낸 릴리스 번호입니다.또한 런타임에 빌드 번호를 표시하기 위해 릴리스와 함께 속성 파일을 배포할 수도 있습니다.

개미 빌드 스크립트는 빌드 중에 생성된 jar/war 파일의 매니페스트 파일에 빌드 번호를 넣습니다.모든 빌드에 적용됩니다.

릴리스 빌드에 대한 빌드 후 액션.Hudson 플러그인을 사용하여 쉽게 실행할 수 있습니다.SVN에 빌드 번호를 태그 붙입니다.

이점:

  • 개발 버전의 jar/war의 경우 개발자는 jar/war에서 SVN 리비전을 찾아 SVN에서 해당 코드를 조회할 수 있습니다.
  • 릴리스의 경우 SVN 리비전은 릴리스 번호가 있는 SVN 태그에 대응하는 리비전입니다.

이게 도움이 됐으면 좋겠다.

허드슨도 사용하고 있습니다만, 보다 간단한 시나리오입니다.

내 개미 스크립트에는 다음과 같은 타겟이 있습니다.

<target name="build-number">
    <property environment="env" />
    <echo append="false" file="${build.dir}/build-number.txt">Build: ${env.BUILD_TAG}, Id: ${env.BUILD_ID}, URL: ${env.HUDSON_URL}</echo>
</target>

허드슨은 내 일이 실행될 때마다 이런 환경변수를 설정해준다.

이 이고, 이 프로젝트에는 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 프로젝트, 이 세 가지가 되어 있습니다.build-number.txt의 루트 - 누가.webapp은 - file file file file file file of of of of of of file file file file file - file file file file file file 。

빌드 성공 시 빌드 번호/타임 스탬프로 태그 지정하도록 허드슨 작업이 이미 설정되어 있기 때문에 이 작업이 완료될 때 소스 컨트롤에 태그를 붙이지 않습니다.

제 솔루션은 개발을 위한 증분 빌드 수만을 커버하고 있으며, 릴리즈 수를 커버하고 있는 프로젝트에서는 아직 충분한 성과를 거두지 못했습니다.

또한 http://code.google.com/p/codebistro/wiki/BuildNumber에 있는 하나의 jar에 있는 BuildNumber Maven 플러그인 및 Ant 태스크도 볼 수 있습니다.나는 그것을 단순하고 직설적으로 하려고 노력했다.설치된 명령줄 Subversion에만 의존하는 매우 작은 jar 파일입니다.

이렇게 해결했습니다.

  • 소스가 빌드 디렉토리에 복사됩니다.
  • anttask "versioninfo" 가 적용됩니다.
  • 수정된 출처를 정리하다

다음은 버전 정보를 저장하는 Java 파일입니다.

public class Settings {

    public static final String VERSION = "$VERSION$";
    public static final String DATE = "$DATE$";

}

anttask "versioninfo"는 다음과 같습니다.

    <!-- ================================= 
     target: versioninfo              
     ================================= -->
    <target name="versioninfo"
            depends="init"
            description="gets version info from svn"
    >

        <!-- 
        get svn info from the src folder 
        -->
        <typedef resource="org/tigris/subversion/svnant/svnantlib.xml"
                 classpathref="ant.classpath"
        />
        <svnSetting id="svn.setting"
                    javahl="false"
                    svnkit="true"
                    dateformatter="dd.MM.yyyy"
        />
        <svn refid="svn.setting">
            <info target="src" />
        </svn>

        <!-- 
        if repository is a taged version use "v <tagname>"
        else "rev <revisionnumber> (SVN)" as versionnumber
         -->
        <taskdef resource="net/sf/antcontrib/antcontrib.properties"
                 classpathref="ant.classpath"
        />
        <propertyregex property="version"
                       input="${svn.info.url}"
                       regexp=".*/tags/(.*)/${ant.project.name}/src"
                       select="v \1"
                       defaultvalue="rev ${svn.info.lastRev} (SVN)"
                       override="true"
        />


        <!-- 
        replace date and version in the versionfile ()
         -->
        <replace file="build/${versionfile}">
            <replacefilter token="$DATE$" value="${svn.info.lastDate}" />
            <replacefilter token="$VERSION$" value="${version}" />
        </replace>

    </target>

여기 2센트 있습니다.

  • 빌드 스크립트는 앱을 빌드할 때마다 빌드 번호(타임스탬프 포함!)를 생성합니다.이로 인해 너무 많은 수가 생성되지만 결코 너무 적은 수는 생성되지 않습니다.코드가 변경되면 빌드 번호가 한 번 이상 변경됩니다.

  • 모든 릴리스에 따라 빌드 번호를 버전화합니다(단, 그 사이는 아님).프로젝트를 업데이트하고 새 빌드 번호를 받으면(다른 사용자가 릴리스를 했기 때문에), 로컬 버전을 덮어쓰고 다시 시작합니다.이로 인해 빌드 번호가 낮아질 수 있기 때문에 타임스탬프를 포함했습니다.

  • 릴리스가 발생하면 빌드 번호는 "build 1547" 메시지와 함께 단일 커밋의 마지막 항목으로 커밋됩니다.그 후 정식 발매가 되면 트리 전체에 태그가 붙습니다.이렇게 하면 빌드 파일에는 항상 모든 태그가 있으며 태그와 빌드 번호 간에 간단한 1:1 매핑이 있습니다.

[편집] 프로젝트와 함께 version.html을 전개하고 스크레이퍼를 사용하여 어디에 설치되어 있는지 정확한 지도를 수집할 수 있습니다.Tomcat 등을 사용하는 경우 빌드 번호와 타임스탬프를descriptionweb.xml 요소주의:컴퓨터가 대신 할 수 있는 일은 절대 외우지 마세요.

NAT은 크루즈컨트롤(여기에 마음에 드는 빌드 관리자 삽입)을 통해 빌드를 실행하고 기본 빌드 및 테스트를 수행합니다.

그런 다음 Ant와 BuildNumber를 사용하여 버전 번호를 증가시키고 이 정보와 빌드 날짜 및 기타 메타데이터가 포함된 속성 파일을 만듭니다.

이를 읽고 GUI/로그 등에 제공하는 전용 클래스가 있습니다.

그런 다음 이 모든 것을 패키징하고 빌드 번호와 해당 빌드를 연결하는 배포 가능 파일을 구축합니다.모든 서버가 시작 시 이 메타 정보를 버립니다.크루즈 컨트롤 로그로 돌아가서 빌드 번호를 날짜 및 체크인에 연결할 수 있습니다.

언급URL : https://stackoverflow.com/questions/690419/build-and-version-numbering-for-java-projects-ant-cvs-hudson

반응형