hugoで生成した静的ページをCircleCIでさくらのレンタルサーバへ自動アップ
はじめに
hugo を使って記事を書き、bitbucket の git リポジトリへプッシュしたら CircleCI で静的ページを生成してレンタルサーバへアップするみたいなことを、やってみましたので紹介します。
ローカルで行うことは、下記の2つだけになるのでとても快適な執筆活動が行えるようになります。
- 記事を書く
- git commit & git push
使用しているレンタルサーバは「さくらのレンタルサーバ ライトプラン」です。
CircleCI の設定方法
CircleCI に追加したリポジトリの中に、下記のディレクトリ1つとファイル1つを作成する必要があります。
個々に記載した設定を CircleCI が自動的に読み取ってファイルを Push したときにデプロイ処理を実行してくれます。
- .circleci ディレクトリの作成
- .circleci/config.yml ファイルの作成
下記のようなイメージでは位置すれば 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.py
がreplace.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";
など一部エコーしている部分は、手動でコンテンツ入れ替えのテストしているとき名残なので、特に意味はないです。