Ja sst'14東北 いまさら聞けないJenkins
-
Upload
- -
Category
Engineering
-
view
1.912 -
download
5
Transcript of Ja sst'14東北 いまさら聞けないJenkins
JaSST’14 Tohoku
いまさら聞けないJenkins
Jenkinsが普及してからずいぶん経ち、すっかり入門的な話を聞かなくなりました。今回は初心に戻って、Jenkinsとはどんなツールなのか?を紹介します。
別にいつでも、どんなレベルの話だって聞いて良いんですよ。
(` ・ω・́)ゞ
おことわり
せっかくのJaSSTですがテストの話では無いです。
ところで
Jenkinsを知らない。名前だけなら知ってる。
おめでとうございます。そんな皆さん向けの話です。
Jenkinsを知ってるし、普段から使ってる。
退屈かも知れませんが、おさらいだと思ってお付き合いください。
わたしの前でJenkinsを語るとは良い度胸だ。
寝てていいです。
(:3[▓▓]
Jenkinsとは
オープンソースのCIサーバ今やCIサーバの代名詞的存在http://jenkins-ci.org
CI:Continuous Integration継続的インテグレーション
超高機能cron
(c) @cactusman
それって何なの?
|ω・̀)チラッそれを
順を追って紹介します
ごくありふれた開発風景
(立場上Javaの話です)
みんな大好きeclipse!!
eclipseでプログラミングやテストをしながら開発を進めます。
さらにリリースモジュール(warファイル)だって作れます。
万能IDEeclipse!!
\(̂ o )̂/
バージョン管理もお忘れなく
開発用PC
リポジトリサーバ開発サーバ
図にするとこんな感じ
でも、こんな事に困っていませんか?
私のところでビルドできる!こっちだとビルドできない!
テストに時間がかかるからサボってた
こうならないためにはどうしたらよいだろう...
| \ _ / _ (m) _ 目 ピコーン / `′ \ ∧_∧ (・∀・∩ (つ ノ ⊂_ノ (_)
みんなで決めたルールを守って、与えられた道具を正しく使おう!
|_| ∧|旨|ω・̀ )|‾|⊂ ノ
でも、人は間違うんです。
その点、機械は間違えません。
チラッ
そこでJenkinsです!
とは、なりません
ズコーッ
機械(Jenkins)に任す前にまずはビルドを自動化します
ビルドツールでビルド手順をスクリプト化します
<?xml version="1.0" encoding="utf-8" ?><project name="commons"> <!-- 環境変数の取込み -->
<property environment="env" />
<!-- パスの設定 --> <property name="src.java.dir" value="src/java" /> <property name="src.test.dir" value="src/test" /> <property name="src.web.dir" value="web" />
<property name="dest.dir" value="dest" /> <property name="dest.java.dir" value="${dest.dir}/classes/java" /> <property name="dest.test.dir" value="${dest.dir}/classes/test" /> <property name="dest.javadoc.dir" value="${dest.dir}/report/javadoc" /> <property name="result.dir" value="${dest.dir}/result" /> <property name="result.test.dir" value="${result.dir}/test" />
<property name="lib.compile.dir" value="${src.web.dir}/WEB-INF/lib" /> <property name="lib.provided.dir" value="lib/provided" /> <property name="lib.test.dir" value="lib/test" />
<!-- ベースとなるCLASSPATH -->
<path id="base.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> </path>
<!-- ベースとなるCLASSPATH(テスト用) --> <path id="test.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> <fileset dir="${lib.test.dir}" includes="*.jar" /> </path>
<!-- リソースファイルのパターン -->
<patternset id="resource"> <include name="**/*.properties"/> <include name="**/*.txt"/> </patternset> <target name="clean" description="クリーンアップ">
<delete dir="${dest.dir}" /> </target>
<target name="prepare"> <mkdir dir="${dest.dir}" /> <mkdir dir="${dest.java.dir}" /> <mkdir dir="${dest.test.dir}" /> <mkdir dir="${result.dir}" /> </target>
<target name="compile-main" depends="prepare"> <!-- リソースのコピー --> <copy todir="${dest.java.dir}"> <fileset dir="${src.java.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.java.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.java.dir}" /> <classpath refid="base.classpath" /> </javac> </target>
<target name="build-webapps" description="WARファイルの作成" depends="compile-main"> <war destfile="${dest.dir}/${ant.project.name}.war" update="true" duplicate="preserve" webxml="${src.web.dir}/WEB-INF/web.xml"> <classes dir="${dest.java.dir}" /> <lib file="${lib.compile.dir}/*.jar" /> <fileset dir="${src.web.dir}" excludes="**/web.xml" /> </war> </target>
<target name="javadoc" depends="prepare" description="Javadocの作成"> <javadoc sourcepath="${src.java.dir}" destdir="${dest.javadoc.dir}" packagenames="com.example.*" classpathref="base.classpath" encoding="utf-8" /> </target>
<target name="compile-test" depends="compile-main"> <!-- リソースのコピー --> <copy todir="${dest.test.dir}"> <fileset dir="${src.test.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.test.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.test.dir}" /> <classpath refid="test.classpath" /> <classpath location="${dest.java.dir}" /> </javac> </target>
<target name="test" depends="compile-test" description="テストの実行"> <delete dir="${result.test.dir}" /> <mkdir dir="${result.test.dir}" />
<junit fork="on" printsummary="on" maxmemory="256m"> <classpath location="${dest.test.dir}" /> <classpath location="${dest.java.dir}" /> <classpath refid="test.classpath" />
<formatter type="xml" /> <batchtest todir="${result.test.dir}"> <fileset dir="${dest.test.dir}"/> </batchtest> </junit> </target>
<target name="release" depends="clean, test, build-webapps, javadoc" description="リリースモジュールの作成"> <zip destfile="${dest.dir}/${ant.project.name}.zip"> <fileset file="${dest.dir}/${ant.project.name}.war"/> <zipfileset dir="${dest.javadoc.dir}" prefix="javadoc"/> </zip> </target>
</project>
<?xml version="1.0" encoding="utf-8" ?><project name="commons"> <!-- 環境変数の取込み -->
<property environment="env" />
<!-- パスの設定 --> <property name="src.java.dir" value="src/java" /> <property name="src.test.dir" value="src/test" /> <property name="src.web.dir" value="web" />
<property name="dest.dir" value="dest" /> <property name="dest.java.dir" value="${dest.dir}/classes/java" /> <property name="dest.test.dir" value="${dest.dir}/classes/test" /> <property name="dest.javadoc.dir" value="${dest.dir}/report/javadoc" /> <property name="result.dir" value="${dest.dir}/result" /> <property name="result.test.dir" value="${result.dir}/test" />
<property name="lib.compile.dir" value="${src.web.dir}/WEB-INF/lib" /> <property name="lib.provided.dir" value="lib/provided" /> <property name="lib.test.dir" value="lib/test" />
<!-- ベースとなるCLASSPATH --> <path id="base.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> </path>
<!-- ベースとなるCLASSPATH(テスト用) --> <path id="test.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> <fileset dir="${lib.test.dir}" includes="*.jar" /> </path>
<!-- リソースファイルのパターン -->
<patternset id="resource"> <include name="**/*.properties"/> <include name="**/*.txt"/> </patternset> <target name="clean" description="クリーンアップ">
<delete dir="${dest.dir}" /> </target>
<target name="prepare"> <mkdir dir="${dest.dir}" /> <mkdir dir="${dest.java.dir}" /> <mkdir dir="${dest.test.dir}" /> <mkdir dir="${result.dir}" /> </target>
<target name="compile-main" depends="prepare"> <!-- リソースのコピー --> <copy todir="${dest.java.dir}"> <fileset dir="${src.java.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.java.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.java.dir}" /> <classpath refid="base.classpath" /> </javac> </target>
<target name="build-webapps" description="WARファイルの作成" depends="compile-main"> <war destfile="${dest.dir}/${ant.project.name}.war" update="true" duplicate="preserve" webxml="${src.web.dir}/WEB-INF/web.xml"> <classes dir="${dest.java.dir}" /> <lib file="${lib.compile.dir}/*.jar" /> <fileset dir="${src.web.dir}" excludes="**/web.xml" /> </war> </target>
<target name="javadoc" depends="prepare" description="Javadocの作成"> <javadoc sourcepath="${src.java.dir}" destdir="${dest.javadoc.dir}" packagenames="com.example.*" classpathref="base.classpath" encoding="utf-8" /> </target>
<target name="compile-test" depends="compile-main"> <!-- リソースのコピー --> <copy todir="${dest.test.dir}"> <fileset dir="${src.test.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.test.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.test.dir}" /> <classpath refid="test.classpath" /> <classpath location="${dest.java.dir}" /> </javac> </target>
<target name="test" depends="compile-test" description="テストの実行"> <delete dir="${result.test.dir}" /> <mkdir dir="${result.test.dir}" />
<junit fork="on" printsummary="on" maxmemory="256m"> <classpath location="${dest.test.dir}" /> <classpath location="${dest.java.dir}" /> <classpath refid="test.classpath" />
<formatter type="xml" /> <batchtest todir="${result.test.dir}"> <fileset dir="${dest.test.dir}"/> </batchtest> </junit> </target>
<target name="release" depends="clean, test, build-webapps, javadoc" description="リリースモジュールの作成"> <zip destfile="${dest.dir}/${ant.project.name}.zip"> <fileset file="${dest.dir}/${ant.project.name}.war"/> <zipfileset dir="${dest.javadoc.dir}" prefix="javadoc"/> </zip> </target>
</project>
antは手堅いビルドツールだけど、面倒でもある。
参考までに同じ事をgradleで書いてみた
<?xml version="1.0" encoding="utf-8" ?><project name="commons"> <!-- 環境変数の取込み --> <property environment="env" />
<!-- パスの設定 --> <property name="src.java.dir" value="src/java" /> <property name="src.test.dir" value="src/test" /> <property name="src.web.dir" value="web" />
<property name="dest.dir" value="dest" /> <property name="dest.java.dir" value="${dest.dir}/classes/java" /> <property name="dest.test.dir" value="${dest.dir}/classes/test" /> <property name="dest.javadoc.dir" value="${dest.dir}/report/javadoc" /> <property name="result.dir" value="${dest.dir}/result" /> <property name="result.test.dir" value="${result.dir}/test" />
<property name="lib.compile.dir" value="${src.web.dir}/WEB-INF/lib" /> <property name="lib.provided.dir" value="lib/provided" /> <property name="lib.test.dir" value="lib/test" />
<!-- ベースとなるCLASSPATH -->
<path id="base.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> </path>
<!-- ベースとなるCLASSPATH(テスト用) -->
<path id="test.classpath"> <fileset dir="${lib.compile.dir}" includes="*.jar" /> <fileset dir="${lib.provided.dir}" includes="*.jar" /> <fileset dir="${lib.test.dir}" includes="*.jar" /> </path>
<!-- リソースファイルのパターン -->
<patternset id="resource"> <include name="**/*.properties"/> <include name="**/*.txt"/> </patternset> <target name="clean" description="クリーンアップ">
<delete dir="${dest.dir}" /> </target>
<target name="prepare"> <mkdir dir="${dest.dir}" /> <mkdir dir="${dest.java.dir}" /> <mkdir dir="${dest.test.dir}" /> <mkdir dir="${result.dir}" /> </target>
<target name="compile-main" depends="prepare"> <!-- リソースのコピー -->
<copy todir="${dest.java.dir}"> <fileset dir="${src.java.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.java.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.java.dir}" /> <classpath refid="base.classpath" /> </javac> </target>
<target name="build-webapps" description="WARファイルの作成" depends="compile-main"> <war destfile="${dest.dir}/${ant.project.name}.war" update="true" duplicate="preserve" webxml="${src.web.dir}/WEB-INF/web.xml"> <classes dir="${dest.java.dir}" /> <lib file="${lib.compile.dir}/*.jar" /> <fileset dir="${src.web.dir}" excludes="**/web.xml" /> </war> </target>
<target name="javadoc" depends="prepare" description="Javadocの作成"> <javadoc sourcepath="${src.java.dir}" destdir="${dest.javadoc.dir}" packagenames="com.example.*" classpathref="base.classpath" encoding="utf-8" /> </target>
<target name="compile-test" depends="compile-main"> <!-- リソースのコピー -->
<copy todir="${dest.test.dir}"> <fileset dir="${src.test.dir}"> <patternset refid="resource"/> </fileset> </copy> <javac destdir="${dest.test.dir}" debug="on" debuglevel="lines,vars,source" optimize="off" deprecation="on" encoding="utf-8" includeAntRuntime="off"> <src path="${src.test.dir}" /> <classpath refid="test.classpath" /> <classpath location="${dest.java.dir}" /> </javac> </target>
<target name="test" depends="compile-test" description="テストの実行"> <delete dir="${result.test.dir}" /> <mkdir dir="${result.test.dir}" />
<junit fork="on" printsummary="on" maxmemory="256m"> <classpath location="${dest.test.dir}" /> <classpath location="${dest.java.dir}" /> <classpath refid="test.classpath" />
<formatter type="xml" /> <batchtest todir="${result.test.dir}"> <fileset dir="${dest.test.dir}"/> </batchtest> </junit> </target>
<target name="release" depends="clean, test, build-webapps, javadoc" description="リリースモジュールの作成">
<zip destfile="${dest.dir}/${ant.project.name}.zip"> <fileset file="${dest.dir}/${ant.project.name}.war"/> <zipfileset dir="${dest.javadoc.dir}" prefix="javadoc"/> </zip> </target>
</project>
apply { plugin 'java' plugin 'war' plugin 'jetty'}
archivesBaseName = 'sample-apps'[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
repositories { mavenCentral()}
dependencies { testCompile 'junit:junit:4.10'}
開発用PC
リポジトリサーバ開発サーバ
図にするとこんな感じ
ここでようやくJenkinsの出番です!
開発用PC
リポジトリサーバ
開発サーバ
ビルドサーバ
まずはインストール
初期設定
ジョブの作成
ビルド実行
Jenkinsすごく簡単!
☆イベント発生
チェックアウト
ビルド実行
ビルドの後処理
ビルドはビルドツールが行う
他のジョブを起動する事も可能
レポートや通知を行う
図にするとこんな感じ
もっといろいろしたい
コード検査をしたい
ビルドツールでコード検査できるようにする
<target name="checkstyle" depends="prepare"> <property name="checkstyle.home" value="${tool.dir}/checkstyle-5.1" /> <taskdef resource="checkstyletask.properties" classpath="${checkstyle.home}/checkstyle-all-5.1.jar"/> <checkstyle config="${checkstyle.home}/sun_checks.xml" failOnViolation="no"> <fileset dir="${src.java.dir}" includes="**/*.java"/> <formatter type="xml" toFile="${result.dir}/checkstyle-result.xml"/> </checkstyle> </target>
<target name="findbugs" depends="compile-main"> <property name="findbugs.home" value="${tool.dir}/findbugs-1.3.9" /> <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask" classpath="${findbugs.home}/lib/findbugs-ant.jar"/>
<findbugs home="${findbugs.home}" output="xml" outputFile="${result.dir}/findbugs-result.xml" > <sourcePath path="${src.java.dir}" /> <class location="${dest.java.dir}" /> </findbugs> </target>
<target name="inspection" depends="checkstyle, findbugs" description="インスペクション">
</target>
Jenkinsに検査結果を取り込む
Violationsプラグイン
カバレッジを測定したい
<target name="test" depends="compile-test" description="テストの実行とカバレッジレポートの作成"> <!-- EclEmma(JaCoCo)の定義 --> <property name="jacoco.home" value="${tool.dir}/jacoco-0.5.6"/> <taskdef resource="org/jacoco/ant/antlib.xml"> <classpath path="${jacoco.home}/lib/jacocoant.jar"/> </taskdef> <!-- ここまで -->
<delete dir="${result.test.dir}" /> <mkdir dir="${result.test.dir}" />
<coverage> <junit fork="on" printsummary="on" maxmemory="256m"> <classpath location="${dest.test.dir}" /> <classpath location="${dest.java.dir}" /> <classpath refid="test.classpath" />
<formatter type="xml" /> <batchtest todir="${result.test.dir}"> <fileset dir="${dest.test.dir}" includes="**/*Test.class" /> </batchtest> </junit> </coverage> </target>
ビルドツールでカバレッジを測定できるようにする
<report> <executiondata> <file file="jacoco.exec"/> </executiondata> <structure name="${ant.project.name}"> <classfiles> <fileset dir="${dest.java.dir}"/> </classfiles> <sourcefiles encoding="UTF-8"> <fileset dir="${src.java.dir}"/> </sourcefiles> </structure> <xml destfile="${result.dir}/coverage_jacoco.xml" /> <html destdir="${dest.dir}/report/coverage"/>
</report> <!-- JaCoCoのレポートをEMMA形式に変換する --> <xslt style="${jacoco.home}/jacoco_to_emma.xslt" in="${result.dir}/coverage_jacoco.xml" out="${result.dir}/coverage.xml" classpath="${jacoco.home}/saxon9he.jar"> <xmlcatalog> <dtd publicid="-//JACOCO//DTD Report 1.0//EN" location="${jacoco.home}/coverage/report.dtd"/> </xmlcatalog> </xslt> </target>
Jenkinsに検査結果を取り込む
JaCoCoプラグイン
// apply plugin: 'java' としなくても,以下のようにまとめて書けるapply { plugin 'java' plugin 'war' plugin 'jetty' plugin 'jacoco'}
// jarファイルの名前archivesBaseName = 'sample-apps'// javacのオプションに encoding=UTF-8 を追加する[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
// mavenリポジトリを利用するrepositories { mavenCentral()}
// 依存ライブラリはローカルにあるJarファイルを直接参照dependencies { testCompile 'junit:junit:4.10'}
// checkstyleとfindbugsなどインスペクション系の設定apply { plugin 'checkstyle' plugin 'findbugs' plugin 'pmd' plugin 'jdepend'}
// オプションを一括指定(エラーが出てもチェックを進める)[checkstyleMain, checkstyleTest, findbugsMain, findbugsTest, pmdMain, pmdTest]*.ignoreFailures = true
参考までに同じ事をgradleで書いてみた
全部のっけるとこんな感じになります
もしかして...
Jenkins ってビルドに関しては何もしてない??
ド キッ
(・ω<)当たりです
ビルドはビルドツールの仕事です
☆イベント発生
チェックアウト
ビルド実行
ビルドの後処理
ビルドはビルドツールが行う
他のジョブを起動する事も可能
レポートや通知を行う
もう一度ご覧下さい
Jenkinsは触媒のようなものです
いろんなツールをまとめます
数多くのプラグインがそれを支えています
プラグインのページはだいたい英語です。
Jenkinsは簡単にはじめられて、いくらでも拡張できます
ちょっとだけ大変かも...。
はじめよう Jenkins
ご静聴ありがとうございました