オフラインJenkins実験環境構築メモ

# 概要
実際に使用されているJenkinsマシンを汚さずに手元のWindows環境で実験するために、JenkinsとSubversionの環境を構築した際のメモ。
Pipeline(ジョブ)で利用するGroovyスクリプトをバージョン管理して、複数のPipelineから共有できるようにする。

- 環境
    - Windows 10
    - Jenkins 2.222.3 
    - Subversion 1.13.0
    - Tortoise SVN 1.13.1

# Subversion

## インストール

`Tortoise SVN`をコマンドラインツール込みでインストール

## ローカルリポジトリ作成

参考: [【svn】コマンドのみで手っ取り早くローカルPCにsvnリポジトリ作ってバージョン管理できるとこに持ってく方法](https://qiita.com/sksmnagisa/items/8c3905e073084b3cac16)

パス指定でハマったので具体的なパスを指定したコマンド例を掲載。

```bat
cd f:\test

@REM ローカルリポジトリ作成
svnadmin create test_rep

@REM trunk作成
mkdir trunk
svn import trunk file:///f:/test/test_rep -m "create trunk"

@REM 試しにチェックアウト
rmdir trunk
svn checkout file:///f:/test/test_rep/trunk
```

- `file:///`のスラッシュは3つ必要であることに注意
- ドライブ指定`f:/`のスラッシュは必要(なしだとcheckoutに失敗した)

```bat
> svn checkout file:///f:test/test_rep/trunk
svn: E170013: Unable to connect to a repository at URL 'file:///f:test/test_rep/trunk'
svn: E180001: Unable to open repository 'file:///f:test/test_rep/trunk'
```

# Jenkins

## インストール

公式( https://www.jenkins.io/download/ )からWindows版をダウンロードしてインストール。
余談であるが、トップぺージ( https://www.jenkins.io/ )はなぜか中文のコンテンツが表示されて、右上の言語を`English`に変えても中文のままだった。

`Blue Ocean`プラグインをインストール。

Jenkinsの言語設定はブラウザの言語設定に依存する。ブラウザの日本語の優先順位を一番上にすれば、日本語になる。

## Pipeline間のコード共有(Global Pipeline Libraries)

- 参考
    - [Jenkinsで共有ライブラリを作成してみる - ヒトリ歩き](https://kotapontan.hatenablog.com/entry/2019/08/27/235603)
    - [Jenkins Shared Libraryで快適 Jenkins 生活？ - Qiita](https://qiita.com/bols_blue/items/50b024cf423439e8e99a)

システムの設定(configure)の`Global Pipeline Libraries`を設定する。

|設定項目|値|
|---|---|
|Name|test-lib|
|DefaultVersion|jenkins|
|Retrieval method|Modern SCM|
|Source CodeManagement|Subversion|
|Project Repository Base|file:///f:test/test_rep/|

`Project Repository Base`と`DefaultVersion`に設定した内容に従ってチェックアウトされる。上の設定の場合、`file:///f:test/test_rep/jenkins`以下がチェックアウトされる。

### 共有コード置き場準備

リポジトリ(file:///f:test/test_rep)に`jenkins`ディレクトリ追加。以下のように共有コードを配置してコミット。
※`jenkins`=`DefaultVersion`に指定した値

```sh
file:///f:test/test_rep/jenkins
+- src                     # Groovy source files
+- vars
|   +- runBat.groovy       # global
+- resources               # resource files (external libraries only)
|   +- org
|       +- foo
|           +- my_bat.bat   # static helper data
```
```runBat.groovy
def call() {
    def myBat = libraryResource'org/foo/my_bat.bat'
    return bat(myBat)
}
```
```my_bat.bat
dir
```

### ジョブ(Pipeline)作成

`Blue Ocean`の`New Pipeline`を選択すると「GitHubかBitbucketか..?」と聞かれて「どれでもないんじゃ」となるので、`Classic Item Creation`を選択。従来の`新規ジョブ作成`画面が表示される。
`パイプライン`を選択してOK。
パイプラインは以下のように記述。

```groovy:Jenkinsfile
@Library('test-lib') _
//'test-lib' = Global Pipeline LibrariesのNameに入れた値
//vars以下を読み込む場合には_(アンダースコア)
//src以下を読み込む場合はimport文を使用
pipeline {
	agent any
	
	stages {
		stage('test') {
			steps {
				runMyBat()
			}
		}
	}
}
```

### classを利用する

複雑な処理を記述する場合はclassが利用できる。`src`下にgroovyコードを配置する必要がある。この例の場合は`file:///f:test/test_rep/jenkins/src/org/foo/BatRunner.groovy`。

```src/org/foo/BatRunner.groovy
package org.foo

class BatRunner {
	def script //WorkflowScript(Jenkinsfile)のインスタンス
	//Jenkinsfileからthisを渡しておくとJenkinsfileで利用できるbatなどの関数が呼べる
	BatRunner(script) {
		this.script = script
	}
	def run() {
		this.script.echo "script => " + script.getClass().toString() //script => class WorkflowScript
		script.bat "dir"
	}
}
```
```groovy:Jenkinsfile
@Library('test-lib') import org.foo.BatRunner
//'test-lib' = Global Pipeline LibrariesのNameに入れた値
def runner = new BatRunner(this) //定義の位置は要検討
pipeline {
	agent any
	
	stages {
		stage('test') {
			steps {
				//Declarative Pipelineでメソッドを呼ぶ場合はscriptブロック内のみ
				script {
					runner.run()
				}
			}
		}
	}
}
```


# 実行
ビルド実行(Run)して`dir`の結果が表示されればOK

#メモ

- groovyファイルのエディタとしてVisual Studio Codeが使える
- `hoge()`と書くと`vars/hoge.groovy`の`call`関数が呼び出される