読者です 読者をやめる 読者になる 読者になる

ぐるっとぐりっど

日曜プログラマがいろいろ試してみたことを、後の自分のためにまとめておく場所

Jenkinsでgo言語のプロジェクトをCIする方法を調査した

はじめに

Golangをちまちまプライベートで触っていて、バックエンドサーバを試しにgolangで書いてみてるんだけど、Jenkinsのpipelineでgoを扱う方法が、調査しても断片的にしか出てこなかったので、本腰を入れて調査してみた。
pipelineでなければ、もっと簡単そうだけど、BlueOceanも1.0リリースされたしね。

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

対象

ソースコードはこちら

github.com

単なる足し算を実装しただけの簡易なもの。
しかも明らかにミスってる(もちろんわざと)

func Sum(a int, b int) int {
	return a + a
}

これをJenkinsでTestしてみる。

事前準備

プラグインの導入、初期設定

Go pluginを導入しておく

Go Plugin - Jenkins - Jenkins Wiki

次にプラグインの設定をする。
日本語メニューの場合、「Jenkinsの設定」→「Global Tool Configuration」にGoの設定があるはず。(http://JenkinsのURL/configureTools/ にアクセスしてもよい)

インストール済Goというのに適当な名前(ここではGo1.8とした)をつけて、必要なGoのバージョンを設定しておく。これは必須ではないが、これをやっておくと、Jenkins専用のGoを設定しておくことができる。CentOSのepelリポジトリが1.6までしかなくて、depが使えなかったので、このやりかたで導入した。

f:id:grugrut:20170410195400p:plain

Jenkinsfileを書く

pipelineは、Jenkins上で書くこともできるけど、ファイルとして切り出して管理することもできる。バージョン管理もできるし、そちらの方が推されてるはず。

というわけで、Jenkinsfileをごりごり書いた。

書いてみたのがこんな

node {
    def root = tool name: 'Go1.8', type: 'go'
    ws("${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/src/github.com/grugrut/golang-ci-jenkins-pipeline") {
        withEnv(["GOROOT=${root}", "GOPATH=${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/", "PATH+GO=${root}/bin"]) {
            env.PATH="${GOPATH}/bin:$PATH"
            
            stage 'Checkout'
        
            git url: 'https://github.com/grugrut/golang-ci-jenkins-pipeline.git'
        
            stage 'preTest'
            sh 'go version'
            sh 'go get -u github.com/golang/dep/...'
            sh 'dep init'
            
            stage 'Test'
            sh 'go vet'
            sh 'go test -cover'
            
            stage 'Build'
            sh 'go build .'
            
            stage 'Deploy'
            // Do nothing.
        }
    }
}

重要(というか自分が詰まった)なのが前半部分。

    def root = tool name: 'Go1.8', type: 'go'

必要なバージョンのGoを利用するための設定がこちら。
nameのところに先程のプラグイン設定で名付けたものを入れる。
はじめに利用するときに、goが自動でダウンロードされるので、始めの一回はそこそこ時間がかかるけど、次からはすぐに使える。ちなみに、このGoのインストール先は、${JENKINS_HOME}/tools/org.jenkinsci.plugins.golang.GolangInstallation/Go1.8/
となっているようだ(最後のGo1.8は自分がつけた名前)。

    ws("${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/src/github.com/grugrut/golang-ci-jenkins-pipeline") {
        withEnv(["GOROOT=${root}", "GOPATH=${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/", "PATH+GO=${root}/bin"]) {
            env.PATH="${GOPATH}/bin:$PATH"

Goに入ってはGoに従えの格言の通り、Golangらしいファイル配置になるように設定している。
1行目のwsは、カレントディレクトリを設定している。普通は${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_ID}/が、カレントディレクトリになるところを、src配下に配置するようにしている。詳細は以下のページで。

Goコードの書き方 - The Go Programming Language

次に2行目は、GOROOTとGOPATHの二つの環境変数を設定している。PATH+GOで、goのバイナリの箇所を設定しているらしいけど、詳しいドキュメントが見付からず、ここは見様見真似でやってる。
GOPATH配下のbinもPATHに含めたかったのだけど、withEnvでやろうとすると、(おそらく)Jenkinsとしての変数展開と、shellの変数展開が競合してうまくいかなかったので、3行目に別途いれてる。


あとは、ソースコードの通り、チェックアウトして、depをインストールした上で、依存関係を解決、その後go vet, go testと来て、とおればbuildしておしまい。(とはいえtestでこけるのでbuildまで行かないのだけど)

結果

f:id:grugrut:20170410201344p:plain

こんな感じで、testにこけてることが確認できた。

なんとなく動いてる気はするけど、もっと効率の良いやりかたがありそうなので、ご存知の方いたら教えてください!!