LoginSignup
23
32

More than 5 years have passed since last update.

初めての Jenkins と Declarative Pipeline

Last updated at Posted at 2018-02-09

初めての Jenkins と Declarative Pipeline

勉強のために手元の Ubuntu 16.04 に Jenkins を入れてみた。仕事でたまに使っているが自分で設定するのは初めてだ。最新版はかなり変わってて面白かった。特に Jenkinsfile というテキストファイルで設定を記述する所と、最初から build agent docker を使う事前提になっている(?) のが興味深い。また、オプションで Blue Ocean プラグイン というのを使うと CircleCI のようなイマドキな画面に早変わりする。人気のある OSS 製品が陳腐化するというのは珍しくないが、こうして進歩を止めない姿勢は素晴らしい。

apt でインストール

Download の説明に従う。自動更新が使える Jenkins Debian packages が楽そう。

Jenkins の公開鍵を apt-key で apt に保存する。

wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -

Jenkins のエントリを sources.list.d に追加

sudo sh -c 'echo "deb https://pkg.jenkins.io/debian-stable binary/" > /etc/apt/sources.list.d/jenkins.list'

インストール

sudo apt-get update
sudo apt-get install -y jenkins

これで自動的に 8080 ポートで起動する。ポート番号を変えたい場合は /etc/init.d/jenkins の HTTP_PORT を変更する。

あと、どうやら docker を使っているらしいので docker グループに入れておく。

gpasswd -a jenkins docker
sudo systemctl restart jenkins

余談だが dpkg -L jenkins でパッケージの中を見ると起動スクリプトが /etc/init.d/jenkins にある。最近の自動起動は systemd に変わったはずなのでどういう仕組なのかなと思ったら、スクリプトの LSB ヘッダという物を使って systemd-sysv-generator で systemd service を自動生成しているらしい。

Post-installation setup wizard

初回起動時だけ色々設定が必要。インストールが完了してブラウザで 8080 ポートにアクセスすると、初期化画面が表示される。

  • Unlock Jenkins: 指示に従って /var/lib/jenkins/secrets/initialAdminPassword にあるパスワードを打ち込む。
  • Customizing Jenkins with plugins: インストールするプラグインを選べるらしいが、良くわからないので Install suggested plugins にした。
  • Creating the first administrator user: ユーザ名とパスワードを入れる。OS のユーザ名とかとは関係なく、Jenkins 内だけのユーザ管理。
    • あとで Manage Jenkins > Configure Global Security > でユーザ管理方法を選べる。

Pipeline の練習

  • New Item を選ぶ。
  • 適当にアイテムに名前を付ける。
  • Multibranch Pipeline を選ぶ
  • Add Source で適当にビルドしたいプロジェクトを選ぶ
    • Github のプライベートレポジトリにアクセスしたい時、GitHub personal access tokens を使う。
      • Personal access tokens のページで Generate new token を押す
      • scope: "repo" を指定して生成
    • Credentials: Add
      • Kind: Username and password
      • Username: github ユーザ名
      • Password: 作った Github personal access token
      • この内容はメニューの Credentials で編集出来る。
    • Owner: github のユーザ名や Organization name を入れる。
    • Repository: 今までの設定が正しいとレポジトリを選択出来る。
  • Scan Repository Triggers
    • Periodically if not otherwise run: チェックして、更新頻度を入れる。
    • Jenkins がファイアウォール内にある時は webhook を受け取れないので、ポーリングして更新を知る。
  • Save

これで何かが走るが特に何も起こらない。そこでレポジトリに Jenkinsfile という名前の以下のようなファイルを作ると Docker image の node 上で npm --version を実行する。


pipeline {
    agent { docker 'node:8.9.4' }
    stages {
        stage('build') {
            steps {
                sh 'npm --version'
            }
        }
    }
}

この文法は Groovy という物らしいが、知らなくても使える。この Jenkinsfile を編集する事でビルド環境を作るが、多少引っかかる部分があったので以下に書く。

トラブルシューティング

  • レポジトリが private な submodule を持っている場合。
    • Jenkins の git 機能で submodule の振る舞いを変える事が出来る。
    • Branch Sources > Behaviors > Advanced sub-modules behaviors
      • Use credentials from default remote of parent repository
  • Error: EACCES: permission denied, mkdir '/.npm' というエラーが出てしまう。
  • Github のビルド結果のリンクが unconfigured-jenkins-location になってしまう。
    • Jenkins > Configure System > Jenkins Location > Jenkins URL: を設定し直す
    • デフォルトで正しい値になっていると思うが、特に設定を変えなくても Save ボタンを押すだけで直る。
  • npm update で fatal: unable to look up current user in the passwd file: no such user

    • git のバージョンが古いとこのエラーが出る らしい。
    • また、HOME を適当に . とかにしていても出るので注意。

      git config --global user.name hoge  # unable to look up のバグ回避
      git config --global user.email hoge@example.com # unable to look up のバグ回避
      
  • because the document's frame is sandboxed and the 'allow-scripts' permission is not set. が出る。

    • Manage Jenkins > Script Console で以下を入力 (セキュリティ上問題があるらしい)

      System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

Docker について

上にサラッと書いたが、このサンプルは docker を使う事前提になっている。プロジェクトをビルドするためには対象ごとに色々な種類やバージョンの開発環境が必要があるのだが、混ざると危険だ。そこで、docker を使ってプロジェクト専用の環境を用意すると管理が楽だ。具体的には例のように agent { docker 'node:6.3' } と記述すると node 6.3 が入った開発環境(Docker イメージ)が出来る。こうした開発環境を自分で作っても良いし、誰かが作った出来合いのやつを Docker Hub からもらってもよい。例えば 6.3 の代わりに node:8.9.4 のように指定すると別のバージョンの node でビルド出来る。

docker ビルド環境は手元の環境と異なるので Jenkinsfile を書く前にちゃんとビルド出来るか試したい。そこでこんな風に手動で docker でビルドしてみた。

$ git clone git@example.com:example/example.git
$ docker run -it --rm -u $(id -u) -e HOME=/work -w /work -v $PWD/example:/work node:8.9.4 bash
I have no name!@f748fa069894:~$ git config --global user.name hoge  # unable to look up のバグ回避
I have no name!@f748fa069894:~$ git config --global user.email hoge@example.com # unable to look up のバグ回避
I have no name!@f748fa069894:~$ npm install
I have no name!@f748fa069894:~$ npm run build

docker run の引数は以下のとおり

  • -i: STDIN を開く
  • -t: pseudo-TTY を割り当てる
  • --rm: 実行後コンテナ削除
  • -u: 実行ユーザを指定
  • -e: 環境変数を指定
  • -w: 実行ディレクトリを指定
  • -v: ホスト位置:コンテナ位置 でホストのディレクトリをコンテナから見えるようにする。
  • イメージ名
  • 実行コマンド

もうちょっと実用的な Jenkinsfile

実際に使っている Jenkinsfile を示します。Cordova というツールを使って Android アプリを作るための物です。たったこれだけですが、十分実用になります。

pipeline {
  agent {
    docker {
      image 'beevelop/android-nodejs:v8.9.4'
      args '-e HOME=.'
    }
  }

  triggers {
    cron('H 15 * * * ')
  }

  stages {
    stage('build') {
      steps {
        sh 'npm --version'
        sh 'npm install'
        sh 'npm run build'
        sh 'npx cordova build'
      }
    }
  }

  post {
    always {
      archiveArtifacts artifacts: 'platforms/android/build/outputs/apk/debug/*.apk', fingerprint: true
    }
  }
}
  • トップレベルは pipeline と書かれたブロック。中に agent, stages, steps, post がある。
  • agent: Pipeline が実行される環境を書く。
    • ここではビルド環境 Docker image として適当に検索して出てきた android-nodejs というのを使っている。有り難い。Cordova が入ったイメージもあったが、Cordova は package.json でローカルにインストールした方が確実に動くので Cordova 本体は無い方が良かった。
  • stages: ビルド手順全体
    • stage: ビルド手順を分けるのに使う。
      • steps: ビルドコマンド
  • post: stage 終了後実行する step を書く。
    • always: 無条件に実行。
    • success: にすると stages が成功した時だけ実行。
      • archiveArtifacts というのを使うとビルド結果を Jenkins からダウンロード出来るようになります。
  • environment: 環境変数を設定。
    • pipeline や stage の中に記述する。
    • Jenkins 環境から credentials() でパスワードを渡せる。
  • options: プラグイン全体の設定。
    • pipeline や stage の中に記述する。
    • buildDiscarder: 保存回数の指定
    • timeout: タイムアウト設定
  • parameters: パラメータの設定
  • triggers: Pipeline を実行するタイミング
    • webhook で実行するタイプの Pipeline では不要。
    • この例では、webhook 以外に定期的にビルドしたいので追加した。
    • cron('H 15 * * * ') のようにすると、毎日 15 時の適当な時間にビルドが走る。
  • tools: ビルドで使うツールを指定すると自動インストールされる。
    • maven, jdk, gradle を指定出来る。
    • ツールは事前に Manage Jenkins > Global Tool Configuration で設定する必要がある。
  • input: stage 内に記述すると、実行中に停止して何か入力出来るらしい。
  • when: stage を実行するかどうか条件に応じて決められるらしい。
  • pararell: stage を並行して実行出来る。

小技

  • 常に最新の submodule でビルドする。この設定で submodule を commit しなくても最新になります。
    • Configure > Branch Sources:
      • Update tracking submodules to tip of branch: check
        • git submodule update --remote が有効になる。

Jenkinsfile の文法チェック

レポジトリにいちいちコミットしないと Jenkinsfile の文法チェックが出来ないというのでは面倒なので、Jenkins は API による文法チェックの機能がある。

JENKINS_URL=(Jenkins の URL)
JENKINS_CRUMB=`curl "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"`
curl -H $JENKINS_CRUMB -F "jenkinsfile=<Jenkinsfile" $JENKINS_URL/pipeline-model-converter/validate

参考

宿題

  • Multibranch Pipeline だと submodule の設定のような細かいチェックアウト情報は Jenkinsfile ではなく Web で設定する。Jenkinsfile で設定する方法もありそうな物だが分からなかった。理想はレポジトリと Jenkins のパスだけを Web で指定して残りは全部 Jenkinsfile に書きたい。参考になりそうな情報:

  • Pipeline: Multibranch

  • Pipeline: SCM Step

  • Snippet Generator

23
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
32