概要
モダンな仕様書の「開発環境」を構築した。
結果として、以下のような雛形の環境が出来上がった。
前回
前回までで個々人のローカルで仕様書を書く準備は整った。
今回はチーム開発や運用効率化を行うべく、CI/CD を整備していく。
前提
前回に加えて、仕様書の CI/CD 環境を整える上で事前に用意しておくものは以下の通り。
- GitHub
GitLab や AWS CodeCommit などでもよい。その場合、以降の自動化の方法が異なってくるだろうが、やっていることは Linux でのコマンド実行なので、同様のことができる。
仕様書を CI する
仕様書を Pull Request ベース開発する
コーディングの世界では、チーム開発をスムーズに回すために Pull Request ベース開発という考え方がある。ざっくり言ってしまうと、コードのレビュー依頼 (Pull Request) をして、レビューOKで採用するというやり方。これをシステマチックに行う方法のことである。
今回は Git Flow を採用して以下の流れで開発することを想定する。
- メンバーは
develop
からfeature/A
ブランチを生やす - メンバーは担当部分を追記して
feature/A
ブランチを push し、develop
ブランチへの pull request を作る - リーダーが pull request を確認してレビューする。指摘事項はコメントで残す。
- リーダーがレビュー完了 (指摘事項が対応済み) を確認したらマージする
メンバーやリーダーと書いたが、チームによって変わると思う。ただ、文章のレビューは、書き方の統一性を保つためにも誰か責任者を置いたほうがよい。または、予め書き方の方針を示し合わせた上で、複数人によるレビューを行なってもよい。
Pull Request を自動でチェックする
仕様書のレビューは、誤解ない良いドキュメントを作る上で重要な作業だと思う。人手によるレビューは、より高度な文章の校正に注力したい。そのためにも、Typo などの簡単な問題は自動でレビューしたいものだ。そこで、Pull Request が生成された時に textlint を自動で走らせてコメントするように設定する。
textlint と言うと、前回ローカルでライブチェックする設定を導入したので、いらないのではと思われるかもしれない。しかし、実際に運用すると、textlint の指摘を修正せずに Pull Request が上げられることが、結構ある。マシンスペックによって、ライブチェックを OFF にしている、焦って確認せずに上げるなど理由は様々だが、いずれにしても複数回チェックすることには意味はある。
今回は GitHub を前提としているため、Pull Request による自動動作には GitHub Actions を使用した。
以下が今回作成したワークフローファイル。 (+npm scripts
の追加)
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 }}
{
...
"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 を想定すると以下の流れになる。
- リーダーは仕様書をリリースするタイミングで
develop
からrelease/x.y.z
ブランチを生やす - リーダーやメンバーは
release/x.y.z
ブランチに対して、記載不備の修正など校正する。このとき仕様書のバージョンを上げる。 - リーダーは
release/x.y.z
ブランチを push し、develop
ブランチへの pull request を作る - リーダーは pull request を確認してマージする
- リーダーは
release/x.y.z
ブランチを push し、main
ブランチへの pull request を作る - リーダーは pull request を確認してマージする
こちらもリーダーである必要はない。リリースに責任を持って丁寧にやれれば、誰でもOKだと思う。
仕様書を自動でデプロイする
ここでは、仕様書を製本(HTML や PDF化)して、誰かと共有できる状態にすることを デプロイ と呼ぶことにする。
このデプロイ、仕様書の Continuous Delivery(継続的デリバリー) には二種類のタイミングがある。
- 開発中である程度追記が完了したタイミング
今回のフローではfeature/A
ブランチがdevelop
にマージされたタイミング。製本した成果物は中間データのため、バージョン管理する必要はない。現在の最新の状態が見れればよい。 - 正式版としてリリースするタイミング
今回のフローではrelease/x.y.z
ブランチがmain
にマージされたタイミング。製本した成果物はバージョン管理していつでも見返せる状態にしたい。
今回も Pull Request の自動チェックと同様、GitHub Actions を使用してこれらを実現する。
以下が今回作成したワークフローファイル。
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
を打つ
- 作成した HTML と PDF を GitHub Pages の
このワークフローによって、マージされた Pull Request の最新結果が常に配信されている状態となり、過去リリースした成果物はバージョン管理され配信かつダウンロード可能な状態を保つことができる。これによって、今までの「ネットワークフォルダ+ファイル名管理」によるツラさや問題から脱却できる。
今回、peaceiris/actions-gh-pages
を用いた GitHub Pages への公開を使ったためgh-pages
ブランチが自動で生成される。初めて生成した後にリポジトリのSettings > Pages
からBuild and deployment
のBranch
をgh-pages
に設定する必要がある。
なお、実際に動いている Pull Request の結果はここで確認できる。
最後に
二回に渡って仕様書をテーマに、調査と検証をしながら、「開発環境」を構築した。まだ「既存のやり方」との違いはあると思う。反発される点もまだあるだろう。しかし、冒頭に書いたように、この記事をきっかけに、やってみようと思った人が少しでも増えたら嬉しい。
なお、間違いなどあれば、是非ご指摘ください。また、「既存のやり方で出来る◯◯ができない」といった反発もウェルカムです。鋭意検討してアップデートしますので。