N度目の正直の新しいブログを立ち上げ
こんにちは、yagihashです。
Obsidianからブログを更新できるようにした — tellme.tokyoを見て「お、それいいじゃん」と思い立ってしばらく経ちまして、ssrf.devを立ち上げました。所要時間はClaude Codeにぶん投げて12時間くらい?ブログはいろいろやってきましたが正直あまり長続きしなくて、何度目かわかりませんが今回こそは長生きして欲しいなーと思っています。
やってること自体はbabarotとほぼ同じなんですが、ガワを作るところからだったりしたのでちょっと時間かかったかなーという感触。とはいえ今回まじで自分でコード1行も書いてないですね。同期用のGitHub AppのPrivate Keyを入れるKMSとかWIFの設定含めて何もかもClaude Code任せでした。
深夜に思い立ってCloudflare Pagesでプレビューを確認できる環境まで整えて、あとはremote-controlでベッドから作業して、変更の都度プレビューで確認、みたいな感じでした。寝落ちして朝起きてmacで作業を再開して、なんやかんやあって今に至るという具合です。
普段ブログはもっぱらyagihash|しずかなインターネットに書いてるんですが、コードとか載せようとするとさすがにちょっと用途が違うよね、という感じがあり、かといって何もかもzennに載せるのもちょっとなぁというのがあり、ちょうどいいブログ枠としてこれに期待しています。
裏側
記事公開までのフロー
Claude Codeに書かせたので合ってるかは知らないです。冗長だなーと思いつつ書き直す元気はないのでほぼそのまま載せます。
flowchart TD
subgraph local["ローカル"]
obsidian["Obsidian (ブログ執筆)"]
end
subgraph vault["yagihash/obsidian"]
main["main blog/*.md"]
end
subgraph gcp["Google Cloud"]
wif["Workload Identity Federation"]
kms["Cloud KMS (GitHub App 秘密鍵)"]
end
subgraph actions["GitHub Actions (yagihash/obsidian)"]
sync["sync-blog-to-ssrf-dev push トリガー"]
reconcile["reconcile-blog-to-ssrf-dev 毎時 / 手動"]
end
subgraph ssrfdev["yagihash/ssrf.dev"]
branch["obsidian/{slug} ブランチ (signed commit)"]
pr["Pull Request"]
site["🌐 ssrf.dev"]
end
obsidian -->|"Obsidian Git 自動 push"| main
main -->|"blog/*.md 変更時"| sync
main -->|"毎時"| reconcile
sync & reconcile -->|"WIF 認証"| wif
wif --> kms
kms -->|"Installation Token"| sync & reconcile
sync -->|"変換 + signed commit"| branch
reconcile -->|"差分検出 + signed commit"| branch
branch --> pr
pr -->|"手動マージ"| site
Vault→ブログのrepoの同期ワークフロー
pushで動くやつ
基本的にはこっちのワークフローでObsidianのVaultに置かれたMarkdownファイルとか画像ファイルを良い感じにしてブログのrepoに配置するPRを立てに行く、という流れです。
flowchart TD
push["blog/*.md が push された"]
changed["変更ファイルを検出 git diff HEAD~1 HEAD"]
meta["フロントマターから slug / title / pubDate 抽出"]
branch{"obsidian/{slug} が origin に存在?"}
checkout_existing["既存ブランチを checkout"]
checkout_new["新規ブランチを作成"]
convert["convert-blog-post.py Obsidian → Astro 形式に変換 (![[画像]] →  など)"]
signed["push-signed-commit.py GitHub API で signed commit 作成"]
pr_exists{"open な PR が存在?"}
create_pr["gh pr create [obsidian] Add/Update: タイトル"]
skip["スキップ"]
push --> changed --> meta
meta --> branch
branch -->|"Yes"| checkout_existing
branch -->|"No"| checkout_new
checkout_existing & checkout_new --> convert --> signed
signed --> pr_exists
pr_exists -->|"No"| create_pr
pr_exists -->|"Yes"| skip
スケジュールor手動で動くやつ
必要かどうかけっこう悩んだのですが差分見て全部綺麗にするPRを立てる、みたいなワークフローはあっても良さそうだな、と思って用意しました。使うかどうかは今のところわからず。
flowchart TD
trigger["毎時 or 手動実行"]
compare["reconcile-blog-posts.py blog/ と ssrf.dev/ を全件比較"]
changes["変更リスト (JSON) add / update / delete"]
loop["各記事をループ処理"]
add["convert-blog-post.py で変換・コピー"]
update["convert-blog-post.py で変換・コピー"]
delete["rm でファイル削除"]
signed["push-signed-commit.py で signed commit"]
pr["PR 作成 or スキップ"]
trigger --> compare --> changes --> loop
loop -->|"action=add"| add
loop -->|"action=update"| update
loop -->|"action=delete"| delete
add & update & delete --> signed --> pr
お悩みポイント
Obsidianのアプリ同士の同期はObsidian Syncを使っているので、例えば出先でiPhoneで記事を書いて各端末に同期する、というところまでは実現可能なんですが、GitHubへの同期はiOSとの相性があまりよくないCommunity PluginのGitを使っていて、ここが最後の壁になっています。(つまり今はiOS→GitHubの経路がない)
常時起動してObsidian Syncで流れてきた差分をGitHubに流してくれる環境をひとつ持っておくのがたぶん簡単なんですが、なんだかなぁという感じです。Claude Codeのremote-controlとかloopとかももっとがっつり使いたいですし、Mac miniを買うか割と真剣に迷っています。
所感
Vault→ブログのrepoにPR立てにいくところとか、Markdownの変換とか、個人的にはいくつか「めんどくさいなー」というポイントがあったんですが、イマドキのめんどくさいのハードルはめちゃくちゃ下がったのを改めて強く感じました。Actionsがコケたのもrun-id渡してこれ見て直して、で終わりですし、試行錯誤の質がだいぶ変わったと思います。
せっかく作ったのでちょこちょこ更新していきたいなーと思います。次回をお楽しみに。