一日坊主ですが……
今年の1/1にブログを始めたにもかかわらず、一度も記事を揚げることなく大晦日を迎えてしまった。三日坊主どころが一日坊主である。
Twitterに脳死でうめき声を垂れ流すことに慣れてしまった今、ブログを書くことはあまりにも難しい。 それに加えて更新が滞っていた理由として、書きかけの記事を作りにくいという問題があった。 このブログがGitHubで公開リポジトリとなっており、書きかけの記事がmainブランチになくサイトでは公開されていないとしても、GitHubでは丸見えになっていたのである。 いや、プライベートリポジトリにしてしまえば解決するのだが、このブログもあまりにも寂しいGitHubのアカウントを少しでも賑やかそうとしたところがあり、できればパブリックのままにしておきたい。
そこで、ブログのレイアウト等を記述しているvueやcssファイルはそのままに、記事の中身にあたるmarkdownファイルを入れたディレクトリだけをプライベートリポジトリにすることにした。
構築手順
構築は以下の順で行う
- contentディレクトリを別リポジトリに移す
- git submoduleで1.で移したリポジトリを参照するようにする
- fleekでデプロイするとき、git submoduleも同時にcloneできるようにする
contentディレクトリを別リポジトリに移す
これは何も工夫することはなく、単に移すだけである。
@nuxt/contentは/content
ディレクトリにあるmarkdownファイルを記事として扱い、このブログでは/content/posts
以下に記事を入れるように設計している。詳しくはこちらの記事を参照。
そのため、postだけを移すことも考えたが、今後ディレクトリ構造を変更した際(つまりURL設計を見直したとき)、また同じ作業を実施するのはだるいのでcontentごと移すことにした。
ちなみに、ブログに挿入している画像は、/static
以下においてあるので変わらずGitHubで丸見えなのだが、画像を選ぶのは大抵最後なので公開したままでも構わない。
将来画像もプライベートリポジトリに入れたくなったときは同様の手順を検討する。
(画像等のサイズによってはGit LFSの方が良いかもしれない)
git submoduleで1.で移したリポジトリを参照するようにする
続いてgit submoduleを導入する。 submoduleに分離することで、記事の執筆と更新の作業を分離し、うっかり公開されてしまうことを防ぐことができる。
上の手順で既に/content
ディレクトリは削除されているので、/
で以下を実行する
git submodule add [email protected]:PikkamanV/NaukaSiteContent.git
これで/.gitmodule
ファイルが生成され、submoduleの追加が完了した。なお、HTTPSではなくSSHで追加した理由は後述する。
submoduleを追加するとVScodeのgit管理ウィンドウは以下のように変わる。
この状態で/content
以下を編集した場合NaukaSiteContentのウィンドウに変更したファイルが表示され、NaukaSiteの方は/content
だけに変更が入ったように表示される。
これはgit submoduleがsubmoduleで読み込んだリポジトリのコミットを参照しているからであり、そのリポジトリであるNaukSiteContent内のファイルを編集すると最終コミットから差分が生じるためである。
このNaukaSiteの/content
の方もコミットしてしまうと、NaukaSiteリポジトリが読んでいる先のコミットが変更されてしまうため、記事の意図しない公開を防ぐためには、NaukaSiteContentの方だけをコミットしておく。
まとめると、これからは以下の手順で記事の更新を行う。
- NaukaSiteリポジトリでcontent以下に移動する
- NaukaSiteContentリポジトリに入るので、新しくブランチを切る
- 新しく切ったブランチ上で記事を書く
- 記事を書き終わったらNaukaSiteContentのmainブランチにマージする
- NaukaSiteリポジトリに戻り、mainブランチのcontentが更新されている扱いになるので、それをコミット&プッシュする
- fleekがmainブランチの更新を検知し、mainブランチがデプロイされる。
fleekでデプロイするとき、git submoduleも同時にcloneできるようにする
最後にデプロイ時にプライベートリポジトリになっているNaukaSiteContentをfleekが読めるようにする。
fleekGitHubでアプリ連携を行ったとしても、ビルドするメインのリポジトリ以外にはアクセスしてくれない。 ためしにGitHubのアカウント設定から連携アプリでfleekを探し、既にアクセスが許可されていたNaukaSiteに加えてNaukaSiteContentを許可してもcloneはできなかった。 そこで、ビルド時に実行するコマンドを指定できるので、その中でGitHubに登録したdeploy keyによるSSH接続でcloneを行う。
具体的には以下の順で実行する。
- mkdir -p ~/.ssh
- echo "$DEPLOY_KEY" > ~/.ssh/id_ed25519
- perl -pe "s;😼;\n;g" -i ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- git c core.sshCommand="ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=no -F /dev/null" clone [email protected]:PikkamanV/NaukaSiteContent.git content
- git submodule update --init --recursive
- yarn && yarn build --target static
- yarn export
ただし、実際の設定画面では1行でしか指定できないので&&
で各コマンドをつないでいる。(yarn export
はもう古いという話は一旦無視させていただく)
なお、先のsubmoduleでHTTPSではなくSSH接続を選んだ理由であるが、鍵の漏洩時の影響を最小限に抑えるためである。 GitHubの場合、personal access tokenを用いることでHTTPS接続でもプライベートリポジトリをcloneすることができる。 しかし、トークンはリポジトリごとではなくアカウントに紐付くため、あるサービスからトークンが漏洩すると、そのサービスに連携していないプライベートリポジトリまでもが編集可能になってしまう。 また、deploy keyの場合write権限を与えないこともできるので、もし漏洩したとしても、pushされるのを防ぐことができる。 よって設定が少々面倒ではあるが、SSH接続によってcloneすることが望ましい。
ただしwork aroundとして、fleekの管理画面ではdeploy keyそのものは登録できないので、環境変数として登録することにする。
さらに、環境変数は当然複数行では登録できないので、元の秘密鍵をあらかじめ決めた区切り文字(上の例では😼)で1行になるように加工し、読み込み前に改行に変換している。
そうして登録した秘密カ鍵を指定してNaukaSiteContentリポジトリをcloneし、git submodule update
でsubmoduleとして読み込んでいる。
こうすることでビルド時にcontentディレクトリの中身が存在するものとしてビルドすることができる。
おわりに
こうして書きかけの記事を公開することなくGitHubにpushすることができるようになった。また1つブログをサボる理由が失われてしまったとも言える。