はじめに
GitHub PagesへデプロイするSourceの指定先は2つあります。それぞれ以下のような違いがあります。
指定先 | 概要 |
---|---|
Deploy From a branch | ホスティングするビルド成果物をコミット、GitHub Pagesで公開 |
GitHub Actions(beta) | GitHub Actionsでビルド成果物を作成、GitHubのartifactとしてアップロードし、GitHub Pagesで公開 |
※ リポジトリのページから「Settings」->「Source」設定確認可能
Source指定にDeploy From a branch
と比較し、GitHub Actions(beta)
を利用するメリットには以下があります。
- ホスティングのために用意しているブランチやビルド成果物が不要になり、認知負荷を下げられる
- ビルド資材をコミットする作業がなくなる
- ビルド資材の容量が大きい場合、pullやcheckoutにかかる時間を削減できる(モノレポの場合コードに対するCIにも影響する)
設定方法
前提
今回は以下をホスティングする想定にします。
- Swagger UI
- AsciiDoc with PlantUML
何らかのHTTP REST APIの仕様書を作る想定です。
リポジトリテンプレート
リポジトリテンプレートは公開しています。用途に応じてカスタマイズして頂けたらと思います。
ファイル/フォルダ構成
$ exa -L 4 -T --git-ignore
.
├── bin
│ └── build.sh ... ./documents配下をビルドし、./distディレクトリに出力する
├── documents
│ ├── assets
│ │ ├── swagger-ui.html ... SwaggerUIのHTML。同一ドメインの./api.ymlにアクセスし、内容APIの内容をレンダリング
│ │ └── VL-Gothic-Regular.ttf ... PlantUMLの文字化け防止
│ └── docs
│ ├── blog-api
│ │ ├── api.yml ... APIのOpenAPI定義
│ │ └── spec.adoc ... APIの仕様を書いたドキュメント
│ └── index.adoc ... 仕様書のルートページ
└── README.md
リポジトリの設定
Settings
-> Source
から、GitHub Actions(beta)
を選択
ビルド設定
documents/docs配下
をビルドして、./dist
に結果を出力するシェルです。個人的にはシェルスクリプトではなくzxやdaxを使う方が推奨だったりします。
bin/build.sh
#!/bin/bash
BIN_PATH="$(dirname -- ${0})"
WS_ROOT_PATH="$BIN_PATH/../"
DIST_PATH="$BIN_PATH/../dist"
DOCUMENT_DIR="docs"
rm -rf $DIST_PATH
# AsciiDocの再起的ビルド
for filename in $(find ./docs -type f |cut -d/ -f3- | grep .adoc); do
asciidoctor \
-a imagesdir@=images \
-a imagesoutdir=$DIST_PATH/images \
-a outdir=$DIST_PATH \
-o $DIST_PATH/${filename%.*}.html \
-r asciidoctor-diagram \
-b html5 \
$DOCUMENT_DIR/${filename}
done
# swaggerの設定
cp $WS_ROOT_PATH/docs/blog-api/api.yml $DIST_PATH/blog-api/
perl -pe 's/<ymlPath>/api.yml/g' $WS_ROOT_PATH/assets/swagger-ui.html > $DIST_PATH/blog-api/api.html
ドキュメント(サンプル)
テスト用に以下のようなドキュメントを用意します。
仕様書のルートページ
documents/docs/index.adoc
:docname: サンプルブログ
:lang: ja
:doctype: book
:icons: font
:toc: left
:toc-title: 目次
:toclevels: 2
:example-caption: 例
:table-caption: 表
:figure-caption: 図
:chapter-label:
:imagesdir: images
:imagesoutdir: images
= サンプルブログ仕様書
== サンプルブログAPI
==== link:blog-api/spec.html[設計書^]
==== link:blog-api/api.html[API仕様書^]
API仕様書ページ
documents/docs/blog-api/spec.adoc
:docname: API仕様書
:lang: ja
:doctype: book
:icons: font
:toc: left
:toc-title: 目次
:toclevels: 3
:example-caption: 例
:table-caption: 表
:figure-caption: 図
:chapter-label:
:imagesdir: ../images
:imagesoutdir: images
= サンプルブログドキュメント
== 仕様書
=== 記事取得
[cols="3*", options="header"]
|===
|メソッド|パス|補足
|GET|/users/{userId}/articles|
|===
[plantuml]
----
@startuml
box "Web" #fff2df
participant "blog.sample.dev" as blog
end box
box "AWS" #fff2df
participant "APIGateway" as apig
participant "lambda" as lambda
database "User" as db_user
database "Article" as db_article
end box
blog -> apig: 記事取得
activate blog
activate apig
apig -> lambda: 記事取得
activate lambda
lambda -> db_user: UIDを取得(userId)
activate db_user
alt 存在しない場合
db_user-->lambda: 取得NG
lambda-->apig: 400 BadRequest
apig-->blog: 400 BadRequest
end
lambda --> apig: 200 OK + 記事情報
apig --> blog: 200 OK
deactivate lambda
deactivate apig
deactivate blog
@enduml
----
SwaggerUIページ
documents/docs/blog-api/api.yml
openapi: "3.0.0"
info:
title: "サンプルブログAPI"
version: "1"
servers:
- url: "https://api.sample.dev/v1"
tags:
- name: "User"
description: "ユーザーに関する操作"
paths:
/users/{userId}/articles:
get:
tags:
- "User"
summary: "ユーザーの記事一覧取得"
security: []
parameters:
- in: "path"
name: "userId"
required: true
schema:
type: string
description: "userId"
- in: "query"
name: "type"
required: true
schema:
type: string
description: "記事タイプ"
responses:
200:
description: "成功"
content:
application/json:
schema:
type: "object"
properties:
articles:
type: "array"
items:
$ref: "#/components/schemas/article"
components:
schemas:
article:
required:
- "articleId"
- "content"
- "title"
- "type"
- "category"
- "description"
- "publishAt"
- "ogpUrl"
- "updateAt"
- "createAt"
type: "object"
properties:
articleId:
type: "string"
example: "xxxxxxxxxxx"
content:
type: "string"
example: "# h1"
title:
type: "string"
example: "XXをやってみた"
type:
type: "string"
enum: ["tech", "gaget", "life"]
example: "tech"
category:
type: "string"
example: ["typescript"]
description:
type: "string"
example: "記事の説明!"
ogpUrl:
type: "string"
example: "https://res.cloudinary.com/sample"
thumbnail:
type: "string"
example: "https://res.cloudinary.com/sample"
createAt:
type: "number"
example: 160915346897
updateAt:
type: "number"
example: 160915346897
publishAt:
type: "number"
example: 160915346897
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: access token for API
security:
- bearerAuth: []
GitHub Actions設定
name: Deploy document
on:
push:
branches:
- main
permissions:
id-token: write
contents: read
actions: read
jobs:
build:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- name: build documents
run: |
sudo gem install asciidoctor
sudo gem install asciidoctor-diagram
mkdir -p /usr/share/fonts/VLGothic
cp ./documents/assets/VL-Gothic-Regular.ttf /usr/share/fonts/VLGothic
./bin/build.sh
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
runs-on: ubuntu-latest
needs: build
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
GitHub Pagesで公開された内容
うまくホスティングされていることが確認できました。
さいごに
ホスティングする場所は、S3の静的サイトホスティングなど他にも色んな候補があります。GitHub Pagesのメリットは、EnterpriseだとGitHubのユーザーで認証ができる点があると思います。S3の静的サイトホスティングと比較すると、過去のビルド結果も保持できるといいなと思います。SourceにGitHub Action(beta)を指定することで、より手軽で柔軟にサイトをホスティング出来るので、試して頂けたらと思います!