k-holyのPHPとか諸々メモ

Webで働くk-holyがPHP(スクリプト言語)とか諸々のことをメモしていきます。ソースコードはだいたいWindowsで動かしてます。

Fabricタスクをモジュール分割して楽々composer更新

Windows7 (MinGW / MSYS) で Fabric シリーズ記事です。

今回は(今回も?)Fabricの使い方としてはPHP無関係ですが、タスクの内容が composer コマンドなのでPHPer向けといえばPHPer向けです。

fabfile.pyをパッケージにしてタスクをモジュール分割

公式ドキュメント Fabfile construction and use — Fabric 1.6 documentation に書かれている通り、 Fabricのfabコマンド用タスクは単一のモジュール fabfile.py に定義する方法の他に、fabfile ディレクトリを作成して __init__.py を置くことでパッケージ化し、モジュール分割する方法があります。

今回は composer のインストールと、composerでインストールしたライブラリの更新を題材に、Fabricタスクをモジュール分割してみます。

~/fabfile.py

from fabric.api import env, run, local, put, cd
from fabric.contrib.files import exists

def gehirn():
    env.hosts = ['133.242.2.104']
    env.port = 22
    env.user = 'kholy'
    env.key_filename = '~/.ssh/id_rsa'
    env.password = 'passphrase-for-key'

def develop():
    env.hosts = ['192.168.1.10']
    env.port = 22
    env.user = 'develop'
    env.key_filename = '~/.ssh/develop.id_rsa'
    env.password = 'passphrase-for-key'

def composer_setup():
    if not exists('bin'):
        run('mkdir bin')
    with cd('bin'):
        run('curl -sS https://getcomposer.org/installer | php')
        run('mv composer.phar composer')

def composer_update(path=""):
    if path != "":
        cd(path)
    run('composer self-update')
    run('composer update')

gehirn と develop は接続先を指定するためのタスクです。

composer_setup で composer.phar をインストールして PATHが通されている .bin/composer に移動し、composer_update:path で指定された composer.json の設置先で composer update するという内容です。

この例ではまだ数は少ないですが、このような他のタスクの実行結果を前提としたタスクが増えていくと、タスク間の依存性を把握するのが大変になるので、モジュール分割した方が良いと思います。

fabfile ディレクトリを作成して、fabfile.py をそのまま fabfile/__init__.py に移動します。

fab --list でタスク一覧を表示すると、こうなります。

(dev)[k_horii@horii ~]$ fab --list
Available commands:

    composer_setup
    composer_update
    develop
    gehirn

fabfile.py の時と同じです。

このままでは何も変わっていないので、composer用のタスクを別のモジュール composer.py に分割します。

~/fabfile/composer.py

from fabric.api import run, cd
from fabric.contrib.files import exists

def setup():
    if not exists('bin'):
        run('mkdir bin')
    with cd('bin'):
        run('curl -sS https://getcomposer.org/installer | php')
        run('mv composer.phar composer')

def update(path=""):
    if path != "":
        cd(path)
    run('composer self-update')
    run('composer update')

分割したタスクを __init__.py から削除します。

~/fabfile/__init__.py

from fabric.api import env, run, local, put, cd
from fabric.contrib.files import exists

def gehirn():
    env.hosts = ['133.242.2.104']
    env.port = 22
    env.user = 'kholy'
    env.key_filename = '~/.ssh/id_rsa'
    env.password = 'passphrase-for-key'

def develop():
    env.hosts = ['192.168.1.10']
    env.port = 22
    env.user = 'develop'
    env.key_filename = '~/.ssh/develop.id_rsa'
    env.password = 'passphrase-for-key'

fab --list でタスクの一覧を表示すると、こうなります。

(dev)[k_horii@horii ~]$ fab --list
Available commands:

    develop
    gehirn

モジュール分割したタスクを認識させるためには import 定義を追加して、fabric.decorators.task デコレータを利用します。

taskデコレータ(@task)は __init__.pycomposer.py の双方に定義します。

ついでに、確認用として which:command も使えるようにしました。

~/fabfile/__init__.py

from fabric.api import env, run, local, put, cd
from fabric.contrib.files import exists
from fabric.decorators import task
import composer

@task
def gehirn():
    env.hosts = ['133.242.2.104']
    env.port = 22
    env.user = 'kholy'
    env.key_filename = '~/.ssh/id_rsa'
    env.password = 'passphrase-for-key'

@task
def develop():
    env.hosts = ['192.168.1.10']
    env.port = 22
    env.user = 'develop'
    env.key_filename = '~/.ssh/develop.id_rsa'
    env.password = 'passphrase-for-key'

@task
def which(command):
    run('which %s' % (command))

~/fabfile/composer.py

from fabric.api import run, cd
from fabric.contrib.files import exists
from fabric.decorators import task

@task
def setup():
    if not exists('bin'):
        run('mkdir bin')
    with cd('bin'):
        run('curl -sS https://getcomposer.org/installer | php')
        run('mv composer.phar composer')

@task
def update(path=""):
    if path != "":
        cd(path)
    run('composer self-update')
    run('composer update')

fab --list で関数のリストを表示すると、こうなりました。

(dev)[k_horii@horii ~]$ fab --list
Available commands:

    develop
    gehirn
    composer.setup
    composer.update

モジュール分割することで、こんなコマンドで Gehirnサーバにcomposerをインストールできるようになりました。

※catコマンドにパイプしているのは、Windowsでエスケープシーケンスを有効にするためです。参考 Windowsでphpunit --colors - iakioの日記

(dev)[k_horii@horii ~]$ fab gehirn composer.setup|cat
[133.242.2.104] Executing task 'composer.setup'
[133.242.2.104] run: mkdir bin
[133.242.2.104] run: curl -sS https://getcomposer.org/installer | php
[133.242.2.104] out: #!/usr/bin/env php
[133.242.2.104] out: Some settings on your machine may cause stability issues with Composer.
[133.242.2.104] out: If you encounter issues, try to change the following:
[133.242.2.104] out:
[133.242.2.104] out: Your PHP (5.3.3-7+squeeze15) is quite old, upgrading to PHP 5.3.4 or higher is recommended.
[133.242.2.104] out: Composer works with 5.3.2+ for most people, but there might be edge case issues.
[133.242.2.104] out:
[133.242.2.104] out: Downloading...
[133.242.2.104] out:
[133.242.2.104] out: Composer successfully installed to: /home/kholy/bin/composer.phar
[133.242.2.104] out: Use it: php composer.phar
[133.242.2.104] out:

[133.242.2.104] run: mv composer.phar composer

Done.
Disconnecting from 133.242.2.104... done.

whichで確認してみます。

(dev)[k_horii@horii ~]$ fab gehirn which:composer
[133.242.2.104] Executing task 'which'
[133.242.2.104] run: which composer
[133.242.2.104] out: /home/kholy/bin/composer
[133.242.2.104] out:

確かに、先ほど ~/bin にインストールした composer コマンドが利用されています。

composer updateしてみます。

(dev)[k_horii@horii ~]$ fab gehirn composer.update|cat
[133.242.2.104] Executing task 'composer.update'
[133.242.2.104] run: composer self-update
[133.242.2.104] out: You are using the latest composer version.
[133.242.2.104] out:

[133.242.2.104] run: composer update
[133.242.2.104] out: Loading composer repositories with package information
[133.242.2.104] out: Updating dependencies (including require-dev)
[133.242.2.104] out:   - Updating volcanus/routing dev-master (4893f2d => 01a256a)
[133.242.2.104] out:     Checking out 01a256aa3e5068c4f074ec118eef4a07c6c76f10
[133.242.2.104] out:
[133.242.2.104] out:   - Updating pinoco/pinoco dev-master (0.7.1 => 0.7.2)
[133.242.2.104] out:     Checking out 0.7.2
[133.242.2.104] out:
[133.242.2.104] out:   - Updating swiftmailer/swiftmailer dev-master (28873a8 => e77eb35)
[133.242.2.104] out:     Checking out e77eb358a1aa7157afb922f33e2afc22f6a7bef2
[133.242.2.104] out:
[133.242.2.104] out:   - Updating symfony/http-foundation 2.2.x-dev (v2.2.1 => 17ba72b)
[133.242.2.104] out:     Checking out 17ba72b450676370cfb406f7675da3f7bb742cfb
[133.242.2.104] out:
[133.242.2.104] out:   - Updating symfony/http-kernel 2.2.x-dev (a1e8288 => e2e0ba4)
[133.242.2.104] out:     Checking out e2e0ba4d7943ee414c497629f402432533df5780
[133.242.2.104] out:
[133.242.2.104] out:   - Updating symfony/finder dev-master (e2f07c7 => 04b4a4a)
[133.242.2.104] out:     Checking out 04b4a4a823cb6f269efc91a2c6659173a7c9f864
[133.242.2.104] out:
[133.242.2.104] out:   - Updating silex/silex dev-master (80f0abd => 1cd7f3f)
[133.242.2.104] out:     Checking out 1cd7f3f050b78dae4458d93892355720f56659f9
[133.242.2.104] out:
[133.242.2.104] out: Writing lock file
[133.242.2.104] out: Generating autoload files
[133.242.2.104] out:


Done.
Disconnecting from 133.242.2.104... done.

併せてプロジェクト別ディレクトリへの composer.json のアップロードを自動化すれば、更に便利になりそうです。

バージョン管理システムで同期させるのが理想なのでしょうけど、少しずつでも日々の作業を自動化していけば、いずれは憧れの本番環境デプロイ自動化に到達できるかなと楽観視しています…。

以下の記事を参考にしました。