hugoで生成した静的ページをCircleCIでさくらのレンタルサーバへ自動アップ

2019.2.23

はじめに

hugo を使って記事を書き、bitbucket の git リポジトリへプッシュしたら CircleCI で静的ページを生成してレンタルサーバへアップするみたいなことを、やってみましたので紹介します。

ローカルで行うことは、下記の2つだけになるのでとても快適な執筆活動が行えるようになります。

使用しているレンタルサーバは「さくらのレンタルサーバ ライトプラン」です。

CircleCI の設定方法

CircleCI に追加したリポジトリの中に、下記のディレクトリ1つとファイル1つを作成する必要があります。
個々に記載した設定を CircleCI が自動的に読み取ってファイルを Push したときにデプロイ処理を実行してくれます。

下記のようなイメージでは位置すれば OK です。

hugo-site/
├── .circleci/
|       └── config.yml
├── archetypes
├── assets
├── config
├── content
├── data
├── layouts
├── static
└── themes

config.yml の内容

config.yml の中身は下記のようにしました。

  version: 2
  jobs:
    build:
      docker:
        - image: cibuilds/hugo:latest

      working_directory: ~/hugo

      steps:

        - checkout

        - run:
            name: Update enviroment
            command: apk update && apk add python3 lftp

        - run:
            name: Building blog pages
            command: hugo -d note.mokuzine.net --cleanDestinationDir

        - run:
            name: create tar
            command: tar -zcvf note.mokuzine.net.tar.gz note.mokuzine.net

        - run:
            name: deploy
            command: python3 deploy.py

記述の内容を簡単に説明していこうと思います。

docker:
    - image: cibuilds/hugo:latest

cibuilds/hugo:latestという docker イメージが既にあったので、これを利用してデプロイまで行うようにしました。

- checkout

bitbucket の設定したリポジトリからソースコード(hugo)のデータを取得します。

    - run:
        name: Update enviroment
        command: apk update && apk add python3 lftp

データを取得したら、コンテナ内のパッケージをアップデートして、python3 と lftp をインストールします。

    - run:
        name: Building blog pages
        command: hugo -d note.mokuzine.net --cleanDestinationDir

hugo -dコマンドを使ってサーバに上げるためのコンテンツデータを生成します。

    - run:
        name: create tar
        command: tar -zcvf note.mokuzine.net.tar.gz note.mokuzine.net

ここからは私の独自方法になりますが、生成したコンテンツデータを tar で固めます。

    - run:
        name: deploy
        command: python3 deploy.py

自作のデプロイ用スクリプトdeploy.pyを実行して、レンタルサーバへ先程作成した tar ファイルをアップロード、データ入れ替えを行います。

deploy.py の内容

CircleCI からレンタルサーバへのアップロードはdeploy.pyが行っています。
さらに、deploy.pyreplace.phpという PHP スクリプトを実行して、古いコンテンツデータとアップロードしたコンテンツの入れ替えを行っています。
さくらインターネットのライトプランでは php が標準で使用できますので、このようにしています。

import subprocess
import tarfile
from ftplib import FTP
import shutil
import os
import urllib.request

ftp = FTP(
    "アップロード先のレンタルサーバ",
    "FTPユーザ",
    passwd="FTPユーザのパスワード"
)

cont = 'note.mokuzine.net.tar.gz'
with open(cont, "rb") as f:
    ftp.storbinary("STOR ./www/"+cont, f)

repsh = 'replace.php'
with open(repsh, "rb") as f:
    ftp.storbinary("STOR ./www/"+repsh, f)

url = 'http://アップロード先のレンタルサーバ/replace.php'

req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
    body = res.read()

ftp.delete("./www/" + repsh)

コンテンツの入れ替えは、replace.phpが行い、入れ替えが終わったらreplace.phpをサーバ上から削除して、サーバに不要なファイルを残さないようにしています。

replace.php の内容

新しく生成したコンテンツデータのアップロードが完了したあとは、replace.phpを使って古いコンテンツを削除して新しいコンテンツを解凍しています。
解凍が終わったら、tar ファイルを削除してゴミを残さないようにしています。

<?php
    echo "repace";
    $sitename = "note.mokuzine.net";
    $zipfile = $sitename . ".tar.gz";
    if (file_exists($zipfile )) {
        echo shell_exec("rm -rf {$sitename}");
        echo shell_exec("tar -zxf {$zipfile}");
        echo shell_exec("rm -rf {$zipfile}");
    } else {
        echo "error";
    }
    return;

echo "repace";など一部エコーしている部分は、手動でコンテンツ入れ替えのテストしているとき名残なので、特に意味はないです。

関連記事