Counts the Clouds

Headless Wordpressの勉強 (1)

Headless WordPressの勉強〜環境構築からプラグイン作成の準備まで〜
2022.07.14

Next.js
GitHub Actions
WordPress

timothy-meinberg-0XU5EtH7O6s-unsplash

Gitプロジェクトの設定

2つのサブモジュールを持つGitプロジェクトを構築する。

フロントエンドのプッシュをトリガーにGitHub Actionsをキックしたいので、リポジトリを分けるためサブモジュール化する。

% mkdir headless-wordpress-research && cd $_
% git init

フロントエンド側。Next.jsのプロジェクトを生成。

% npx create-next-app@latest --ts
npx: 1個のパッケージを2.472秒でインストールしました。
 What is your project named? frontend

サブモジュールにするためにはGitを初期化する必要がある。frontendディレクトリはcreate-next-appでGitの初期化が行われているのでこのままでOK。

次に、WordPressのサブモジュール。docker-compose.ymlはあとで使う。

% touch docker-compose.yml
% mkdir -p wordpress && touch $_/{Dockerfile,.gitignore}
% mkdir -p wordpress/scripts && touch $_/wp-install.sh
% mkdir -p wordpress/plugins/github-actions-kicker && touch $_/index.php

サブモジュール化するため、手動で初期化しておく。ファイルが空のままだが内容はあとで追加する。

% cd wordpress
% git init
% git add .
% git commit -m "first commit"
% cd ..

それぞれサブモジュールとして親プロジェクトに追加。

% git submodule add ./frontend
Adding existing repo at 'frontend' to the index
% git submodule add ./wordpress
Adding existing repo at 'wordpress' to the index

親プロジェクトをコミットする

% git add .
% git commit -m "first commit"

GitHubにリポジトリを作成して、それぞれpushしておく。

Next.jsアプリをGitHub ActionsでビルドしてFTPする

ここから本題。フロントエンドのソースコードをGitHubにプッシュすると、Next.jsのアプリをビルドしてFTPでレンタルサーバーにデプロイされるようにする。

% cd frontend

SSGのためexportコマンドを追加。

    "export": "next export",

create-next-appで生成されたデフォルトのアプリを少し修正。

コマンドが動くことを確認。

% yarn build && yarn export
yarn run v1.22.17
# ...
  Done in 1.09s.

画面も確認しておく。

% yarn dev

Next.jsのデフォルト画面

ワークフローの定義

フロントエンドにGitHub Actionsのワークフローを書くためのファイルを追加。

% mkdir -p .github/workflows/ && touch $_/deploy.yml

以下のようなワークフローを定義。

# frontend/.github/workflows/deploy.yml
name: Deploy Next.js SSG with FTP

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-20.04

    steps:
      - name: 🚚 Checkout
        uses: actions/checkout@v2

      - name: 🔧 Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: 14.x
          cache: yarn

      - name: 📦 Install dependencies
        run: yarn --frozen-lockfile

      - name: 🔨 Build
        run: yarn build && yarn export

      - name: 📂 Sync files
        uses: SamKirkland/FTP-Deploy-Action@4.3.0
        with:
          server: ${{ secrets.FTP_SERVER }}
          username: ${{ secrets.FTP_USER }}
          password: ${{ secrets.FTP_PASSWORD }}
          local-dir: './out/' # Must end with `/`

変更をプッシュする前にワークフローで使用するsecretsを定義しておく。リポジトリの(アカウントのではない)Settings→Secrets→ActionsにFTP_SERVERFTP_USERFTP_PASSWORDを定義。

FTPでデプロイする部分はFTP Deployを使用する。プッシュするとワークフローが実行され、FTPでサーバーにアップロードされる。

FTP Deployは2回目以降は差分アップロードするので、最初からアップロードし直したいときはリモートサーバーの.ftp-deploy-sync-state.jsonを削除する。削除しないと差分の同期に失敗するのでデプロイも失敗する。

GitHubへのプッシュをトリガーにして、Next.jsのアプリをレンタルサーバーにデプロイできた。

WordPressからGitHub Actionsをキックする(準備編)

今度は、WordPressのコンテンツの変更に応じて、フロントエンドがデプロイされるようにしたい。

フロントエンドのワークローにWordPressからキックするためのrepository_dispatchのイベントを用意。

# frontend/.github/workflows/deploy.yml
# ...
on:
  # ...
  repository_dispatch:
    types:
      - wp_github_actions_kicker_event
# ...

Personal Access Tokenの作成

GitHubアカウントのSettings→Developer Settings→Personal Access Tokenとたどって、「Generate new token」をクリック。New personal access tokenの画面で「workflow」のスコープをチェックすると「repo」のスコープも自動でチェックされるので、「Generate token」する。検証なので期限は7日とかにしておくが、実際にどうするかは考える必要がある。作成したトークンは控えておく。

Personal Access Tokenを設定する様子

Personal Access Tokenを使用して、上で作成したイベントがトリガーされるか確認。

curl -X POST \
-H "Authorization: token <YOUR GITHUB PERSONAL ACCESS TOKEN>" \
-H "Accept: application/vnd.github.everest-preview+json" \
-d '{"event_type": "wp_github_actions_kicker_event"}' \
-i https://api.github.com/repos/<ORGANIZATION>/<REPOSITORY>/dispatches

GitHub Actionsが起動するのを確認できた。

GitHub Actionsがキックされた様子

開発環境の構築

実際にはcurlではなくWordPressの自作プラグインでイベントをキックするため、Dockerの開発環境を用意する。

# docker-compose.yml
version: '3'

services:
  mysql:
    container_name: headless-wp-mysql
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    container_name: headless-wp-wordpress
    depends_on:
      - mysql
    build:
      context: ./wordpress
      dockerfile: Dockerfile
    ports:
      - '8000:80'
    volumes:
      # プラグインをマウント
      - ./wordpress/plugins/:/var/www/html/wp-content/plugins/
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress

  mailhog:
    container_name: headless-wp-mailhog
    image: mailhog/mailhog
    ports:
      - '8025:8025'
      - '1025:1025'

  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: headless-wp-pma
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql # mysqlサービス名を指定
      - PMA_USER=root
      - PMA_PASSWORD=somewordpress
    links:
      - mysql
    ports:
      - 8080:80
    volumes:
      - ./phpmyadmin/sessions:/sessions

volumes:
  db_data:

WordPressコンテナのDockerfile。wp-cliをインストール。

# wordpres/Dockerfile
FROM wordpress:latest

RUN curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \
    && chmod +x wp-cli.phar \
    && mv wp-cli.phar /usr/local/bin/wp \
    && wp --info
RUN chown www-data /var/www

COPY --chown=www-data:www-data ./scripts/wp-install.sh ./scripts/wp-install.sh
RUN chmod +x ./scripts/*

コンテナ起動後にWordPressのインストールと初期設定を行うためのスクリプト。WordPressのDockerfileに書いてもWordPressが見つからず実行できないので、コンテナが立ち上がったあとに手動で実行する。

# wordpress/scripts/wp-install.sh
#!/bin/bash

wp core install \
--url="http://localhost:8000" \
--title="test" \
--admin_user='admin' \
--admin_password='password' \
--admin_email='admin@example.com'

# デバッグログを出す
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_DISPLAY true --raw
wp config set WP_DEBUG_LOG true --raw

# 使わないと思うけどメール環境
wp config set WPMS_ON true --raw
wp config set WPMS_SMTP_HOST 'mailhog'
wp config set WPMS_SMTP_PORT 1025 --raw
wp config set WPMS_SSL ''
wp config set WPMS_SMTP_AUTH false --raw
wp config set WPMS_SMTP_AUTOTLS false --raw
wp config set WPMS_MAILER 'smtp'

wp language core install --activate ja
wp option update timezone_string 'Asia/Tokyo'
wp option update date_format 'Y-m-d'
wp option update time_format 'H:i'

wp plugin delete hello
wp plugin delete akismet

プラグインを認識させる最低限の内容。

<?php
// wordpress/github-actions-kicker/index.php

/*
  Plugin Name: GitHub Actions Kicker
  Plugin URI:
  Description: GitHub Actionのトリガー
  Version: 1.0.0
  Author: Yuji Ito
  Author URI:
  License: MIT
 */

?>

コンテナをビルドして起動しインストールスクリプトを実行。ユーザーを指定しているのはrootユーザーで実行するとWP-CLIに怒られるため。全部のコマンドに--allow-rootオプションを指定するのはいまいちなので、www-dataユーザーを指定して実行することにした。

% docker-compose build
% docker-compose up -d
% docker exec -it --user 33:33 headless-wp-wordpress /bin/bash ./scripts/wp-install.sh

これでプラグインがリストに表示される。最後のコマンドは長いのでコンテナ起動後に自動的に実施したかったが、そこまでは設定できなかった。

プラグインリストに表示された様子

これから追加するカスタムプラグイン以外のプラグインを除外するようにwordpressディレクトリの.gitignoreファイルに追加。あとでカスタムテーマを使うため、カスタムテーマ以外のテーマも除外しておく。

# wordpress/.gitignore
plugins/*
!plugins/github-actions-kicker
themes/*
!themes/headless-wordpress-research

phpmyadminのセッション用のボリュームを除外。

# .gitignore
phpmyadmin

今回はここまで。