FORCIA CUBEフォルシアの情報を多面的に発信するブログ

textlint + Reviewdog + GitLab CI でアドベントカレンダーの校正をした話

2021.12.15

アドベントカレンダー2021 エンジニア テクノロジー

これは、Qiita Advent Calendar 2021 GitLabの15日目の記事です。

はじめに

こんにちは、フォルシアにて、旅行会社向けの web アプリケーションを開発しています、エンジニアの高橋です。普段のアプリ開発の業務のほかに技術広報も兼任しており、弊社で開催しているアドベントカレンダーの運営もお手伝いしています。

フォルシアではもともと、社内のイベントとしてアドベントカレンダーを始めましたが、2018 年からは弊社ブログ(FORCIA CUBE)にて外部の方向けに記事を公開しています。 社内のみで記事を公開していた頃は、誰かが多少締め切りをすぎても「かまへんかまへん」と言えますが、外部に公開するとなるとそうはいきません。25 日間落とすことなく記事を上げ続けるために、執筆者へのフォローや締め切り管理、ブログへのアップロードを組織的に行う必要がありました。

外部公開を始めた初年度は esa というドキュメントツールのみで記事や進捗を管理していましたが、どの記事がいつ公開なのか、レビューが終わっているのかどうかなどを一覧で見ることができず、管理がなかなか大変でした。 そこで 2020 年より、社内ですでに使用していたコードのホスティングサービスである GitLab を利用して記事を管理するようにしました。GitLab の issue 機能を使い 1 issue = 1 記事に対応させて管理するようにしたことで、かんばんボードを使って記事の進捗を管理することができるようになり、大変便利でした。以下の図のように、カラムやラベルを付けて記事を管理しています。記事自体も issue に直接記載する形式にしました。

gitlab_issue.JPG

issue の利用により進捗の管理が容易になった点はよかったのですが、その年のアドベントカレンダー運営の振り返りでは以下のような課題も上がりました。

  • レビューがやや難しい
  • せっかくなので、GitLab の CI 機能をもっと活用したい

そこで今年のアドベントカレンダーでは、 GitLab の MR 機能(マージリクエスト。GitHub の Pull Request に相当する機能)を利用してみることにしました。

MR であれば

  • 行単位でレビューが書けるため、指摘箇所がわかりやすい
  • 編集履歴を残すことができる
  • CI を活用しやすい

といった利点があります。 さらに、せっかく CI を使えるようになったので以前からやってみたいと思っていた誤字脱字の指摘、文章の構成の自動化にとりくんでみました! その内容を本記事で紹介させてください。

できたもの

投稿された記事を校正し、MR にレビューコメントをしてくれる「赤ペン博士 bot」を作りました。

03_gitlab_comment.jpg

使用したライブラリの説明

textlint

textlintは「linter」と言われるツールの一種で、記述されたプログラムや文章がルールに沿って書かれているかをチェックしてくれます。多くの linter がプログラミング言語を対象としてツールであるのに対して、textlint は自然言語を対象にしているため、文章の校正に利用できます。

textlint で適用するルールは様々なプラグインから自分で取捨選択でき、例えば以下のような項目をチェックできます。

  • 文末が「。」で終わっているかどうか
  • 日本語の誤用がされていないかどうか
  • 必要な箇所にスペースが入れられているかどうか

textlint の導入によりこれまで人力で指摘・修正していた文章の誤りを自動で検知することができるようになります。

Reviewdog

y03.png

Reviewdogは様々な linter と組み合わせて、GitHub や GitLab などのコードホスティングサービスに linter が指摘した内容をレビューコメントとして投稿してくれるツールです。これにより、GitLab に push された記事に対して、textlint を適用した結果を該当箇所にコメントできます。

余談ですが、ロゴが可愛いのも特徴です。

GitLab CI

GitLab CIは GitLab が公式に提供している Continuous Integration(CI)ツールで、GitLab 上に push されたコードに対して、トリガーや実行内容を設定して処理を行うことができます。一般的なプロジェクトではテストやデプロイを自動化するために使われることが多いですが、今回は校正を自動化するために利用しました。

Reviewdog が MR にコメントするには GitLab でアクセストークンを発行する必要がありますが、Reviewdog 用の GitLab アカウントを新規で作成し、プライベートアクセストークンを発行することで実現しました。プロジェクト単位でアクセストークンを発行することもできますが、その場合アイコンを設定できないためレビューがややたんぱくになってしまうのが難点です。

上記のツールを組み合わせ、以下のような仕組みを作成しました。

y04.png

MR が作成されたり更新されると自動で GitLab の CI が起動し、CI の中では文章に対して textlint で校正をかけ、その結果を Reviewdog が MR へのコメントとして通知してくれます。

各種設定について

次に、ツールを動かす設定をご紹介します。

package.json の設定

textlint は npm を使って導入できます。package.json を未作成のプロジェクトの場合、プロジェクトのルートディレクトリで

npm init -y
npm install --save-dev textlint

とすることで、package.json の作成と textlint のインストールが行われます。textlint の拡張パッケージ(後述)についても同様に npm からインストールできます。

gitlab-ci.yml の設定

.gitlab-ci.ymlファイルをリポジトリに作成し、GitLab 側の設定をいくつかすることで CI 機能を使うことができます。もう少し詳しく知りたいという方は、よければ以下の記事をご覧ください。

GitLab CI/CD 導入の手引き(FORCIA CUBE)

CI では使用するライブラリのインストールと、 textlint, Reviewdog の実行をしています。また、Reviewdog 実行用の API アクセストークンのキーは CI 設定の Variables に登録してあります。

image: alpine # CIで使用するdockerイメージの指定
reviewdog:
  allow_failure: true # CIに失敗してもMRをMerge可能なようにする設定
  script:
    - apk add --update git
    - apk add --update npm
    - npm install # package.jsonに登録したtextlintのインストール
    # reviewdogのinstall
    # bin/ 以下に実行ファイルがインストールされます
    - wget -O - -q https://raw.githubusercontent.com/reviewdog/reviewdog/master/install.sh | sh -s
    # textlintとreviewdogの実行
    # *.md ファイルを対象にlinterを実行しています
    - npx textlint -f checkstyle *.md | bin/reviewdog -f=checkstyle -name="textlint" -reporter=gitlab-mr-discussion

textlint のプラグイン

textlint には様々なプラグインがあり、自分の好みのルールを追加することができます。今回利用したのは以下のプラグインになります。

これらのプラグインの細かなルールは .textlintrc.jsにて設定することができます。 今回は以下のような設定で利用しています。

module.exports = {
  plugins: {
    "@textlint/markdown": {
      extensions: [".md"], // マークダウン用の拡張
    },
  },
  rules: {
    // textlint-rule-prhの設定
    prh: {
      rulePaths: ["./prh.yml"],
    },
    // textlint-rule-preset-jtf-styleの設定
    "preset-jtf-style": {
      "1.2.1.句点(。)と読点(、)": false, // 文中のピリオドとカンマを許容
      "1.1.3.箇条書き": false, // 箇条書きの文末に句点(。)以外を許可
      "2.1.8.算用数字": false, // 算用数字以外も許容する。1桁は全角でも入力できるように。
      "2.2.1.ひらがなと漢字の使い分け": true, // ひらがなにしたほうが良い漢字をサジェスト
      "4.1.3.ピリオド(.)、カンマ(,)": false, // 文中のピリオドとカンマを許容
      "4.3.1.丸かっこ()": false, // 半角丸括弧を許容
      "4.3.2.大かっこ[]": false, // 半角大括弧を許容
    },
    // textlint-rule-preset-ja-technical-writingの設定
    "preset-ja-technical-writing": {
      "no-exclamation-question-mark": {
        allowFullWidthExclamation: true,
        allowFullWidthQuestion: true,
      },
      "no-doubled-joshi": {
        strict: false,
        allow: ["か", "が", "に"], // これらの助詞は同一文中に多く登場しても許容
      },
    },
    // textlint-rule-preset-ja-spacingの設定
    "preset-ja-spacing": {
      "ja-space-around-code": {
        before: true,
        after: true,
      },
    },
    "ja-technical-writing/ja-no-mixed-period": {
      allowPeriodMarks: [":"],
    },
    "ja-technical-writing/max-ten": { max: 5 }, // 文中の「、」の数は5個まで
    "ja-technical-writing/sentence-length": false, // 文の長さは指定なし
    "ja-technical-writing/ja-no-weak-phrase": false, // 弱い表現を許容
    "ja-technical-writing/max-comma": false, // カンマの数は指定なし
    "ja-spacing/ja-space-around-code": false, // インラインコードの前後にスペースを入れなくてもよい
  },
};

phr.yml の設定

前述した textlint のプラグインの一種である textlint-rule-prh を用いることで、表現の揺れを統一することができます。phr.ymlに以下のようなルールを登録して、ライブラリ名の揺れなどを統一しました。

version: 1
rules:
  - expected: Docker
    pattern: docker
    specs:
      - from: docker
        to: Docker
  - expected: Ansible
    pattern: ansible
  - expected: Ansistrano
    pattern: ansistrano
  - expected: Kubernetes
    pattern: kubernetes
  - expected: React
    pattern: react
  - expected: Redux
    pattern: redux
  - expected: Next.js
    patterns:
      - next.js
      - Nextjs

以下のように揺れを指摘してくれます。

02_docker.jpg

おわりに

今回の仕組みを導入したことにより、人力で指摘するのはハードルが高い内容も自動でレビューできるようになり、運営チームの負担を減らしつつ記事の質を高めることができるようになったと思います。
また個人的に嬉しかったこととしては、記事を書いてくださる方達も赤ペン博士によるレビューを面白がってくださったことです。煙たがられるかなとも思っていたので、楽しんでいただけたようで作った甲斐がありました。

それでは残りの記事もお楽しみに!

この記事を書いた人

高橋優樹

サウナがはかどる季節になりました。

フォルシアではフォルシアに興味をお持ちいただけた方に、社員との面談のご案内をしています。
採用応募の方、まずはカジュアルにお話をしてみたいという方は、お気軽に下記よりご連絡ください。


採用お問い合わせフォーム 募集要項

※ 弊社社員に対する営業行為などはお断りしております。ご希望に沿えない場合がございますので予めご了承ください。