Jenkinsのジョブをソースコードとしてバージョン管理したい


調べると過去の先人達の記事が幾つか出てきますが、私のしたい事とはちょっとずつ違っていたので、あれこれやってみた事をまとめてみました。

## やりたいこと

* Jenkinsのジョブ設定 (とPipelineコード) のみをバージョン管理したい
	* ``$JENKINS_HOME/jobs/{job-name}/config.xml``
* それ以外はバージョン管理しない
	* ジョブ履歴
	* ジョブワークスペース
	* 認証情報
	* ユーザー情報
	* etc...
* Jenkinsの動作環境の構築手順もコード化したい

## 出来たもの

動くものがここ↓にあります。

* https://github.com/megmogmog1965/version-controlled-jenkins

> 動作環境:
> → Linux系OS, docker: 17.09.0-ce, docker-compose: 1.16.1

## うごかしかた

githubからコードをcloneします。

```
$ git clone https://github.com/megmogmog1965/version-controlled-jenkins
```

コンテナを起動します。 (ビルドも勝手にされます)

```
$ cd /path/to/version-controlled-jenkins/
$ docker-compose up -d
```

ブラウザでアクセスします。

* http://localhost:8080

> ホストマシンの ``./jenkins_home/secrets/initialAdminPassword`` に Administrator password があります

起動時点で既にジョブ "Build docker image" があります。

* ![jenkins-jobs.png](https://qiita-image-store.s3.amazonaws.com/0/60131/42315513-841c-4e8e-25de-237914e93c4c.png "jenkins-jobs.png")

中身は Jenkins Pipeline ジョブです。[docker/labs.git] をcloneしてImageをビルドします。

```
node {
    stage('Clone git repository') {
        git url: 'https://github.com/docker/labs.git', branch: params['branch']
    }
    stage('Build docker image') {
        sh "cd beginner/flask-app/ && docker build -t ${params.image_name}:${params.image_tag} ."
    }
}
```

もちろん新規に追加することもできます。

* ![new-job.png](https://qiita-image-store.s3.amazonaws.com/0/60131/87ed533f-e228-d4eb-47f2-09605ff55ecc.png "new-job.png")

追加したジョブ設定は ``git add .`` でバージョン管理対象にできます。その他の設定・データの類は無視されます。

```
$ git add .
$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:

	new file:   jenkins_home/jobs/new_job/config.xml
```


## しくみ

* [Dockerfile] / [docker-compose.yml] でJenkins動作環境をコード化します
* ``$JENKINS_HOME`` をgitでバージョン管理します。但し ``.gitignore`` で ``$JENKINS_HOME/jobs/{job-name}/config.xml`` 以外を全て管理対象から外します

```
.
├── .gitignore
├── Dockerfile
├── docker-compose.yml
└── jenkins_home
    └── jobs
        └── {ジョブ名}
            └── config.xml
```

### Dockerfile

[Jenkins公式のImage] を元にカスタマイズして作ります。
ジョブが必要とする環境 (dockerコマンドとか, java, mvn, npm, etc...) の構築はここでソースコード化します。

```docker
FROM jenkins:2.60.3-alpine

# using root.
USER root

# setup local environment.
RUN apk upgrade --update && \
    apk add --no-cache --update docker curl
```

### docker-compose.yml

コンテナの立ち上げ方をソースコード化します。

* ホストマシンの ``./jenkins_home`` ディレクトリをコンテナの ``$JENKINS_HOME`` にマウントします。Jenkinsのデータはホストマシン上で永続化されます
* ホストマシンの ``./jenkins_home`` はジョブ設定 ``config.xml`` だけがgitバージョン管理されます

```yaml
version: '3.1'
services:
  jenkins:
    build: .
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - ./jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
```

> ``/var/run/docker.sock:/var/run/docker.sock`` をマウントしているのは、Jenkinsジョブがdockerコマンドを使える様に、docker in docker の為です。これのせいでWindowsで動かないので、なくてもいいです。

### .gitignore

ホストマシンの ``./jenkins_home`` ディレクトリへのgit管理対象の除外設定です。
ジョブ設定 ``$JENKINS_HOME/jobs/{job-name}/config.xml`` のみがバージョン管理対象になります。

```
# manage: "jenkins_home/jobs/{job-name}/config.xml"
!jenkins_home/
jenkins_home/*
!jenkins_home/jobs/
jenkins_home/jobs/*
!jenkins_home/jobs/*/
jenkins_home/jobs/*/*
!jenkins_home/jobs/*/config.xml
```


[Dockerfile]:https://docs.docker.com/engine/reference/builder/
[docker-compose.yml]:https://docs.docker.com/compose/
[docker/labs.git]:https://github.com/docker/labs
[Jenkins公式のImage]:https://hub.docker.com/_/jenkins/