【年末大掃除】.mdをCI/CDで整理する

皆様初めまして、19新卒の坂井です。
AIサービス開発本部のAI Cameraチームに所属し、普段は画像処理やロジック検討や追加機能の実装を行ってます。

目次

はじめに

4月に入社し、気がつけば年末が目前に迫ってました。
もう、来年からは新卒と名乗れなくなってしまうのですね。

さて、年末ということで大掃除も兼て図の様なドキュメント状況を打開するため、 f:id:optim-tech:20191220224405p:plain

チーム内のプロジェクトドキュメントをCI/CDで生成する様に整備した話をしていきたいと思います。

CI/CDとは?

CI: Continuous Integration ~ 継続的インテグレーション ~

継続的インテグレーションでは、コードをプッシュする度にビルドやテストが自動的に行われます。
このフェーズでは、ビルドやテストを通過したアプリケーションが成果物(Artifact)となります。
docs.gitlab.com f:id:optim-tech:20191218151024:plain

CD: Continuous Delivery ~継続的デリバリー ~

CD: Continuous Deployment ~ 継続的デプロイ ~

継続的デリバリーやデプロイでは、CIで作成した成果物(Artifact)をステージング環境や本番環境にデプロイする仕組みのことを指します。
docs.gitlab.com f:id:optim-tech:20191218151022:plain

Tools

GitLab

OPTiMでは、ソフトウェア開発支援環境にGitLabを使用しています。
ドキュメントの生成は、GitLabで提供されている以下の機能を活用し構築していきます。

GitLab CI/CD

GitLab CI/CD は、リポジトリのルートに.gitlab-ci.ymlを配置しておくことで、プッシュやMRの際に.gitlab-ci.ymlにて設定したスクリプトやジョブが GitLab Runnerによって実行されます。
https://docs.gitlab.com/ee/ci/introduction/img/gitlab_workflow_example_11_9.png docs.gitlab.com

GitLab Runner

GitLab Runnerは、GNU / Linux、macOS、およびWindowsオペレーティングシステムのマシンで動作するオープンソースプロジェクトです。gitlab-ci.ymlにて設定されたスクリプトやジョブを実行し、結果をGitLabに送り返します。

GitLab Pages

GitLab Pagesは、GitLabのリポジトリから静的なWebサイトを直接公開できる機能です。 https://docs.gitlab.com/ee/user/project/pages/img/new_project_for_pages_v12_5.png docs.gitlab.com

GitLab Container Registry

GitLab Container Registryは、Docker Container RegistryがGitLabに統合されているため、すべてのプロジェクトにDockerイメージを保存するための独自のスペースを確保できます。

GitLab Badges

GitLab Badgesは、図に示す様なリンクを持った画像を貼り付けることができ、画像内の数値は画像が指すリンク先のURLの情報等を元にCI/CD パイプラインのstatusやcoverageの値等を示すことができます。
f:id:optim-tech:20191218180047p:plain

静的サイトジェネレータ

GitLab Pagesでは静的なWebサイトを公開できるとのことなので、プロジェクト用ドキュメントを作成する上でMarkdown(.md)記述可能かつPlantUMLに対応しているものが良いと考えMkDocsを採用しています。

MkDocs

MkDocsは、Markdown(.md)で記述されたドキュメントとmkdocs.ymlから静的なWebサイトを生成してくれます。

拡張機能

今回はプロジェクトで使用する上で必要になりそうな以下の拡張機能を設定しました。
拡張機能ごとの例を示していきます。

警告文

mkdocs-material:admonition
f:id:optim-tech:20191218151015p:plain

注釈

mkdocs-material:footnotes
f:id:optim-tech:20191218151048p:plain

アイコンフォント

fontawesome-markdown
f:id:optim-tech:20191218151042p:plain

PlantUML

plantuml-markdown
f:id:optim-tech:20191220224411p:plain

コードハイライト

mkdocs-material:codehilite
f:id:optim-tech:20191218151029p:plain

プロジェクトのCI/CDに組み込む

ディレクトリ構成

プロジェクトのリポジトリに/docs配下に.mdファイルを配置し、mkdocs.yml内で.mdを指定することでドキュメントを構成できます。

project/
 ├ docs/   # docs配下に.mdを配置
 │ └ index.md 
 │ └ css/
 │   └ custom.css
 └ mkdocs.yml # .mdを指定しておく方が良い

mkdocs.yml

 # Project information
site_name: 'ドキュメント'
site_description: 'リファレンス'
site_author: 'sakai'

nav:
  - 概要: index.md
  - mkdocs.yml解説: yml.md
  - ローカル実行: local_process.md
  - docker実行: docker_process.md
  - Badge登録手順: Setting.md
  - サンプル:
    - 1.警告文: Samples/Admonition.md
    - 2.アイコンフォント: Samples/Fontawesome.md
    - 3.注釈: Samples/Footnotes.md
    - 4.コード: Samples/Code.md
    - 5.PlantUML: Samples/PlantUML.md
 
# Copyright
copyright: '©︎ 2019 OPTiM AI Camera Team'

# Documentation and theme
docs_dir: 'docs'
theme:
  name: 'material' 
  palette:
    primary: 'Indigo'
    accent: 'Cyan'

# Options
extra:
  font:
    text: "Noto Sans JP"
    code: "Consolas"
  in:
    prev: 'Previous'
    next: 'Next'
  search:
    language: 'ja'

extra_css:
    # font: Noto Sans JP
    - "https://fonts.googleapis.com/earlyaccess/notosansjp.css"
    - "https://fonts.googleapis.com/css?family=Open+Sans:600,800"
    # iconfonts
    - "https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css"
    # settings
    - "css/custom.css"

markdown_extensions:
  - admonition
  - footnotes
  - fontawesome_markdown
  - plantuml_markdown:
      server: http://www.plantuml.com/plantuml
  - codehilite:
      use_pygments: true
      noclasses: true
      pygments_style: monokai
      linenums: true

css/custom.css

body {
    font-family: "Noto Sans JP";
}

.md-typeset pre {
    color: #f8f8f2;
}
.md-typeset .codehilitetable {
    margin-left:-20px;
    margin-right: -20px;
    border-radius: 0;
}
.md-typeset .codehilitetable .linenodiv {
    background-color: #222 !important;
}
.md-typeset .codehilitetable .linenodiv pre {
    background-color: #222 !important;
    color: #aaa;
    margin: 0;
}
.md-typeset .codehilitetable .md-clipboard:before {
    color: rgba(240,240,240,.8);
}
.md-typeset .codehilitetable .md-clipboard:hover:before {
    color: rgba(102,217,224,1);
}

参考:フォントのカスタマイズ 参考:コードハイライト

前準備

GitLab Runnerは用意してある前提で進めていきます。
GitLab Container Registryにビルド環境をpushし、プロジェクトで使用する際は登録されているDockerイメージをpullして使用していきます。まず、共通で使用するMkDocsのビルド環境を用意していきます。

MkDocsビルド用のDockerfileを用意

alpineのイメージを用い、ビルド用のイメージを作成します。
docker/ci/mkdocs/Dockerfile

FROM python:alpine

RUN pip install --upgrade pip \
  && pip install mkdocs \
  && pip install mkdocs-material \
  && pip install fontawesome_markdown \
  && pip install plantuml-markdown

WORKDIR /root

CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"]

こちらのDockerfileは、ローカル環境でも以下のコマンドを実行しhttp://localhost:8000にアクセスすることで手元でもドキュメントを確認できる様にしています。

$ docker build -t mkdocs -f docker/ci/mkdocs/Dockerfile .
$ docker run -p 8000:8000 -v $PWD:/root mkdocs

GitLab Container Registryにイメージを登録

続いて、先ほど作成したDockerfileをビルドしCI/CDでContainer Registryに登録します。 .gitlab-ci.yml

stages:
  - docker

variables:
  DOC_IMAGE_TAG: ${CI_REGISTRY_IMAGE}/document:latest
    
document:docker:
  stage: docker
  image: docker:dind
  before_script:
      - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
  script:
    - docker pull ${DOC_IMAGE_TAG} || true
    - docker build --cache-from ${DOC_IMAGE_TAG} -t ${DOC_IMAGE_TAG} -f docker/ci/mkdocs/Dockerfile .
    - docker push ${DOC_IMAGE_TAG}

上記の.gitlab-ci.yml内で使用しているGitLab CI/CD Variables

変数 説明
CI_REGISTRY_IMAGE 特定のプロジェクトに関連付けられている
レジストリのアドレスを返す
CI_REGISTRY_USER コンテナをGitLab Container Registryに
プッシュするために使用するユーザー名
CI_REGISTRY_PASSWORD コンテナをGitLab Container Registryに
プッシュするために使用するパスワード
CI_REGISTRY Container Registryが有効な場合、
GitLabのContainer Registryのアドレスを返す

各リポジトリに導入

GitLab Container Registryに登録したMkDocsのビルド環境を用い、CI/CDパイプラインにdockerとbuild, pagesステージを追加します。各リポジトリに導入後のイメージは以下の様になります。 f:id:optim-tech:20191220230709:plain

CI/CDでビルドからPagesでの公開

レビュー後のドキュメントをPagesに反映するためにmasterにマージされた時のみGitLab Pagesが更新しています。
.gitlab-ci.ymlの記述は以下の様になります。

variables:
  DOC_IMAGE_TAG: registry.example.com/group/project/document:latest

stages:
  - docker
  - build
  - release

document:
  stage: docker
  image: docker:dind
  before_script:
    - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
  script:
    - docker pull ${DOC_IMAGE_TAG} || true 

# mkdocsによるドキュメント生成
document:build:
  stage: build
  image: ${DOC_IMAGE_TAG}
  before_script:
  script:
    - mkdocs build
  artifacts:
    paths:
      - site/
    expire_in: 10 min

# GitLab Pagesに公開
pages:
  stage: release
  script:
    - mv site public
  artifacts:
    paths:
      - public/
    dependencies:
      - document:build
    only:
      - master

GitLab Badgeに登録

GitLabサイドバー > Settings > General > Badgesから設定を行うことができます。
badgesの画像にはShields.IOを使用しています。 f:id:optim-tech:20191218180045p:plain

リポジトリのPagesのドメインはGitLab Pages default domain namesに従い、リンクを設定しておくことでドキュメントへBadgeからアクセスできます。

おわりに

年始などの久しぶりの業務や新しいメンバーのためにドキュメントへのアクセスがしやすい体制を整えてみました。
先日、新卒で行なったLTで共有したところ早速反応がありissueが追加され始めました。

ライセンス表記

  • 各リポジトリに導入の画像で使用しているGitLabロゴはGitLabの公式ページで配布されている画像を使用しています
  • 各リポジトリに導入の画像で使用しているMarkdownロゴはGitHubで公開されているものを使用しています
  • この記事ではCC BY-SA4.0ライセンスで公開されているGitLab Docsを翻訳・追記しています。