Fractal + CircleCI + Slackで効率よくスタイルガイドを構築する

# TL;DR
- スタイルガイドを構築するにあたりFractalを採用した経緯と導入方法について
- CircleCIの設定について
- 外部からのリソースを自分のプロジェクト内に格納するために`git pre-commit`を使った
- CircleCIの結果をSlackに通知するようにした

## なぜスタイルガイドを作ったか
- 共通のパーツとパターンを使用したページを多く作成する必要があったため、認識共有のために導入した
- コードを綺麗に保ちたかった
- 追加修正や運用に耐えうる何かがほしかった

### メリット
- 認識を共有できるため、複数人での制作がスムーズになる。
- cssが得意でなくてもそれなりにページを制作できる。
- コードが綺麗に保たれる

### デメリット
- スタイルガイド分の工数がかかる
- 仕様変更で条件が複雑になるにつれてつらくなる。


# Fractalとは
[デモページ](http://fractal.clearleft.com/)

- スタイルガイドを自動で生成してくれるスタイルガイドジェネレーター
- デフォルトではテンプレートエンジンの[Handlebars](https://handlebarsjs.com/)で記述する（設定すれば他のテンプレートエンジンなども使える）
- コンポーネントとドキュメントでディレクトリが分かれている。

## 導入例
都市が導入していたりするようで、以下の例だと結構モダンな手法を取り入れている。

[City of Boston](https://patterns.boston.gov/)
Web Componentsのコンポーネントもある。

[City of Ghent](https://stijlgids.stad.gent/v2/)
Atomic Designを採用している。

### 参考
[frctl/awesome-fractal#Showcase](https://github.com/frctl/awesome-fractal#showcase)

## なぜFractalを採用したか
- [公式ドキュメント](https://fractal.build/guide)がわりとわかりやすかった。
- ReactやVueのようなフレームワークであればStorybook等の選択肢があるが、マークアップによるページの作成であったためFractalでスタイルガイドを構築した。
- 本番サイトやビルドツールと楽に連携できそうだった
- UIが良いので使いやすくわかりやすい。
- 導入が比較的簡単。
- 構造やファイル構成がわかりやすい。

## 実際に導入する
### セットアップ
```bash
# グローバルにインストール
$ npm i -g @frctl/fractal
# プロジェクトを作る
$ npm init -y
# プロジェクにインストール
$ npm install --save @frctl/fractal
```

### 設定
```fractal.js
'use strict'

const fractal = module.exports = require('@frctl/fractal').create()

const mandelbrot = require('@frctl/mandelbrot');

// skinの設定
const myCustomisedTheme = mandelbrot({
    skin: "navy"
});

fractal.web.theme(myCustomisedTheme);

// タイトル
fractal.set('project.title', 'Component Library')

// コンポーディレクトリ
fractal.components.set('path', __dirname + '/components')
// ドキュメントディレクトリ
fractal.docs.set('path', __dirname + '/docs')

// 開発サーバー
fractal.web.set('server.sync', true)
fractal.web.set('server.syncOptions', { open: true })

// 書き出し先ディレクトリ
fractal.web.set('builder.dest', __dirname + '/dist')

// 静的ファイル読み込み
fractal.web.set('static.path', __dirname + '/assets')

```

### ディレクトリ構成
設定ファイルで設定したディレクトリ構成は以下のようになる。

```bash
├── assets
│   └── css
├── components
├── dist
├── docs
│   └── index.md
├── fractal.js
└── package.json
```

### 使い方
```bash
# 開発サーバーが立ち上げる
$ fractal start --sync
# 静的ファイルとして書き出し
$ fractal build
```

### コンポーネントの追加方法
`fractal.js`で設定した`components`の中に追加する。

例：
`components/button/button.hbs`

### 外部プロジェクトのcssをassetに追加する
ガイドの元となるcssが別プロジェクトのディレクトリにある場合、そのプロジェクトのディレクトリを`fractal.js`で設定して読み込むか、ガイドプロジェクト内にファイルを追加する必要がある。
また、注意点として、静的ファイル読み込みディレクトリ直下に`index.html`が存在するとそちらが反映されスタイルガイドの画面が出てこなくなる。
今回の場合、CIを回すため`Git`の`Pre-commit Hook`でスタイルガイドプロジェクト内に元となるcssを生成することにした。

```bash
$ node-sass --include-path scss [元のscss] ./assets/css/style.css --output-style compressed
```


# CIを設定する
```config.yaml
version: 2
jobs:
  build:
    docker:
      - image: circleci/node:9.3.0-stretch
    steps:
      - checkout
      - restore_cache:
          keys:
            - npm-{{ checksum "package.json" }}
      - run:
          name: npm install
          command: npm install
      - run:
          name: Build
          command: npm run fractal:build
      - run:
          name: apt-get update
          command: sudo apt-get update
      - run:
          name: Install lftp
          command: sudo apt-get install lftp
      - run:
          name: Deploy
          command: lftp -c "set ftp:ssl-allow no; open -u $FTPUSERNAME,$FTPPASS $FTPHOST; mirror -R $LOCALPATH $SERVERPATH --parallel=10"
      - save_cache:
          paths:
            - node_modules
          key: npm-{{ checksum "package.json" }}
      
workflows:
  version: 2
  build_and_deploy:
    jobs:
      - build
```

基本的にnodeのイメージを持ってきて、ビルドさせてデプロイするだけ。

## 環境変数
ftpでアップしなければいけない制限があったためlftpで同期するために以下の環境変数をCircleCI上で設定する。

- FTPUSERNAME(ftpのユーザーネーム)
- FTPPASS(ftpのパスワード)
- FTPHOST(ftpのホスト名)
- LOCALPATH(ローカルのアップ対象のパス)
- SERVERPATH(サーバー上のアップ先のパス)


# Git
[外部プロジェクトのcssをassetに追加する](###外部プロジェクトのcssをassetに追加する)
> 今回の場合、CIを回すため、スタイルガイドプロジェクト内に元となるcssを生成することにした。

これを行うために`Git`の`Pre-commit Hook`を使用した。

## git pre-commitとは
コミット前に特定の処理を実行できるもの。
今回は常に最新版のcssが反映されるようにコミット前にscssのコンパイルの処理を走らせた。

`git/hooks`内に`pre-commit`というファイルを作成する。
その中にシェルスクリプトを記述する。他のスクリプトでも可能。

```pre-commit
#!/bin/sh

node-sass --include-path scss [元のscss] ./assets/css/style.css --output-style compressed
sleep 5
git add assets/css/style.css
```

これでコミット前に外部プロジェクトのscssをコンパイルし、スタイルガイドプロジェクトの静的ファイルディレクトリに格納してステージングに上げるという処理が完了する。その後、pushすればCIがまわる。

# Slackに通知する

## Slackの設定
https://my.slack.com/apps/A0F7VRE7N-circle-ci

ここからインストールする。

<img width="1024" alt="1d009ec2be50a854df2feb5877f57c4b.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/c2509bc7-9dc4-7063-d1e8-e870ce50b491.png">
ここから`設定を追加`をクリック。

<img width="1002" alt="79d0b483626774667936ed3b9998ef04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/3e0695c4-9781-b171-2394-b6afe8298aba.png">

通知したいチャンネルを選択肢、`CircleCIインテグレーションの追加`をクリックする。
![webhook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/f1c2d806-9e65-f597-2615-a874049cfa92.png)


## CircleCIの設定
通知したプロジェクトの設定画面から`Chat Notifications`を開く。
![chat_notice.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/02cc2119-dc5e-ba1c-56a8-1917eb93a819.png)

SlackのWebhook URLのところに控えておいたURLを貼り付けて`Save`で完了。
gitにpushして通知がくればOK。

## おまけ
### GitHubにCircleCIのバッジをつける

<img width="109" alt="スクリーンショット 2019-05-10 18.06.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/0d513723-3ba8-6348-f4a6-865f4a9ce66d.png">
↑これ。

通知したプロジェクトの設定画面から`Status Badges`を開き`Embed Code`からMarkdown用のコードをREADME.mdに追加する。
![Badge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/859c3c89-fb56-6e6f-de5f-6ceaeb99cfeb.png)

#### プライベートリポジトリの場合
`Branch`から任意のものを選択し、`API Token`の`add one with status scope.`からTokenを取得する。
![api_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243815/c11958cd-369b-309e-1be8-6752fb976d2e.png)

# まとめ
- だいぶ見通しがよくなった。特に複数人で作業する場合。
- 認識を共有できる
- 修正に強くなった。cssがごちゃつかなくなった。

# 参考
[Fractal User Guide](https://fractal.build/guide/)
[Fractal デザインスタイルガイド 導入](https://qiita.com/fujihiko/items/70f985fbc4bb32c505a1)
[githubでREADME.mdにCircleCIのバッジを表示する](https://qiita.com/Hanocha/items/8ad74258eb43d0959590)