LoginSignup
4
1

More than 1 year has passed since last update.

Github Actions でGithub Pages更新用ビルド、プルリクを自動化する(mkdocs mike利用)

Last updated at Posted at 2021-12-01

はじめに

  • Github Pagesの公開ページの版管理(MkDocs plugin mike利用)にて、手動でのGithub Pagesを公開する使い方を勉強しました。
  • ただ、こういった作業はなるべく自動化したい(CIしたい)ので、Github Actionsを用いてGithub Pagesへデプロイする仕組みを実装しました。
    • ただし、最終的にはデプロイするためのPull Requestする、というところに着地しました。

0. 参考ページ

1. 構想

1.1. 前提・制約条件

  • 前提条件:メインとなるブランチはmasterブランチとします。(ただし、特に名称に意味はないです)
    • 最近は、ブランチ名をmainにするらしいです。
  • 前提条件:Github Pagesの公開ページの紐づけブランチは、gh-pagesブランチとします。
  • 制約条件:公開リポジトリで実施するため、gh-pagesブランチはprotected branchに設定します。つまり、pushによるアップロードを禁止します。
    • 結構、push禁止でCI回すのにハマったので、CI構築のポイントがまとめられればと思います。

1.2. やりたいこと

  • masterブランチにてMkDocs文書を管理します。mkdocsの文書をGithub Pagesにアップロードするタイミングは、以下の2点とします。
    • masterブランチのものを、任意のタイミング(自分がやりたい時)にGithub Pagesにアップロードする。
      • 「masterにpushされたときCIを回す」はよくあるのですが、masterが頻繁に更新されるときにPull Requestが連発するのは正直面倒なので、masterの内容のアップロードは自分がやりたい時(→workflow_dispatch利用)としています。
    • masterブランチのものに対して、リリースする(≒tag打ちする)ときにGithub Pagesにアップロードする。
      • masterブランチの特定のcommitに対してtagが打たれたときに(tag push event利用)Actionsが動作するようにします。

2. リポジトリ構成

my-mkdocs-mike
├── .devcontainer
│   └── devcontainer.json
├── .github
│   └── workflows
│       └── mkdocs-deploy.yml   <ーこれがActionsを定義するファイル
├── Dockerfile
├── LICENSE
├── README.md
├── docker-compose.yml
├── docs
│   ├── index.ja.md
│   ├── index.md
│   └── topic1
│       └── 内容省略
├── mkdocs.yml
├── requirements.txt
└── site

3. 構築したCI

  • まずは全体像を提示したあと、ポイントをまとめます。

3.1. Actions処理全体

name: MkDocsBuild

on:
  workflow_dispatch:
  push:
    tags:
      - '*'

env:
  PR_BRANCH: gh-pages-${{ github.run_number }}

jobs:
  release-PR:
    runs-on: ubuntu-latest
    steps:
      - name: execute apt install
        run: |
          sudo apt update
          sudo apt install -y hub

      - name: setup python
        if: ${{ success() }}
        uses: actions/setup-python@v2
        with:
          python-version: '3.10.0'

      - name: checkout code
        uses: actions/checkout@v2
        with:
          ref: ${{ github.ref }}

      - name: pip install
        if: ${{ success() }}
        run: |
          pip install -r requirements.txt 

      - name: setup mkdocs project
        if: ${{ success() }}
        env:
          REF: ${{ github.ref }}
        run: |
          export VER=`echo "${REF##*/}"`
          echo "version=${VER}" >> $GITHUB_ENV
          git remote set-url origin https://github-actions:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}
          git config --local user.name "${GITHUB_ACTOR}"
          git config --local user.email "${GITHUB_ACTOR}@users.noreply.github.com"
          git fetch

      - name: make PR_BRANCH
        if: ${{ success() }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          git checkout -b ${{ env.PR_BRANCH }} origin/gh-pages
          git push origin ${{ env.PR_BRANCH }}
          git checkout ${{ github.ref }}

      - name: check mike list previous
        if: ${{ success() }}
        continue-on-error: true
        run: |
          mike list --branch ${{ env.PR_BRANCH }} | grep ${{ env.version }}
          if [ $? ]; then
            mike delete --branch ${{ env.PR_BRANCH }} ${{ env.version }}
          fi

      - name: build mkdocs
        if: ${{ success() }}
        run: |
          mike deploy --branch ${{ env.PR_BRANCH }} ${{ env.version }}

      - name: checkout PR_BRANCH
        if: ${{ success() }}
        run: |
          git checkout ${{ env.PR_BRANCH }}

      - name: pull request
        if: ${{ success() }}
        uses: peter-evans/create-pull-request@v3
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: Update MkDocs 
          committer: GitHub <noreply@github.com>
          author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
          signoff: false
          branch: ${{ env.PR_BRANCH }}
          base: gh-pages
          delete-branch: true
          title: 'Update MkDocs'
          body: |
            Update report
          labels: |
            automated pr
          draft: false

3.2. ポイント1:PRを出すためのブランチをCI内で自動生成する

  • PR_BRANCH: gh-pages-${{ github.run_number }}にて、PRするためのブランチ名をgh-pages-ジョブナンバーで定義します。
    • PRブランチは、Merge後に(人が)削除する想定だが、「人はよくブランチを消し忘れる」ので、その対策でCIでPRするブランチ名が毎回違うものになるようにしています。
  • PRブランチの派生元は、当然ですがgh-pagesです。
    • git checkout -b ${{ env.PR_BRANCH }} origin/gh-pages <-ココの箇所
  • PRのたびに、PRブランチを生成するポイントは、長命ブランチを避けるためです。PRブランチを固定してしまうと長命ブランチとなり、修正が増えるたびにコンフリクトを起こす状態になります。
    • ブランチは、なるべく短命に、役割を終えたら消す(または使わない)ことを心がけています。
    • また、CIが動作するときに、前回状態に依存した作りにしないためでもあります。
  • 流れとしては、以下の通りです。
    1. プロジェクトをcloneしてfetchする。
    2. gh-pagesを派生元として、gh-pages-XXXブランチを作成する。(ただし、XXXはworkflowの実行通し番号(github.run_number)である)
    3. 一度、リモートブランチにgh-pages-XXXブランチをpushする。
    4. 以降の処理において、gh-pages-XXXブランチに修正をcommit -> push
      • このとき、mkdocsの版管理ツールmikeを用いて、master(or tagの内容)をmike deploしてgh-pages-XXXへビルド内容をcommitする。
    5. gh-pages-XXX -> gh-pagesへPRを出す。

3.3. ポイント2:actionsのオプション「continue-on-error: true」は便利

  • この「continue-on-error」は、以下のような設定をするオプションです。
    • Github Actions公式より引用)「ステップが失敗してもジョブが失敗にならないようにします。 trueに設定すれば、このステップが失敗した場合にジョブが次へ進めるようになります。」
  • step name: check mike list previous ですが、このstepは、「mike listしたときに登録したい名称で登録済みの場合、それを削除する」という処理となります。
    • この処理、「登録されていない」場合、grep処理の帰り値がreturn 1となるため、step失敗扱いになります。
  • この処理は、たとえreturn 1(grep失敗)となっても、step処理的には失敗ではないので、次stepへ処理を継続させるために本オプションを設定します。

4. Github Actionsが動作したときの流れ

※workflow_dispatchでも動きますが、ここではtag打ちからの流れを示します。

gh-actions-mike-demo.gif

5. おわりに

  • このCIを組むとき、Github Pagesの公開ページの版管理(MkDocs plugin mike利用)の知見から、「mike deploy」してgh-pagesに登録された成果物をpushすればいいや、くらいのノリで考えていました。
  • でも、考えていくうちに、gh-pagesが簡単にpushできたら、簡単にGithub Pagesが編集できてしまうのでは?、と思い、いろいろ思考錯誤した結果、本記事の構築内容となりました。
    • privateリポジトリでやるのもいいのですが、なるべく公開したいですね。(承認欲求なのか、OSSの考えなのか、定かではないですが)
  • 今回は触れていませんが、本来のCIとしては、masterブランチへのPR時に、ビルドチェック、静的解析、を実施するものがあります。そちらについても別題材で記事を書きたいと思っています。
4
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
4
1