流行りのCIを導入して卒論を爆速で書き上げる

# モチベーション
大学生にとっての最終試練…
はい。卒論執筆の季節がもうすぐやって参ります。:qiitan-cry:

文字数多いと校正とかめんどくさいなぁ。

### うーん、CIで自動化しちゃお！w

世間はzoomだGoogle Meetだと躍起になっていますが、**時代はCIですよCI。**:trollface:

# CIとは？

ここでCIについて軽くおさらいしておきます。:pencil2:

> CIとは、Continuous Integrationの略で、継続的インテグレーションと呼ばれています。
CI(継続的インテグレーション)では、開発者が自分のコード変更を頻繁にセントラルリポジトリにマージし、その度に自動化されたビルドとテストを実行します。
小さなサイクルでインテグレーションを繰り返し行い、インテグレーションのエラーを素早く修正することによりチームは統合されたソフトウェアをより迅速に開発できるようになります。
--- CI(継続的インテグレーション)とは | CloudBees Jenkins より引用

まとめると、成果物(文章やコードなど)がある程度完成する度に自動テストでチマチマ修正して、計画的且つ迅速に開発・作成を行う手法のことです。

![ci_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/1731d039-d9d0-13cb-5dd8-660c045890a3.png)
--- CI(継続的インテグレーション)とは | CloudBees Jenkins より画像引用

簡単に言えば、夏休みのドリルを取り組む度に丸つけをして、間違いを修正しながら確実に学力をつけていくイメージですね!
(もちろん僕は最後にまとめて丸つけをするタイプでした。笑)

# 今回やること
そんなわけで導入しましょう流行りのCI。:qiita-fabicon:

導入したい必須機能は以下の通り。

- 文章中の間違いとかを自動で校正してくれる。
- 校正結果が簡単に確認できる。
- ファイルを投げたら教授に自動通知してくれる。
- 教授が簡単にファイルをダウンロードできる。

あとは補助機能として、

- 多数のユーザーでも各々でCIが動く。
- 内容がそれぞれ別々に通知される。

とかあったらゼミ仲間にも使ってもらえそう。:edit-request:

# 実装
完成後のファイルパスは以下のようになります。

```
Sotsuron_CI/ ---- .travis.yml (2-1.で作成。3-2.で追記。)
              |
              |-- .textlintrc (2-2.で作成)
              |
              |-- sample_sotsuron.docx (卒論本文)
              |
              |-- README.md (リポジトリ作成時に自動生成されただけ。無しでも支障なし。)
```

## 1. CIを行う環境を整える

とりあえず今回は[Travis CI](https://travis-ci.com/)を使ってみます。(無料だし。)
![Travis-CI-logo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/7fa3150f-ee40-bce7-efb5-aa45b55c2b6a.jpeg)
--- Travis CI | narito ブログ より画像引用

よってCIを行う環境は**Githubリポジトリ**になります。
![161221.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/9c0c9ded-6e3c-d883-6c7b-1fdeff87aa13.jpeg)
--- Travis CI から GitHub へ git push を行う設定 | Tips Note by TAM より画像引用

簡単すぎるので割愛しますが、ここでは以下の作業を行います。

1. [新規リポジトリを作成](https://prog-8.com/docs/github-pages)
2. [Travis CIと連携](https://photo-tea.com/p/17/javascript-test-how-to-5/)

↑もし手順とか忘れた場合は、各リンク先のページを参考にしてください！
※ Travis CIのリンク先での「COVERALLSと連携させるステップ」は不要ですので飛ばしてOKです。

## 2-1. 文章の自動校正を導入

ここからTravis CIで行う機能をコードとして実装していきます。

今回、文章の自動校正には[textlint](https://github.com/textlint/textlint)を使用します。
ですが、textlintはMicrosoft Wrodの文書(.docx)に非対応であるため、文書の形式を変更させなければ校正できません。
そこで校正する前にMicrosoft Wrodの文書(.docx)をMarkdown文書(.md)に変換する[pandoc](https://pandoc.org/)を利用します。

つまり流れとしては、

1. pandocで卒論を.docx形式から.md形式に変換。
2. textlintで文章を自動校正。

という感じです。

それではリポジトリに`.travis.yml`を作成して以下のコードを追加します。

```.travis.yml
sudo: false
language: node_js
node_js:
  - '8.12.0'
before_script:
  - sudo apt-get update -y
  - sudo apt-get install pandoc libghc-pandoc-prof
  - pandoc -s sample_sotsuron.docx -t markdown -o sample_sotsuron.md
  - npm init -y
  - npm install textlint --save-dev
  - npm install textlint-rule-preset-ja-technical-writing --save-dev
  - npm install npx --save-dev
script:
  - npx textlint --preset ja-technical-writing sample_sotsuron.md -f pretty-error
```

textlintがnode_jsで作成されているため`language`は`node_js`を指定します。

ちなみにTravis CIはUbuntuのDockerコンテナ上で動くため、pandocやtextlintのインストールは`apt-get`で行います。

また、今回の文章校正ルールとして、
`textlint-rule-preset-ja-technical-writing`
を指定し、[技術文書向けのtextlintルールプリセット](https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing)を使用しています。

`npm`で必要なものをインストールして、最後に`npx`でtextlintを起動させています。
(ちなみにtextlintコマンド内の`-f pretty-error`はtextlintの出力形式を表すオプションです。)

## 2-2. textlintルールプリセットの修正

今回、技術文書向けのtextlintルールプリセットを用いて卒論を校正するわけですが、
**デフォルト設定のルールは結構厳しめです…** :innocent:

このままでは卒業が危うくなってしまうので、適宜ルールを修正します。

リポジトリに`.textlintrc`を作成して以下のコードを追加します。

```name:.textlintrc
{
  "filters": {},
  "rules": {
    "preset-ja-technical-writing": {
      "sentence-length": {
          "max": 150
        },
      "max-kanji-continuous-len": {
          max: 10
      },
      "max-comma": {
        "max": 5
      },
      "ja-no-mixed-period": false,
      "ja-unnatural-alphabet": false,
      "no-exclamation-question-mark": false,
      "no-unmatched-pair": false,
    }
  }
}
```

`preset-ja-technical-writing`の内容を以下のように修正しています。

`sentence-length`: 1文の文字数 (最大:100→150に変更)
`max-kanji-continuous-len`: 連続する漢字長 (最大:6→10に変更)
`max-comma`: 1文中のカンマ数 (最大:3→5に変更)
`ja-no-mixed-period`: 文末の句点記号 (falseで校正ルールから外す)
`ja-unnatural-alphabet`: 不自然なアルファベットをチェック (falseで校正ルールから外す)
`no-exclamation-question-mark`: 感嘆符(!, ?)をチェック (falseで校正ルールから外す)
`no-unmatched-pair`: 1文中の[]や「」のペアをチェック (falseで校正ルールから外す)

**これらの記述はtextlintを起動する際に内部的に自動で参照されます。**
**(`.travis.yml`の修正も不要。)**

※記載した以外のルールはデフォルト設定で適用されています。

## 3-1. CIの結果をSlackに自動通知

次に卒論ファイルが更新されたことをSlackに自動通知させます。

まずはSlackとTravis CIを連携させます。
先人の知恵をお借りして、以下のQiita記事を参考にしてください。

[図解: Travis CIの結果をSlack通知する方法](https://qiita.com/nwtgck/items/17840855cb76f60fa1fe)

ただし、今回 **2-1. 文章の自動校正を導入** で作成した`.travis.yml`は以下のように変更してください。

```.travis.yml
sudo: false
language: node_js
node_js:
  - '8.12.0'
before_script:
  - sudo apt-get update -y
  - sudo apt-get install pandoc libghc-pandoc-prof
  - pandoc -s sample_sotsuron.docx -t markdown -o sample_sotsuron.md
  - npm init -y
  - npm install textlint --save-dev
  - npm install textlint-rule-preset-ja-technical-writing --save-dev
  - npm install npx --save-dev
script:
  - npx textlint --preset ja-technical-writing sample_sotsuron.md -f pretty-error
### 以下の部分を追加 ###
notifications:
  email: false
  slack:
    rooms:
      - secure: <YOUR TOKEN>
    template:
      - "Sotsuron checked on `sample_sotsuron`."
      - "Result: <https://travis-ci.org/github/USER_NAME/REPOSITORY_NAME/branches|%{message}>"
      - "----------------------------------------"
      - "Download Sotsuron: https://github.com/USER_NAME/REPOSITORY_NAME/raw/%{branch}/sample_sotsuron.docx"
```

`secure`の値となっている`<YOUR TOKEN>`は[図解: Travis CIの結果をSlack通知する方法](https://qiita.com/nwtgck/items/17840855cb76f60fa1fe)と同様にAPIトークンをご自身で設定してください。

`template`はSlackに通知されるメッセージのテンプレートです。
またテンプレート内のURLは以下の通りです。

- Result : CIの実行結果リンク
- Download Sotsuron : ブランチに更新された卒論ファイルのダウンロードリンク

URL内部の`USER_NAME/REPOSITORY_NAME`はご自身のGitHubアカウント名とリポジトリ名に置き換えてください。

Slack上では以下のように通知されます。

![スクリーンショット 2020-08-10 1.46.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/006a3174-4b13-e037-34ca-1f35b49a95b7.png)

これで教授にいちいち連絡しなくても卒論を書き進められますね。:file:

## 3-2. 通知内容をブランチごとに分ける

最後にブランチごとにSlackへの通知内容が変更されるようにしましょう。
これは各ゼミ生にそれぞれブランチを割り当てることで複数人の卒論を管理できるようにするための実装です。

下記のように`.travis.yml`を変更してください。

```.travis.yml
### 新規追加 ###
branches:
  except:
    - master
###############
sudo: false
language: node_js
node_js:
  - '8.12.0'
before_script:
  - sudo apt-get update -y
  - sudo apt-get install pandoc libghc-pandoc-prof
## 修正 ##
  - pandoc -s ${TRAVIS_BRANCH}.docx -t markdown -o ${TRAVIS_BRANCH}.md
##########
  - npm init -y
  - npm install textlint --save-dev
  - npm install textlint-rule-preset-ja-technical-writing --save-dev
  - npm install npx --save-dev
script:
## 修正 ##
  - npx textlint --preset ja-technical-writing ${TRAVIS_BRANCH}.md -f pretty-error
##########
notifications:
  email: false
  slack:
    rooms:
      - secure: <YOUR TOKEN>
    template:
    ## 修正 ##
      - "Sotsuron checked on `%{branch}`."
      - "Result: <https://travis-ci.org/github/USER_NAME/REPOSITORY_NAME/branches|%{message}>"
      - "----------------------------------------"
      - "Download Sotsuron: https://github.com/USER_NAME/REPOSITORY_NAME/raw/%{branch}/%{branch}.docx"
    ##########
```

`branches`でmasterブランチを除外しています。アプリ開発などではmasterへのpush時にCIを発動させることが多いですが、今回はmasterをCIパイプラインの管理に使用したいのでこのように設定しました。

pandocやtextlintを実行する際に呼び出す`TRAVIS_BRANCH`はTravis CI発動時の環境変数であり、CIを動かしているブランチ名が入ります。

**よって今回はブランチ名と卒論ファイル名を一致させることで、複数人の卒論を管理できるようにしました。**

また`notifications`内に記載した`%{branch}`はSlack通知時にCIを実施したブランチ名に置き換えられる変数です。

この実装によって以下のような通知ができるようになりました。
![スクリーンショット 2020-08-10 5.16.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/b3981ec9-fddf-f77e-c064-39390dcbff4c.png)
※ブランチ名は`example_user_sotsuron`で作成しています。


# 最後にCIを動かしてみる

最後に今回実装した卒論CIを[GitHub.com](https://github.com/)のGUIで動かして確認してみます。

## 1. ブランチの作成

まずはmasterを元に新規ブランチを作成します。
![スクリーンショット 2020-08-10 4.11.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/84cc37ca-8d48-0535-9022-5e9c42abaa5d.png)
左上の`master`と表記されているブランチボタンをクリックして`Switch branches/tags`メニューを開き、テキストボックスにブランチ名を記入して下の`Create branch: ブランチ名 from 'master'`をクリックします。

![スクリーンショット 2020-08-10 4.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/a0e07758-9518-a760-a6a2-5bb588afda20.png)
すると新しくブランチが作成されました。
(次回以降、作成済みブランチに切り替えるには左上のブランチボタンから選べます。)

## 2. ファイルのアップロード

次にファイルをアップロードします。
![スクリーンショット 2020-08-10 4.22.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/fe697e9f-8b21-a177-2f5d-f77a1cb7bc19.png)
右上の`Add file`ボタンを押して`Upload files`を選んでください。

![スクリーンショット 2020-08-10 4.23.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/0e4dbb35-d49e-53e3-c1d0-2861fdc2164a.png)
ファイルを画面中央にドラッグ&ドロップするか、あるいは画面中央の`choose your files`をクリックしてファイルを選択するか、いずれかの方法で卒論のファイルをアップロードします。
**※アップロードする卒論のファイル名は必ずブランチ名と一致させてください！**

![スクリーンショット 2020-08-10 4.26.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/b0a4c61b-6067-a563-560b-53771adeac9e.png)
卒論のファイルが読み込まれて画面中央にファイル名が表示されたら、ブランチ名と卒論ファイル名が一致していることを再度確認します。

**※アップロードする卒論のファイル名がブランチ名と一致していない場合はCIがうまく起動しません！**

ブランチ名と卒論ファイル名の一致が確認できたら、下部の`Commit changes`に変更事項に関するメッセージ(任意)を記入して緑の`Commit changes`ボタンを押します。

これで卒論ファイルのアップロードが完了しました。

## 3. Slack通知の確認

それではSlackに移動してCIの通知を確認してみましょう。
![スクリーンショット 2020-08-10 4.39.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/43b02b12-ccbb-82bd-67f1-0fb835b6a4d2.png)
卒論ファイルをアップロードしてから数分後、上記のような通知がされていれば成功です！

#### …って、ビルドエラーしてるし。泣

## appendix: Travis CIの結果確認

そんな時はSlackに通知されたメッセージの`Result`にあるリンクからTravis CIを確認してみましょう！

![スクリーンショット 2020-08-10 4.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/87ea54d2-4feb-14b4-7519-6cfc13b23bb6.png)
はい。Travisさんからしっかり:x:もらってますね。笑
右のバツマークから詳細を確認できます。

![スクリーンショット 2020-08-10 4.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/4f0c1dbb-a16a-acab-6839-54ed8f7fb884.png)
今度は結果の下部にログ画面が表示されました！
このログ画面からCIのどこでどのようにエラーが発生したのかが確認できます。

少しスクロールしてエラー内容を確認してみましょう。

![スクリーンショット 2020-08-10 4.48.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/73fd3371-41fb-2acc-b9d8-39554c537f44.png)
### どうやらtextlintから色々と指摘されていますね。:japanese_goblin: 笑
このようにtextlintによって文章の校正を自動化することができました。

とりあえずログを最後まですっ飛ばしてみましょう。

![スクリーンショット 2020-08-10 4.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357086/d9a034c4-0d0d-65fb-287f-a89faca078db.png)
### エッッッッッッッッッッッッッッ! 114 problems !!!

私の卒論生活はまだまだ長そうです…:writing_hand: 涙

あと最後に、:lgtm:よろしくお願いします！

# 参考リンク
[textlintで日本語の自動校正サービスを作ってみた！](https://liginc.co.jp/342157)
[Wordファイル(.docx)をMarkdownへ変換する](https://gist.github.com/tomo-makes/b03e910ea7095bbe2c98de5be828dfba)
[Setting Up Slack Build Notification in Travis CI for Github Project](https://axdlog.com/2018/setting-up-slack-build-notification-in-travis-ci-for-github-project/)