5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Asciidocで仕様書の「開発環境」を整える (2)

Last updated at Posted at 2022-08-23

概要

モダンな仕様書の「開発環境」を構築した。
結果として、以下のような雛形の環境が出来上がった。

前回

前回までで個々人のローカルで仕様書を書く準備は整った。

今回はチーム開発や運用効率化を行うべく、CI/CD を整備していく。

前提

前回に加えて、仕様書の CI/CD 環境を整える上で事前に用意しておくものは以下の通り。

  • GitHub

GitLab や AWS CodeCommit などでもよい。その場合、以降の自動化の方法が異なってくるだろうが、やっていることは Linux でのコマンド実行なので、同様のことができる。

仕様書を CI する

仕様書を Pull Request ベース開発する

コーディングの世界では、チーム開発をスムーズに回すために Pull Request ベース開発という考え方がある。ざっくり言ってしまうと、コードのレビュー依頼 (Pull Request) をして、レビューOKで採用するというやり方。これをシステマチックに行う方法のことである。

今回は Git Flow を採用して以下の流れで開発することを想定する。

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f35333330392f30363134303132312d613062362d343237662d633134392d3638353863313439373338652e706e67.png

  1. メンバーはdevelopからfeature/Aブランチを生やす
  2. メンバーは担当部分を追記してfeature/Aブランチを push し、developブランチへの pull request を作る
  3. リーダーが pull request を確認してレビューする。指摘事項はコメントで残す。
  4. リーダーがレビュー完了 (指摘事項が対応済み) を確認したらマージする

メンバーやリーダーと書いたが、チームによって変わると思う。ただ、文章のレビューは、書き方の統一性を保つためにも誰か責任者を置いたほうがよい。または、予め書き方の方針を示し合わせた上で、複数人によるレビューを行なってもよい。

Pull Request を自動でチェックする

仕様書のレビューは、誤解ない良いドキュメントを作る上で重要な作業だと思う。人手によるレビューは、より高度な文章の校正に注力したい。そのためにも、Typo などの簡単な問題は自動でレビューしたいものだ。そこで、Pull Request が生成された時に textlint を自動で走らせてコメントするように設定する。

textlint と言うと、前回ローカルでライブチェックする設定を導入したので、いらないのではと思われるかもしれない。しかし、実際に運用すると、textlint の指摘を修正せずに Pull Request が上げられることが、結構ある。マシンスペックによって、ライブチェックを OFF にしている、焦って確認せずに上げるなど理由は様々だが、いずれにしても複数回チェックすることには意味はある。

今回は GitHub を前提としているため、Pull Request による自動動作には GitHub Actions を使用した。
以下が今回作成したワークフローファイル。 (+npm scriptsの追加)

.github/workflows/run-lint.yml
name: run-lint
on:
  pull_request_target:
    types: [ opened, synchronize ]
    paths: [ 'src/**/*.adoc' ]
jobs:
  lint:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - name: Setup reviewdog
        uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest
      - name: Switch to pull request branch
        uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Setup node with cache
        uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
      - name: Install packages via packages.json
        run: npm install
      - name: Run lint
        run: npm run lint:ci
      - name: Report if textlint finds problems
        if: failure()
        run: |
          if [ -e ./.textlint.xml ]; then
            # report by reviewdog
            cat ./.textlint.xml | reviewdog -f=checkstyle -name="textlint" -reporter="github-pr-review" -level="warning"
            # clean output file
            rm -rf ./.textlint.xml
          fi
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          URL: ${{ github.event.pull_request.html_url }}
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package.json
{
...
  "scripts": {
    ...
    "lint:ci": "textlint ./src/**/*.adoc -f checkstyle -o ./.textlint.xml",
    ...
  },
...
}

やってることの流れとしては、

  • すべての Pull Request に対して adoc ファイルに変更があった時のみ実行する
  • textlint はnpm scriptsで実行する。指摘事項を検出するとエラーとなり、Pull Request に×印が付く。
  • textlint の指摘事項がある場合 reviewdog を使って Pull Request のコメントとして表示する

もし、textlint は失敗しているが Pull Request のコメントが何もない場合は、Pull Request で追加・修正した場所ではないところが指摘されている可能性がある。その場合、この Pull Request で修正するように促そう。

なお、実際に動いている Pull Request の結果はここで確認できる。

仕様書を CD する

ここからは仕様書のリリースや管理など CD について構築する。

仕様書を Pull Request ベースでリリースする

まず、仕様書リリース時のフローをまとめる。今回も Git Flow を想定すると以下の流れになる。

  1. リーダーは仕様書をリリースするタイミングでdevelopからrelease/x.y.zブランチを生やす
  2. リーダーやメンバーはrelease/x.y.zブランチに対して、記載不備の修正など校正する。このとき仕様書のバージョンを上げる。
  3. リーダーはrelease/x.y.zブランチを push し、developブランチへの pull request を作る
  4. リーダーは pull request を確認してマージする
  5. リーダーはrelease/x.y.zブランチを push し、mainブランチへの pull request を作る
  6. リーダーは pull request を確認してマージする

こちらもリーダーである必要はない。リリースに責任を持って丁寧にやれれば、誰でもOKだと思う。

仕様書を自動でデプロイする

ここでは、仕様書を製本(HTML や PDF化)して、誰かと共有できる状態にすることを デプロイ と呼ぶことにする。
このデプロイ、仕様書の Continuous Delivery(継続的デリバリー) には二種類のタイミングがある。

  • 開発中である程度追記が完了したタイミング
    今回のフローではfeature/Aブランチがdevelopにマージされたタイミング。製本した成果物は中間データのため、バージョン管理する必要はない。現在の最新の状態が見れればよい。
  • 正式版としてリリースするタイミング
    今回のフローではrelease/x.y.zブランチがmainにマージされたタイミング。製本した成果物はバージョン管理していつでも見返せる状態にしたい。

今回も Pull Request の自動チェックと同様、GitHub Actions を使用してこれらを実現する。
以下が今回作成したワークフローファイル。

.github/workflows/run-build.yml
name: run-build
on:
  pull_request:
    branches: [ develop, main ]
    types: [ closed ]
jobs:
  build:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup node with cache
        uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
      - name: Install packages via packages.json
        run: npm install
      - name: Build Asciidoc
        run: npm run build
      - name: Publish latest
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist
          keep_files: true
      - name: Create tag
        id: create-tag
        if: github.base_ref == 'main' && startsWith(github.head_ref, 'release')
        run: |
          TAG_NAME=$(echo ${{ github.head_ref }} | sed 's/release\///')
          echo "::set-output name=tag-name::${TAG_NAME}"
          echo $TAG_NAME
      - name: Publish versioned
        uses: peaceiris/actions-gh-pages@v3
        if: github.base_ref == 'main' && startsWith(github.head_ref, 'release')
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist
          destination_dir: ${{ steps.create-tag.outputs.tag-name }}
          keep_files: true
      - name: Create release
        if: github.base_ref == 'main' && startsWith(github.head_ref, 'release')
        uses: softprops/action-gh-release@v1
        with:
          name: ${{ steps.create-tag.outputs.tag-name }}
          tag_name: ${{ steps.create-tag.outputs.tag-name }}
          generate_release_notes: true
          files: dist/index.pdf
          draft: false
          prerelease: false

やってることの流れとしては、

  • developまたはmainブランチへ Pull Request がマージされた時のみ実行する
  • npm scriptsを実行して HTML と PDF ファイルを作る
  • 作成した HTML と PDF を GitHub Pages のルートにデプロイする
  • もしrelease/x.y.zブランチをmainにマージしたのであれば
    • 作成した HTML と PDF を GitHub Pages の./x.y.z以下にデプロイする
    • 作成した HTML と PDF を GitHub の Releases にアップロードする
    • mainブランチにタグx.y.zを打つ

このワークフローによって、マージされた Pull Request の最新結果が常に配信されている状態となり、過去リリースした成果物はバージョン管理され配信かつダウンロード可能な状態を保つことができる。これによって、今までの「ネットワークフォルダ+ファイル名管理」によるツラさや問題から脱却できる。

今回、peaceiris/actions-gh-pagesを用いた GitHub Pages への公開を使ったためgh-pagesブランチが自動で生成される。初めて生成した後にリポジトリのSettings > PagesからBuild and deploymentBranchgh-pagesに設定する必要がある。

なお、実際に動いている Pull Request の結果はここで確認できる。

最後に

二回に渡って仕様書をテーマに、調査と検証をしながら、「開発環境」を構築した。まだ「既存のやり方」との違いはあると思う。反発される点もまだあるだろう。しかし、冒頭に書いたように、この記事をきっかけに、やってみようと思った人が少しでも増えたら嬉しい。

なお、間違いなどあれば、是非ご指摘ください。また、「既存のやり方で出来る◯◯ができない」といった反発もウェルカムです。鋭意検討してアップデートしますので。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?