何回目かわからないけどブログを作りました。
試したい技術が現れるたびにブログを作っている気がしますが、今回はちゃんと更新していけるように頑張ります。
このブログは、Obsidianのvault(保管庫 ローカルのディレクトリ)の一部のディレクトリをブログ記事として切り出してSSGで記事化し公開する構成になっているので、その説明をします。
Quartz自体の説明はここではしません。
この構成のメリット
pushごとに公開
Obsidianのノートを更新してpushするたびにデプロイjobが実行されるので公開が楽です。
プライベートなvaultと同一リポジトリ内で独立
通常、QuartzなどのSSGでブログを作るときは、SSGリポジトリの内部にObsidianのvaultを配置することになると思います。
その場合、プライベートなvaultとは独立することになりますが、管理が面倒ですし、LLMの恩恵を受けながら記事を書きたい場合は同一のリポジトリで管理して、同じ場所でドキュメントをindex化して活用したいです。
そういったことができるようになります。
構成
リポジトリは2つ登場します。
- obsidian-vault
- プライベートなObsidian vaultで普通にドキュメント管理として使う
_published
ディレクトリ内のドキュメントのみブログ記事としてビルドして公開したい
- obsidian-blog
- ブログのSSGやUIなどを管理する(つまりこのブログの本体)
- ソースコードはこちら
アプローチは、obsidian-vaultの _published
ディレクトリ内に変更があったときにGitHub Actionsでeventをdispatchしてobsidian-blog側のGitHub Actionsのトリガーにし、obdsidian-blogではobsidian-vaultをcloneしてきて _published
内のみSSGで記事を生成して公開するというものです。
ローカルでは obsidian-blog の content
で obsidian-vault のシンボリックリンクを貼ればローカルでもプレビューできます。
sequenceDiagram participant OV as obsidian-vault participant GA1 as GitHub Actions participant GB as obsidian-blog participant GA2 as GitHub Actions participant GH as GitHub Pages OV->>GA1: _published/に差分あり GA1->>GB: vault-updated event GB->>GA2: triggered GA2->>OV: クローン GA2->>GA2: Quartz 4でビルド GA2->>GH: デプロイ
Deploy用yml
これで _published
に差分があったときに obsidian-blog
のGAが受け取れるeventをdispatchします。
DISPATCH_TOKEN
は、obsidian-blogの contents:read,write
権限を持つ personal access token(PAT)です。
name: Trigger Blog Deploy on Published Changes
on:
push:
branches:
- main
paths:
- '_published/**/*.md'
jobs:
dispatch:
runs-on: ubuntu-latest
steps:
- name: Trigger deployment in obsidian-blog repo
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.DISPATCH_TOKEN }}
repository: tachibanayu24/obsidian-blog
event-type: vault-updated
これで obsidian-vault
から受け取ったeventをトリガーにしてデプロイを実行します。 obsidian-blog
でmainブランチにpushしたときにも実行します。
VAULT_ACCESS_TOKEN
は、obsidian-vaultの contents:read
権限を持つ personal access token(PAT)です。
name: Deploy Blog
on:
push:
branches:
- main
repository_dispatch:
types: [vault-updated] # obsidian-vaultの `_published` が更新されたらdispatchされる
permissions:
contents: write
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout obsidian-blog Repo
uses: actions/checkout@v4
with:
path: obsidian-blog
- name: Checkout obsidian-vault Repo (to temp location)
uses: actions/checkout@v4
with:
repository: tachibanayu24/obsidian-vault
path: vault-temp
token: ${{ secrets.VAULT_ACCESS_TOKEN }}
- name: Prepare content directory
run: mkdir -p obsidian-blog/content
- name: Copy published content
run: |
if [ -d "vault-temp/_published" ] && [ "$(ls -A vault-temp/_published)" ]; then
cp -r vault-temp/_published/* obsidian-blog/content/
else
echo "Warning: vault-temp/_published directory is empty or does not exist."
fi
# attachmentsは通常 `_published` には配置しないので、画像など正しく表示するためにこれもコピーする
- name: Copy attachments to content root
run: |
if [ -d "vault-temp/_config/attachment" ] && [ "$(ls -A vault-temp/_config/attachment)" ]; then
cp -r vault-temp/_config/attachment/* obsidian-blog/content/
else
echo "Info: vault-temp/_config/attachment directory is empty or does not exist."
fi
- name: Setup Node, Install, Build
working-directory: obsidian-blog
env:
NODE_ENV: production
run: |
npm ci
npx quartz build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./obsidian-blog/public
cname: blog.tachibanayu24.com
おわり
これで単一vault内でプライベートな領域と公開用の領域で分けることができました。