Hiroto's diary

プログラミング関連を書くかも

hugoでブログを生成してTravis CIでデプロイする

最近新しく鉄道関連用のブログをGitHub Pagesに作った。

このブログの本文は全てMarkdownで書いていて、GithubにpushしたらTravis CIで自動的にサイトを生成してデプロイするようになっている。

サイトを作った時のメモ適当に。

GitHubリポジトリを作る

自分はリポジトリ名をblogにして作ったので、ここではリポジトリ名をblogで説明します。

hugoでサイトを作る

公式のドキュメントを読んでhugoをインストールする。テーマなどもドキュメントを読めば大体書いてあるのでインストールしておく。

テスト用に記事を作ってhugo serverで確認しておくと便利。

ここで一回commitをしておく

git add .
git commit -m "First commit"
git push origin master

gh-pagesブランチを切る

先に切っておかないと不便なのでブランチを切って適当なコミットをする

git symbolic-ref HEAD refs/heads/gh-pages
rm .git/index
git clean -fdx
echo "blog" > README.md
git add .
git commit -m "First commit"
git push origin gh-pages

Travis CIの設定をする

.travis.ymlを書いて自動デプロイするようにする。

GitHubのトークンを取得する

curlでトークンを取得する。USERは置き換えてください。出てきたトークンはメモしておく。

curl -X POST -u USER -H "Content-Type: application/json" -d "{\"scopes\":[\"public_repo\"],\"note\":\"token for pushing from travis\"}" https://api.github.com/authorizations

暗号化してTravisCIに渡すために、RubyGemsからtravisをインストールする

gem install travis

暗号化をする。USERGithubのユーザー名、REPOリポジトリ名、TOKENは先ほど取得したトークンに置き換えてください。

travis encrypt -r USER/REPO GH_TOKEN=TOKEN

実行して出てきた結果は保存しておく。

デプロイするシェルスクリプトを書く

.travis.ymlに一行ずつ書いてると骨が折れるので単一のファイルにまとめて書く。

${USER}/${REPO}は置き換えてください。

script/deploy.sh

#!/bin/bash

set -eu

# hugo関係のファイルを置く場所。
HUGO_DIR=./hugo
echo "HUGO_DIR : ${HUGO_DIR}"

# hugoのバイナリファイル
HUGO_BIN="${HUGO_DIR}/hugo"
echo "HUGO_BIN : ${HUGO_BIN}"

# サイトを生成するディレクトリ
DIST_DIR=./public
echo "DIST_DIR : ${DIST_DIR}"

# hugoのファイルがなかったらダウンロード
if [ ! -e "${HUGO_DIR}" ];then
  echo "Download hugo bin"

  HUGO_PACKAGE=hugo.tgz
  echo "HUGO_PACKAGE : ${HUGO_PACKAGE}"

  echo "Create '${HUGO_DIR}'"
  mkdir ${HUGO_DIR}

  cd ${HUGO_DIR}
  wget -O ${HUGO_PACKAGE} https://github.com/spf13/hugo/releases/download/v0.16/hugo_0.16_linux-64bit.tgz
  tar -xvf ${HUGO_PACKAGE}
  cd ..
fi

# DIST_DIRが無かったらGitHubからclone
if [ ! -d "${DIST_DIR}" ];then
  echo "Clone via GitHub"
  echo "Clone to '${DIST_DIR}'"
  git clone https://${GH_TOKEN}@github.com/${USER}/${REPO} ${DIST_DIR} --depth 1 --branch gh-pages > /dev/null 2>&1
fi

# サイトを生成
echo "Compile site"
${HUGO_BIN}

# 変更があったらcommit
cd ${DIST_DIR}
git add .
d=`date +"%Y/%m/%d %k:%M:%S"`
git diff --cached --exit-code --quiet || git commit -m "Update blog at ${d}"

# GitHubにpush
echo "Push to GitHub"
git push origin gh-pages > /dev/null 2>&1
echo "Successfully deployed."

.travis.ymlを書く

以下のは最低限。必要な場合は自分で追加してください。

language : bash

script :
  - bash ./script/deploy.sh

env:
  global:
    secure: "travis encryptで出てきた値"

適当にコミットしてテストする

適当なファイルに空行を入れるなりしてTravis CIを走らせる。

設定を変更

デフォルトの設定だとURLが長くなったりサマリーが省略されなかったりで不便なので色々設定する。

hugoのSummaryが巨大化する問題を回避する

hugoでブログを作ったけどサマリーがやたら大きくて困ってたので色々調べた。

結論から言えばconfig.tomlにhasCJKLanguage = trueを入れれば回避出来る。もしくはマークダウンの先頭(設定の所)にisCJKLanguage = trueを入れる。

公式ドキュメントを読んだら普通に書いてあった。(https://gohugo.io/overview/configuration)


何も設定しないとサマリーが本文そのままになってサマリーの部分がほとんど本文になる。正直サマリーが本文まるまるだと読む気も失せるので適当な長さで切りたいと思った。調べたらマルチバイト文字の時だけ起こる問題みたいで、英語の時は起きないみたいなので日本語で本文を書く時はオプションで指定する必要があった。

config.tomlで一括で指定する

config.tomlに一行書き足すと全ての記事でisCJKLanguageが自動的に指定される。

# 追加
hasCJKLanguage = true

マークダウンで個別に指定する

一括で指定しないで特定の記事だけ指定する場合はこっちの方が良い

+++
title = "タイトル"
isCJKLanguage = true
+++

PHP CS Fixerを使ってファイルの先頭に自動的にコメントを挿入する

PHPのコーディングスタイルを直すPHP CS Fixerでファイルの先頭にヘッダーを自動的に挿入する。

バージョン1系ではこの方法で出来ますが2系ではこの方法では出来ません

バージョン2系は以下の記事を見てください。

hiroto-k.hatenablog.com

.php_csにヘッダーを追加する

.php_csファイルが無い場合は作る。ある場合は書き加える。

<?php

use Symfony\CS\Fixer\Contrib\HeaderCommentFixer;

// 先頭に追加するコメント
// *等は勝手に挿入される
$header = <<<EOS
This file is part of MyApp.

(c) Hiroto Kitazawa <hiro.yo.yo1610@gmail.com>

For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOS;

HeaderCommentFixer::setHeader($header);

// 省略

fixersにheader_commentを追加する

fixerheader_commentが無いと挿入されないのでheader_commentを追加する。

<?php

// 省略

$fixers = [
    // 省略
    "header_comment",
];

return Config::create()->fixers($fixers);

fixコマンドを実行

通常通り実行する。

ただし、キャッシュを有効にしてると修正されない場合があるので.php_cs.cacheファイルがあれば削除しておく。

./vendor/bin/php-cs-fixer fix

Travis CIでRubyのテストを高速化する

効果

設定 時間
デフォルト 3~4分
並列化 & キャッシュ 1分

方法

.travis.ymlに以下を追加するだけ

# bundlerのオプションを変更
# 並列で実行する数を4にしてインストールするパスをvendor/bundleに変える
install : bundle install --jobs=4 --path vendor/bundle

# vendor/bundleをキャッシュする
cache:
  directories:
    - vendor/bundle

bundle installを並列で実行する

gemが大量にあったり、ネイティブエクステンションを使ってたりするとビルドが遅くなります。なので並列でインストールして高速化します。

bundle installTravis CIのデフォルトだと3個並列で実行されます。これを4個に増やします。

install : bundle install --jobs=4

gemをキャッシュする

テストを走らせる度に何回もbundle installを繰り返してインストールするのは非常に効率が悪いです。なのでgemをキャッシュして再インストールが必要なgemだけインストールします。

bundlerのオプションをオーバーライドしてインストールするディレクトリを変えます。

install : bundle install --jobs=4 --path vendor/bundle

これでvendor/bundleにgemがインストールされます。が、このままだとvendor/bundleはキャッシュされないので設定を追加します。

cache:
  directories:
    - vendor/bundle

これでキャッシュされる。

Circle CIでPHPのmemory_limitを変更する

Circle CIのPHP環境はデフォルトのmemory_limit128Mと非常に低くてPHPUnitがまともに実行できない。

そこでmemory_limitを書き換えてまともに動くようにする。

ビルド環境を調べる

Circle CIではビルド環境としてUbuntu 12.04とUbuntu 14.04が選べる。この環境によってiniファイルの場所が違うので注意。

dependenciesに書き換える処理を追加する

circle.ymldependenciesmemory_limitを追加する。テスト環境の準備段階でもPHPを使うので先に書き換える。値は最大で4096M(CircleCIのメモリ量は4GB)なので4096Mにする。

環境によってiniファイルを作る場所が違うので分けて書きます。

Ubuntu 12.04の場合

circle.yml

dependencies:
  override:
    - 'echo "memory_limit = 4096M" > ~/.phpenv/versions/$(phpenv global)/etc/conf.d/memory.ini'

Ubuntu 14.04の場合

circle.yml

dependencies:
  override:
    - 'echo "memory_limit = 4096M" > /opt/circleci/php/$(phpenv global)/etc/conf.d/memory.ini'

これでmemory.iniが作られてmemory_limit4096Mになってテストが走る。