Bitbucket や GitHub で自動デプロイする PHP スクリプト (2019年版)

GitHub and SourceTree

GitHub や Bitbucket などの Git ホスティングサービスの Hook や Webhook サービスを使って、Git に Push した時、自動的にサーバー側で最新版の master ブランチを pull するための PHP を拾ってきて、数年間運用し続け、この度大幅アップデートを行いました。

旧バージョンの2019年版です

更新: 2019年8月9日

大きいプロジェクトであれば、きちんと Travis CI などのサービスを使いましょう。

宣伝:ウェブサイトを作るCMS は concrete5 で決まり!(世界では、アメリカ陸軍、スイス政府、日本でも、官公庁、銀行、市町村サイト、国公立大学で使われています。)

 

豆知識: Hook とは

Git には、標準で hook と呼ばれる機能があります。アクションの各段階において、シェルスクリプトを実行できるものです。

UNIX系の OS を使っていて黒い画面に詳しい人は、詳しくは、

を見ると、いろいろできます。

 

豆知識: Webhook とは

Git の hook は Mac を含めた UNIX 系のPCで黒い画面を使いこなしている人しか恩恵はありませんが、Web関係者で Git を使って楽をしたい人にオススメなのが、GitHub が提供している Webhooks や、 Bitbucket の Hooks 機能です。

GitHub や Bitbucket でこの機能を使いこなすと、例えば、 Git で master ブランチ Push された時、自動的に本番サーバーに Git の情報を Fetch/Pull して FTP でアップする必要がなくなります。

ちょっと高度に活用すると、 develop という名前のブランチを作って、それは開発環境サーバーに自動的に Fetch/Pull するように設計できます。

さらに高度に活用すると、 Push された時に本番や環境サーバーでも Grunt とか Gulp とかの自動タスクをを本番サーバーでも走らせたりなどを行うことが出来ます。

 

Webhook を PHP スクリプトを使って、自動的に git pull されるスクリプトを見つけて、ちょっと改造してみた。

これらの Webhook は、GitHub や Bitbucket 側で指定したサーバーなどに信号を送るだけです。なので、信号を受け取ってから、サーバー側でアクションを起こす仕組みを作る必要があります。

今回は、GitHub や Bitbucket から、「 git fetch 」する PHP スクリプトを叩く仕組みを探して改造してみました。

いろいろ探してたんですが「Using Bitbucket for Automated Deployments」や「Automated git deployments from Bitbucket」というブログ記事をのサンプルを見つけさせていただきました。

 

サーバー準備

まず、サーバーの準備が必要です。

サーバーは

  • トップディレクトリに WordPress や concrete5 がインストールされている想定
  • PHP が exec() 使える
  • Git がインストールされている
  • 非公開 Git レポジトリを使う場合は、 SSH 公開鍵のサポート
  • 「https 」がサポートするとセキュア
  • Basic 認証がある
  • Git デプロイの実行場所とコードの場所が違うドメイン or サブドメイン上にあって見つかりにくい

以上を満たしている

今日準備する Deploy コードは PHP を利用しているので、PHP が動くサーバーである必要があります。

 

Git レポジトリを作成 & .gitignore ファイルを作成

Git レポジトリを作成し、concrete5 や WordPress などの CMS サイトを使っている人は .gitignore ファイルを作りましょう。

参考までに、WordPress や concrete5 に最適化された gitignore ファイルのサンプルを置いておきます。

ここでは、

  • concrete5 の files 以下のファイル郡を無視
  • WordPress の wp-contens/uploads/ フォルダ以下のファイル郡を無視
  • 後述の deployment.phpdeployment.log を無視
  • 追加アドオンやプラグインはあえて保存
  • WordPress や concrete5 の本体もあえて管理

しています。適宜編集してやってください。

#
# .gitignore sample for concrete5 & WordPress projects
# concrete5 & WordPress 用 .gitignore サンプルファイル
#
# rename this file to '.gitignore' when you actually use it
# 使用の際はファイル名を[.gitignore]に変更してください
#
 
# ignore system files
.DS_Store
thumbs.db
__MACOSX
._*

# ignore the error log and .htaccess and others
error_log
.htaccess
.ftpquota

# ignore everything but the index.html
/application/config/database.php
/application/config/doctrine/*
/application/config/generated_overrides/*
/application/files/*
!/application/files/.gitkeep
!/application/files/.gitignore
# /concrete/*
/updates/*
/config/site.php
/files/*
!/files/index.html
!/files/.gitkeep
!/files/.gitignore
/wp-content/blogs.dir/*
/wp-content/cache/*
/wp-content/uploads/*

# ignore sitemap.xml
sitemap.xml

# Ignore hook log
deployments.php
deployments.log

 

Deploy 用にサーバーの公開鍵を GitHub や Bitbucket に登録

各サーバーで、Deploy 用公開鍵を生成します。

下記ステップの詳しくは「4.3 Git サーバー – SSH 公開鍵の作成」を参照。

  1. cd ~/
  2. mkdir .ssh (.ssh ディレクトリが作成されていない場合、作成済みの場合は cd ~/.ssh/)
  3. ssh-keygen -t rsa -b 4096 -C [email protected]
  4. 鍵の保存先はデフォルトのまま「.ssh/id_rsa」を指定
  5. パスフレーズは空のまま。そのまま「改行 (Return)」キーを2回押す
  6. cat ~/.ssh/id_rsa.pub で表示されるキーをコピーして、GitHub や BitBucket にコピー
  7. GitHub や Bitbucket の該当ページに公開鍵を登録
    1. GitHub の登録場所 https://github.com/[自分のID]/[GitHubレポジトリ]/settings/keys
    2. Bitbucket の登録場所 https://bitbucket.org/[自分のID]/[BitBucketレポジトリ]/admin/deploy-keys

 

Apache や Nginx の設定で .git ディレクトリを見れないように設定

.git ディレクトリが閲覧できてしまうと、過去のコードの変更、PHPファイルなどプログラムファイルの中身も分かってしまい、大変危険になります。

なので Apache や Nginx の設定で .git ディレクトリを 404 にしましょう。

checkout –mirror オプションで git ディレクトリを Web 公開領域以外に保存した方は下記の設定変更は不要です。

Apache の場合:

mod_rewrite の拡張が有効になっている Apache の .htaccess であれば下記の行を加えると、(ほとんどのサーバーで mod_rewrite は有効)

RedirectMatch 404 /\.git

Nginx の場合:

Nginx の場合は root 権限のあるユーザーが、直接 Nginx の config ファイルを編集するしかありません。

Nginx の server {} の中に下記の location ルールを挿入します。

location ~ /\.git {
    return 404;
}

 

サーバー上に git clone + git checkout

次に、Git Clone を行います。BASIC 認証や IP 制限などで非公開の領域であれば、普通に git pull しても良いかもしれません。

前述しましたが、公開する Web サーバー領域に git pull すると、 /.git/ ディレクトリの中も公開サーバーにいれられてしまうので、あまり良い方法ではありません。もしも、前述の設定ができなければ、 git clone --mirror をして、Web 公開領域に git checkout するのが良いでしょう。

git clone –mirror した場合、自動デプロイは git fetch して git checkout するという方法をとります。

公開するブランチを master とします。ただ、本来ならは、公開用は production などのネーミングで行ったほうが良いでしょう。

cd [Git レポジトリを格納する場所]
git clone --mirror [GitHub か Bitbucket 用 URL] [オプション: 作成する Git レポジトリ名]
cd [Git レポジトリ名 もしくは作成したGitレポジトリフォルダ名]
GIT_WORK_TREE=[Web公開領域のパス] git checkout -f master

 

Deploy 実行用コードの設置

GitHubのコードを、ダウンロード保存して、自分のサーバーに合わせて変数を変えてください。

https://github.com/concrete5cojp/git-Webhooks-Auto-Deploy-PHP-Script

こちらの deployment.php が本体のファイルです。(行数は 2019/8/9 時点の行数です。変わっている場合があります。)

  • 必須: 28行目の「EnterYourSecretKeyHere」は、秘密キーです。記号以外の半角の数字や英字の小文字大文字のコンビネーションで秘密キーを設定してください。
  • 必須: 37行目の directory の「/path/to/git/repo」を自分のサーバーの git レポジトリのパスに置き換えてください。
  • オプション: 38行目の work_dir の「/path/to/www」は、git 内のファイルの公開先を指定します。前述の「.git ディレクトリを見れないように設定」している場合は、directory と同じにっして大丈夫です。前述の設定ができない場合は、directory はブラウザから見えない場所に設定し、この work_dir は Web 領域を指定するようにしてください。
  • オプション: 38行目は ファイル名を入れると、指定された場所に Git 自動デプロイの動作ログを残せます。空欄だとログは作られません。
  • オプション: 39~40行目の「Branch」は、master 以外のブランチを希望すれば、必ず、サーバー上で git checkout [ブランチ名] と、希望するブランチを指定してください。
  • オプション: 42行目の syncSubmodule は、git のサブモジュールを使っている場合、サブモジュールも git pull するかの設定です。わからない方は、false のままで結構です。なお、directory と work_dir を別の領域にして分けている場合は submodule の更新がうまく出来ない場合があります。
  • 必須: 43行目は、true か false のどちらかの設定が必須です。true だと、 git reset –hard コマンドを走らせて git 内の領域を強制的にリセットします。諸刃の刃ですが、true だと安全な運用がしやすいと個人的に思うオプションです。
  • オプション: 44行目の git_bin_path は、git のプログラムをどう入力すれば実行されるかを指定します。普通であれば「git」で良いのですが、PHP 実行の際にパスが通ってないので git への絶対パスが必要とか、別の git プログラムを動かしたいと行った時に変更してください。
  • オプション: 54〜59行目は、サーバー上で自動デプロイした後に特定のコマンドを実行するためのコマンドを入力し、ログに出力するものです。サンプルでは、WordPress の Upgrade PHPスクリプトを普通に叩くシェルを実行するサンプルになっています。上級者向けですが、いろいろ試したい人は、コメントを外して試してみてください。

PHP とシェルスクリプトが分かる人は、上記のスクリプトは、シェルを実行しているだけなので、適宜コマンドを変えて作ってやってもいいかもしれません。

 

Deploy 実行URLを作成

URL は

https://example.com/deployment.php?key=パスワードキー

と「 key= 」の後にパスワードになる半角英数字のパスワードキーを入れてください。https 通信になっているので、key がバレにくくなります。

また、BASIC 認証の設定もされている場合は、

https://[Basic認証ID]:[Basic認証パス]@example.com/deployment.php?key=パスワードキー

という URL になります。

公開用のサーバーの場合でも、このデプロイ用 PHP ファイルは Basic 認証が設置してある https でアクセスする場所に設置するのをお勧めします。

https をサポートしていないサーバーの場合は、URLを「http」に戻すことを忘れずに。

GitHub や Bitbucket で URL の設定

GitHub や BitBucket で Webhook の設定を行います。

  • GitHub や Bitbucket の設定ページに行く
    • GitHub は https://github.com/[自分のID]/[GitHubレポジトリ]/settings/hooks
    • Btbucket は https://bitbucket.org/[自分のID]/[BitBucketレポジトリ]/admin/hooks
  • GitHub は Add Webhook、Bitbucket は POST を選択して Add をクリック
  • Deploy 実行URLを入力
    • GitHub では、「Payload URL」のところに。あとの項目は空白やデフォルトのママ
    • Bitbucket では、URLを項目に入れて保存

試しに Pull Request をしてサーバーに反映されているか、テストしてみましょう。

 

テストして deploy_log_filename.log を確認

正常に終わっていたら、deploy_log_filename.log というログファイルが生成されて、どのような変更があったかのログが見られるはずです。

※ 注意:ログファイルが肥大になるかもしれないので、定期的に削除するか、/var/log/gitdeploy のように logrorate がかかっている領域にログファイルを保存しても良いかもです。

 

ご意見募集

間違ってたり、ヤバかったりしたら、ご指摘や、 GitHub へのプルリクエストをお願いします。

 

それでは、自動 deploy ガンバってみてください。

宣伝:ウェブサイトを作るCMS は concrete5 で決まり!(世界では、アメリカ陸軍、スイス政府、ミニクーパー等、日本でも、市町村サイト、国公立大学で使われています。)

以上。