2018年5月21日月曜日

CircleCI を利用して Sphinx プロジェクトを gh-pages に自動公開する

前回 のこれを、 push したら自動で gh-pages の公開までできるように設定する。

前提条件

手順

CircleCI でビルドできるように設定

CircleCI 上でプロジェクトを選択

サインアップボタン押下。

パブリックなものしか扱わないし、とりあえずパブリックオンリーで。

GitHub の OAuth でログイン。

パスワード入力。

GitHub の Organization 選択?自分のものを選ぶ。

プロジェクト選択。今回は sphinx プロジェクト。

CircleCI のサイトは開いたまま次の作業を行う。

sphinx プロジェクトに CircleCI 設定ファイルを追加

sphinx プロジェクトに .circleci/config.yml ファイルを作成し、 CircleCI の設定を記述する。

1 ステップ目として、ビルドして、成果物を公開する設定をした。

version: 2
jobs:
  build:
    docker:
      - image: mikoto2000/sphinx
    working_directory: ~/sphinx_gh-pages/work
    steps:
      - checkout
      - run:
          name: Build html
          command: cd work; make html
      - store_artifacts:
          path: work/build/html
          destination: htmls

コミット & プッシュする。

CircleCI でのビルド

CircleCI からビルドを起動する。

Start building ボタン押下。

ビルドが成功すると、下記のように成功ビルドが表示され、Artifact が見られる。 (このスクリーンショットは事後に撮ったので、 gh-pages ブランチが見えているし失敗しているけどそこは無視して)

gh-pages ブランチへ push するための設定

鍵の作成と登録

gh-pages に push するためには、 「GitHub に push しようとしているこの CircleCI が、許可されているユーザーか判定する」必要がある。

つまり、 CircleCI に秘密鍵を登録し、 GitHub に公開鍵を登録する。

push 用の鍵作成

msys2 環境で以下コマンドを実行し、鍵を作った。

$ mkdir -p ~/tmp/sshkeys
$ cd ~/tmp/sshkeys
$ # カレントディレクトリに id_rsa という名前で鍵を作る
$ # `-C` はコメントなので適切な感じに
$ ssh-keygen -t rsa -b 4096 -m pem -C circleci-sphinx_gh-pages -f ./id_rsa

CircleCI に秘密鍵を登録

BUILDS -> プロジェクト名右側の設定ボタン押下。

SSH Permissions -> Add SSH Key ボタン押下。

ホスト名と秘密鍵の文字列を入力。

こんな感じでホスト名とフィンガープリントが確認できる。

GitHub に公開鍵を登録

プロジェクトページ -> Settings -> Deploy keys -> Add deploy key と選択していく。

タイトルと、公開鍵の文字列を貼り付け。 push が必要なので、「Allow write access」のチェックを入れる。

パスワード入力。

キー追加が確認できる。

config.yml の更新

gh-pages の config.yml 作成

CircleCI の設定ファイルが無いまま gh-pages ブランチに push してしまうと、 それをトリガーに「CircleCI がビルド開始 → 設定ファイルがないから Failed」 という嫌な感じになってしまう。それを回避するため、 gh-pages ブランチにビルドスキップ設定をしたファイルを追加する。

.circleci/config.yml を作成し、次のように設定する。

version: 2
jobs:
  build:
    branches:
      ignore:
        - gh-pages

これを push すれば、それ以後 gh-pages に push しても CircleCI のビルドがスキップされる。

master ブランチの config.yml 更新

ワークフローを使って下記処理をしてもらえるように設定を更新する。

  1. build フェーズ(build ジョブ)
    • sphinx を使って html をビルドする
  2. deploy フェーズ(deploy ジョブ)
    • gh-pages を clone
    • 「1.」の成果物を add, commit, push

add_ssh_keys に、 CircleCI に登録した Deploy key の fingerprint(今回でいうと "bd:d3:5c:3d:ff:e9:6b:4e:c3:fd:89:2e:e7:48:67:c9") を設定する。

version: 2
jobs:
  build:
    docker:
      - image: mikoto2000/sphinx
    working_directory: ~/sphinx_gh-pages/work
    steps:
      - checkout
      - run:
          name: Build html
          command: cd work; make html
      - persist_to_workspace:
          root: work/build/html
          paths:
            - ./*
  deploy:
    machine: true
    steps:
      - add_ssh_keys:
          fingerprints:
            - "bd:d3:5c:3d:ff:e9:6b:4e:c3:fd:89:2e:e7:48:67:c9"
      - attach_workspace:
          at: work/build/html
      - run:
          name: Clone gh-pages
          command: git clone -b gh-pages git@github.com:mikoto2000/sphinx_gh-pages.git
      - run:
          name: Delete exists file
          command: rm -rf sphinx_gh-pages/*
      - run:
          name: Copy build results
          command: cp -rf work/build/html/* sphinx_gh-pages
      - run:
          name: Setup git
          command: cd sphinx_gh-pages;git config --local user.name "mikoto2000"; git config --local user.email "mikoto2000@gmail.com"
      - run:
          name: Git push
          command: cd sphinx_gh-pages; git add ./; git commit -m "From `git log --oneline origin/master -n 1`"; git push
workflows:
  version: 2
  build_and_deploy:
    jobs:
      - build:
          filters:
            branches:
              only: master
      - deploy:
          requires:
            - build

成功すると、下図のように

  • master ブランチの build ジョブが SUCCESS
  • master ブランチの deploy ジョブが SUCCESS
  • gh-pages ブランチが SKIPPED

となる。

TODO

  • [ ] : config.yml などの設定ファイルのみ更新した場合、 deploy ジョブの git commit で失敗することがあるのでどうにかする。
  • [ ] : CircleCI の環境変数機能を使う
  • [ ] : ; 区切りでコマンド列挙しているのが格好悪いからどうにかする

参考資料

更新履歴

日付 更新内容
2018/5/21 新規作成
2019/2/8 2019/2/8 時点の ssh-keygen の挙動に合わせて push 用の鍵作成コマンドを修正

Sphinx でビルドした html を gh-pages で公開する

前提条件

方針

  1. sphinx プロジェクトの成果物ディレクトリを ignore する
  2. 「1.」のディレクトリで git init して gh-pages ブランチに紐づける

手順

Sphinx プロジェクト作成

# source と build は分割する設定にすること
# jekyll の拡張を有効にすること
$ docker-compose run --rm sphinx sphinx-quickstart
Welcome to the Sphinx 1.4.9 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]: 

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]: 

The project name will occur in several places in the built documentation.
> Project name: sphinx_gh-pages
> Author name(s): mikoto2000

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0
> Project release [1.0.0]: 

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]: ja

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]: 

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]: 

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]: 

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]: 
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: 
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: 
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: 
> coverage: checks for documentation coverage (y/n) [n]: 
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]: 
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]: 
> ifconfig: conditional inclusion of content based on config values (y/n) [n]: 
> viewcode: include links to the source code of documented Python objects (y/n) [n]: 
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]: y

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]: 
> Create Windows command file? (y/n) [y]: 

Creating file ./source/conf.py.
Creating file ./source/index.rst.
Creating file ./Makefile.
Creating file ./make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file ./source/index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

成果物ディレクトリを ignore 設定してコミット、プッシュ

$ echo "work/build/html" > .gitignore
$ git add .
$ git commit -m 'Initial commit.'
$ git push

ドキュメントビルド

$ docker-compose run --rm sphinx make html

gh-pages ブランチを作成してプッシュ

$ cd work/build/html
$ git init
$ git add .
$ git commit -m 'Initial commit.'
$ git remote add origin git@github.com:mikoto2000/sphinx_gh-pages.git
$ git checkout -b gh-pages
$ git push origin gh-pages

参考資料