GithubとJenkinsを連携させてアプリケーションを自動デプロイさせる。

#  GithubとJenkinsを連携させてアプリケーションを自動デプロイさせる。
## はじめに
　現在卒業論文でSpringBootを使ってデータをDBに貯めるシステムを作っている。
データの入力自体は自分以外の人に手伝ってもらうためシステムが出来上がったところはサーバーにあげて運用しつつ、完成していない機能をローカルで開発し並行しながら進めていきたい。
そこで、機能が完成したらGithubにpushし、それをトリガーにしてサーバーに自動デプロイできれば、運用システムを止めることなく、（実際には数秒止まる）新しい機能が実装されたシステムをユーザー（手伝ってくれる人）に使ってもらうことができる。
　そこでローカルから、git hubのプライベートリポジトリにgit pushしたらgithub webhooksがjenkinsにhttpリクエストを送り、それをトリガーにjenkinsがgit cloneしてspringアプリケーションをビルドし実行するというシェルスクリプトを実行するようにした。
注：一応Spring/SpringBootアドベントカレンダー１５日目の記事です。笑
## 開発環境

Java 1.8
Jenkins 2.891
Git 1.8.3.1
Github
CentOS 7.2　

## 設定方法
### jenkinsの設定
#### 新規ジョブ作成
　新規ジョブ作成作成からJob名を入力しフリースタイルプロジェクトのビルドを選択しOKをおす。
<img width="1074" alt="スクリーンショット 2017-12-15 10.46.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/136442/a7301041-6c32-cbe3-9d20-8fd3b5cd25da.png">

#### Httpリクエストの受信URL設定
　そうすると設定画面が出るので、ビルド・トリガの所のリモートからビルドにチェックし、認証トークンを入力。
認証トークンはなんでも良い。例えば認証トークンをSecretとするとJENKINS_URL/job/New/build?token=Secretがwebhooksがhttpリクエストを送信する場所となる。
JENKINS_URLの部分は自分のjenkinsが動作するURLとなる。
とりあえず一旦保存ボタンを押し保存。
### Github Webhooksの設定
Githubには特定のイベントが起きたら指定URLにHTTPリクエストを送信するWebhooksという機能がある。
それを今回使った。
デプロイしたいシステムのGithubリポジトリを開きSettingを開きWebhooksからAdd webhooksを選択。
<img width="1100" alt="スクリーンショット 2017-12-15 12.03.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/136442/6c99f9a5-863f-259f-8fad-420c32a7716e.png">

Payload URLに先ほどJenkinsで設定しHTTPリクエストを受信するURLを記述。
URLに記述する際にログインユーザー情報を追加する必要がある。
URLは
`http://[USER_ID]:[API_TOKEN]@[JENKINS_HOST]/job/[JOB_NAME]/[build|buildWithParameters]?token=[TOKEN_NAME]`
User＿IDとAPIトークンはjenkins→jenkinsの管理→ユーザーの管理→設定アイコンをクリック→APIトークンの表示で見ることができる。
Content typeはデフォルトの`application/x-www-form-urlencoded`を選択。
Secretは空欄。
Which events would you like to trigger this webhook?の欄は今回pushイベントをトリーがにしたいので
Just the push eventにチェック
そしてAdd webhooksを押してRecent Deliveriesの欄に緑のチェックがついていれば設定完了。
403エラーが出た場合はjenkinsのcsrfトークンのチェックを外すとできる。セキュリティ的にはよろしくない。

### jenkinsユーザーでgithubにsshできるようにする。
#### jenkinsユーザの公開鍵、秘密鍵を作成
jenkinsをインストールした際にjenkinsユーザーができているはずである。
そのjenkinsユーザのホームディレクトリは/var/lib/jenkinsである。ここに.sshディレクトリを作りそこに認証用の公開鍵と秘密鍵を生成する。

``` 
$ cd /var/lib/Jenkins
$ sudo mkdir .ssh
$ sudo ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /var/lib/jenkins/.ssh/id_rsa
Enter passphrase (empty for no passphrase):(enter)
Enter same passphrase again:(enter)
```

これで鍵が生成される。
#### 自分のGithubのアカウントにjenkinsユーザーの公開鍵を登録
<img width="1051" alt="スクリーンショット 2017-12-15 13.01.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/136442/af35c4ab-474f-cd0b-790a-5df5c6f7524a.png">
 `cat .ssh/id_rsa.pub`で出力された鍵の情報をgithubユーザの鍵に追加する。
 方法はgithubの右上のユーザアイコンを右クリックしSetting→SSH and GPG keysをクリック。new ssh keyでtitleを適当に入れて、
 keyのところにさっきの`cat .ssh/id_rsa.pub`で出力された鍵の情報をコピーアンドペースト。
 Add ssh keyをクリックして登録が完了した。
 これができたら一度githubにsshしてみよう。
 `sudo -u jenkins ssh -T git@ssh.github.com`
 Hi 〜〜〜〜〜! You've successfully authenticated, but GitHub does not provide shell access.と出ればsshが成功している。
できない人は443ポートでアクセスして見る。
`ssh sudo -u jenkins ssh -T -p 443 git@ssh.github.com`
これでsshが成功したら`/var/lib/jenkins/.ssh`にconfigファイルを作る。

#### /var/lib/jenkins/.ssh/configを作る。(先ほどsshできなかった人)
以下のコマンドを実行。

```
$ cd /var/lib/jenkins/.ssh  
$ sudo vi config
```  
以下configの内容

```:.ssh/config
Host github.com
    User git
    Hostname ssh.github.com
    Port 443
```
これを設定して

```
$ sudo -u jenkins ssh -T git@github.com
```
で先ほどの
Hi 〜〜〜〜〜! You've successfully authenticated, but GitHub does not provide shell access.が出れば設定完了。
できない人は`id_rsa`や`config`の権限を変えたり、所有者をjenkinsに変えたり、`/var/lib/jenkins/.ssh/known_hosts`を作って同様に権限、所有者をjenkinsにすれば解決するはず。

### 再びjenkinsの設定
先ほど作ったJobの設定をする。
左上の設定をクリックする。
ビルドの欄のビルド手順の追加をクリックしシェルの実行をクリック。
そこに以下のシェルを追加


```
#前に残っているspringプロセスを削除してspringアプリケーションを止める。
ps aux | grep java | [ビルド後のjarの名前].jar | grep -v sudo | awk '{print "kill -9 " $2}' | sudo  sh

#springアプリケーションをデプロイするディレクトリに移動する。今回は/var/webapp/spring/にデプロイすることにした（権限とか所有者とか設定済み）
cd /var/webapp/spring/

# 前にgit cloneしたアプリケーションの削除
sudo rm -rf [リポジトリ名]

#git cloneする。
git clone [リポジトリのssh用のurl]

#cloneされたリポジトリのルートディレクトリに移動
cd [リポジトリ名]

# Mavenでビルドする。ビルドするとプロジェクトのルートディレクトリにtargetディレクトリにspringの実行可能jarファイルができる。
sudo ./mvnw clean package

#jarファイルの実行　&でバックグラウンドで実行している。--server.portで好きなポートで実行できる。
sudo java -jar ./target/[ビルド後のjarの名前].jar --server.port=8080  &
```
これで保存して、設定は以上。
jarをバックグラウンドで実行するとログがわからなくなるのでspring-bootのapplication.propartiesに以下の記述をかくとプロジェクトのルートディレクトリ以下に/logs/spring.logというログファイルができそこにログが吐き出される。

```:/src/main/resource/application.proparties
logging.file=./logs/spring.log 
```

## テスト
何かプロジェクトに変更を加えてgit pushして見る。
そうするとjenkinsジョブが起動し、Jobが成功すればば完了。
ブラウザで自分のアプリケーションのURL打って実行されていればOK!

## おわりに
今回は研究室の先輩にお手伝いしてもらった。
Special thanks　[@cappyzawaさん](https://qiita.com/cappyzawa)、しょうたろうさん！！！！  

## 参考文献  
[JenkinsとGitHubのWebhook連携の整理 | Aiming 開発者ブログ](https://developer.aiming-inc.com/infra/jenkins-github-webhook-collaboration/)