はじめに
前回は331件の記事を移行スクリプトで変換しました。
今回はGitHubにpushするだけでAstroのビルドからサーバーへのデプロイまで自動化するCI/CDを構築します。
コアサーバーの制約
コアサーバーはSSH接続に「接続元IPアドレスの事前承認制」を採用しています。
GitHub ActionsのランナーはIPが動的に変わるため、SSH/SFTPは使用不可です。FTP一択になります。
GitHub Secrets の登録
リポジトリの Settings → Secrets and variables → Actions → New repository secret から以下を登録します。
| シークレット名 | 内容 |
|---|---|
FTP_SERVER | FTPサーバーのホスト名 |
FTP_USERNAME | FTPユーザー名 |
FTP_PASSWORD | FTPパスワード |
FTP_SERVER_DIR | アップロード先ディレクトリ(末尾に/必須) |
ワークフローファイル
.github/workflows/deploy.yml を作成します。
name: Build and Deploy to Coreserver
on:
push:
branches:
- main
concurrency:
group: deploy
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup Node.js
uses: actions/setup-node@v4.4.0
with:
node-version: '22'
cache: 'npm'
- name: Cache Astro build
uses: actions/cache@v4
with:
path: .astro
key: ${{ runner.os }}-astro-${{ hashFiles('src/data/blog/**', 'src/pages/**', 'src/layouts/**', 'src/components/**') }}
restore-keys: |
${{ runner.os }}-astro-
- name: Install dependencies
run: npm ci
- name: Build
run: npx astro build
- name: Deploy HTML/CSS/JS via FTP (differential)
uses: SamKirkland/FTP-Deploy-Action@v4.3.5
with:
server: ${{ secrets.FTP_SERVER }}
username: ${{ secrets.FTP_USERNAME }}
password: ${{ secrets.FTP_PASSWORD }}
server-dir: ${{ secrets.FTP_SERVER_DIR }}
local-dir: ./dist/
exclude: |
**/posts/**
- name: Deploy new images via FTP
env:
FTP_SERVER: ${{ secrets.FTP_SERVER }}
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
FTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
FTP_SERVER_DIR: ${{ secrets.FTP_SERVER_DIR }}
run: |
sudo apt-get install -y lftp
lftp -u "$FTP_USERNAME,$FTP_PASSWORD" \
-e "set ftp:ssl-allow no; set net:timeout 60; mirror -R --only-missing ./dist/posts/ ${FTP_SERVER_DIR}posts/; quit" \
ftp://$FTP_SERVER
設計のポイント
デプロイを2ステップに分けた理由
| ステップ | 対象 | 方式 | 理由 |
|---|---|---|---|
| ステップ1 | HTML/CSS/JS | 差分転送(FTP-Deploy-Action) | 記事を更新するたびに変わるので差分のみ送る |
| ステップ2 | 画像(posts/) | 未存在ファイルのみ転送(lftp --only-missing) | 一度アップした画像は変わらないため毎回再送しない |
画像を差分転送に含めると、331件分の大量ファイルが毎回転送対象になってしまいます。
--only-missing で「サーバーにまだないファイルだけ」送ることで効率化しています。
concurrency の設定
連続でpushした場合に複数のワークフローが同時実行されると、FTP転送が競合してサーバー上の状態が壊れる可能性があります。
cancel-in-progress: true にすることで新しいpushが来たら古いビルドをキャンセルし、常に最新のコードだけがデプロイされます。
lftpを使う理由
FTP-Deploy-Actionはコアサーバーとの相性が悪く、大量ファイル転送時に ECONNRESET エラーが頻発しました。
画像転送には安定性の高い lftp を使うことで解消しました。
ハマりポイント
FTP_SERVER_DIRの末尾に/がないと転送先パスがずれてエラーになります。必ず末尾に/を付けてください- FTP-Deploy-Action は
.ftp-deploy-sync-state.jsonをサーバーに保存して差分管理するため、初回は全ファイルが転送されます
まとめ
コアサーバーのSSH制約があってもFTPで問題なく自動デプロイできます。
2ステップデプロイとlftpの組み合わせで安定した運用が実現できました。
次回はGoogle AdSenseの設置方法を紹介します。