January 29, 2013

FuelPHPでMySQLドキュメントを生成するパッケージを作ってみました。

2013/01/10 追記
高機能版作りました。

FuelPHPでMySQL/PostgreSQL/SQLiteのドキュメントジェネレータを作ってみました。
http://madroom-project.blogspot.jp/2013/02/fuelphpmysqlpostgresqlsqlite.html

--

ソースは、以下になります。
https://github.com/mp-php/fuel-packages-mydoc

Linuxサーバ上でMySQLドキュメントを作りたく、ジェネレータを探したんですが見つからず、FuelPHPのパッケージとして作ってみました。(実はまだLinuxサーバ上で実行していませんが。。。)

Twitter Bootstrapを使っています。

とりあえず、以下を出力するようにしてみました。
* テーブル一覧とテーブル詳細
* インデックス一覧とインデックス詳細
* トリガー一覧とトリガー詳細

以下、使い方です。(READMEはいつもの通り、後日。。。)

(1)
fuel/packagesに"mydoc"というディレクトリ名で配置します。

(2)
config.phpのalways_load.packagesに"mydoc"を追加します。

(3)
db.phpの設定をします。尚、PDOドライバは使用出来ません。

(4)
実行します。
php oil r mydoc:html <スキーマ名>
<スキーマ名>はdb.phpの"default"とかとは異なります。例えばmysqliなら、connection.databaseの値です。ローカルやCIサーバ上で実行することを想定しているので、スキーマ名指定にしました。

ドキュメントはapp/tmp/mydocに出力されます。第二引数にディレクトリ名を与えると、そのディレクトリの下にmydocディレクトリが出力されます。既にmydocディレクトリが存在する場合は"-f(--force)"オプションを付けて下さい。削除した後、再度、生成します。

(5)
設定で
* webfontの指定ができます。
* 除外するテーブルの指定ができます。
* 除外するテーブル名の正規表現が指定出来ます。


一気に作ったのでソースが散らかっている感がありますが、少しずつ整えようと思います。。。

明日、試しにJenkinsからキックしてみます。

January 27, 2013

FuelPHPのマイグレーションをTravis CIで実行する

先に、.travis.ymlのサンプルです。
language: php

php:
  - 5.3
  - 5.4

before_script:
  - mysql -e 'create database fuel_test;'

script:
  - FUEL_ENV=test php oil r migrate
  - phpunit --coverage-text -c fuel/app/phpunit.xml
ポイントは、以下の二つと思います。
* "before_script"でデータベースをcreateする
* "script"でユニットテストを実行する前に"FUEL_ENV=test"でマイグレーションを実行する

これで、DBが関係するユニットテストも実行出来るようになります。

尚、TravisのMySQLは
* host : localhost
* username : root
* password : 空
で接続出来ました。

ついでに、.travis.ymlをGitHubに追加しておきました。
https://github.com/mp-php/fuel-myapp/blob/master/.travis.yml

--

参考:
http://about.travis-ci.org/docs/user/database-setup/

FuelPHPのユニットテストをTravis CIで実行してみる

無料で使えるCIサービスのTravis CIでFuelPHPのユニットテストを実行してみました。
https://travis-ci.org/

以下、手順をメモしておきます。


GitHubで https://github.com/fuel/fuel をforkしておきます。

TravisにGitHubアカウントでログインします。

https://travis-ci.org/profile の"Repositories"タブから"Sync now"します。
尚、"Profile"タブから日本語表示も選べます。

forkしたレポジトリを"ON"にします。

テスト用のブランチを作成してpushしてみます。
$ git checkout -b travis-test
$ git push origin travis-test
Total 0 (delta 0), reused 0 (delta 0)
To https://mp-php@github.com/mp-php/fuel.git
 * [new branch]      travis-test -> travis-test
まだ、Travis側では何も起こりません。

Travisのドキュメント http://about.travis-ci.org/docs/ を参考にして、「.travis.yml」をルート直下に作成してpushしてみます。
$ vim .travis.yml
-- .travis.yml --
language: php

php:
  - 5.3
  - 5.4

script: phpunit -c fuel/core/phpunit.xml
$ git add .travis.yml
$ git commit -m "Added .travis.yml"
[travis-test 8b45691] Added .travis.yml
 1 file changed, 8 insertions(+)
 create mode 100644 .travis.yml
$ git push
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 332 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://mp-php@github.com/mp-php/fuel.git
   982c3ed..8b45691  travis-test -> travis-test 
Travis側で、PHP5.3とPHP5.4で、それぞれユニットテストが実行されたようです。

以下、PHP5.3でのログの一部です。
$ phpunit -c fuel/core/phpunit.xml
PHPUnit 3.7.10 by Sebastian Bergmann.

Configuration read from /home/travis/build/mp-php/fuel/fuel/core/phpunit.xml

...............................................................  63 / 330 ( 19%)
............................................................... 126 / 330 ( 38%)
............................................................... 189 / 330 ( 57%)
............................................................... 252 / 330 ( 76%)
............................................................... 315 / 330 ( 95%)
...............

Time: 6 seconds, Memory: 17.50Mb

OK (330 tests, 350 assertions)

Done. Build script exited with 0
ビックリするくらい簡単でした。

尚、.travis.ymlの"script"を以下のようにすれば、ログにカバレッジが出力されました。
script: phpunit --coverage-text -c fuel/app/phpunit.xml 
TravisのドキュメントにはDB関係の記載も有るので、細かな使い方を確認していこうと思います。

ちなみに https://github.com/fuelphp/fuelphp (FuelPHP 2)にも、.travis.ymlが有りました。

January 25, 2013

PHP製のGitビュアー、"GitList 0.3"をちょっと直して使ってみた

先日、GitLab 4.1にパブリックモードが搭載されましたが、まだcloneだけでブラウザからの閲覧は出来ないようです。RhodeCodeとかだと出来るのかもしれませんが、とりあえず、認証なしで閲覧可能なビュアーを探してみました。

そこで見つけたのがGitListです。

PHP製なので、インストール/アンインストールも楽そうだし、試してみました。DBも不要です。Silexというフレームワークで実装されているそうです。

以下の"Requirements"を満たした環境で、Composerを使ったインストール手順を書いておきます。
(やっていることは、"Installing"と"Building"とほとんど同じです。)

適切な場所でgit cloneします。
$ git clone https://github.com/klaussilveira/gitlist.git .
cacheディレクトリを777に変更します。(もしかしたら不要かも。とりあえず記載の通りに。。。)
$ chmod 777 cache
composer.pharをインストールして実行します。
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install
config.ini-exampleをconfig.iniとしてコピーして編集します。
$ cp config.ini-example config.ini
$ vim config.ini
* "client"は、gitコマンドのパスです。
* "repositories"は、レポジトリを保存しているディレクトリです。
* hidden[]は、非表示にしたいレポジトリです。以下の形式で、複数指定が出来ました。
hidden[] = '/xxx/yyy'
hidden[] = '/zzz/aaa'
* その他の設定は未確認です。

index.phpが有る場所にブラウザからアクセスして、レポジトリ一覧が表示されればインストールはOKです。ただ、適当なレポジトリを選択してディレクトリを二つ進めると、以下のエラーが出ました。
Oops! fatal: Not a valid object name ...

で、forkして応急処置したのが
https://github.com/mp-php/gitlist/commit/49c7bb2ab09d24fb9cdc7c1674e871bcb04cfe64
になります。ブランチは"develop"です。
(やっつけなので、PR送れる内容では有りませんが。。。)

GitListは、まだv0.3なので、細かなバグは残っていそうですが、とりあえずこれで使えそうです。把握しているその他の問題として、どのディレクトリにいても、必ずトップ階層のREADMEが表示されてしまいます。(クリティカルでは無いので放置しています。。。)

ファイル内の文字列検索も出来ますし、ビュアーとしては良い方向性な印象です。

尚、最初、gitレポジトリのパーミッションで弾かれて、閲覧出来ませんでした。ビュアーの都合で大元のレポジトリのパーミッションを緩めるのはアレなので、定時にて適当な場所に複製、パーミッションを緩めて、そちらを閲覧するようにしました。なので、最新性は無くなりますが、まあ、とりあえず良いかなということで、使っていってみようと思います。

January 22, 2013

GitLab4.1でfilesとcommitsが404になった

2013/01/23 追記

以下のPRの内容の方が、僕のやっつけより的確です。
https://github.com/gitlabhq/gitlabhq/pull/2706/files

--

現象は、以下の通りです。
404 when viewing Files and Commits tab
https://github.com/gitlabhq/gitlabhq/issues/2602

報告者はNginxで、僕はApacheなので、その辺は関係無さそうです。
ttp://example.com/gitlabの形式で運用している場合に発生する(ことがある)のかなと。

GitLabのソースはあまり知らないですし、そもそもRubyをよく知らないので、grepしまくって応急処置しました。この方法(この箇所の修正)が正しいかどうかはわからないですが、一応、diff書いておきます。(ハードコーディングでみっともないですが。。。)
$ git diff
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 270a0aa..e6682b2 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -51,7 +51,7 @@ module ExtractsPath
     return pair unless @project
 
     # Remove project, actions and all other staff from path
-    input.gsub!(/^\/#{Regexp.escape(@project.path_with_namespace)}/, "")
+    input.gsub!(/^\/gitlab\/#{Regexp.escape(@project.path_with_namespace)}/, ""
     input.gsub!(/^\/(tree|commits|blame|blob|refs)\//, "") # remove actions
     input.gsub!(/\?.*$/, "") # remove stamps suffix
     input.gsub!(/.atom$/, "") # remove rss feed

January 21, 2013

FuelPHP1.5のfromdbタスクで、既存テーブルからscaffoldとmodelを作ってみる

FuelPHP1.5で、既存テーブルからscaffoldやmodelを生成するfromdbタスクが実装されました。

実は、以下のタスクがベースになっています。(ソースにチラッと書いてあります。)
「FuelPHP - 既存DBからのScaffold」
http://www.slideshare.net/mamoruotsuka/fuelphp-tokyo-vol220120923

経緯は最後に書くとして、使い方をざっと見ておきます。

(1)
サンプルのテーブルを作成します。
-- -----------------------------------------------------
-- Table `parents`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `parents` ;

CREATE  TABLE IF NOT EXISTS `parents` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(255) NOT NULL ,
  `age` INT NOT NULL ,
  `created_at` INT NOT NULL ,
  `updated_at` INT NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `children`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `children` ;

CREATE  TABLE IF NOT EXISTS `children` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `parent_id` INT NOT NULL ,
  `name` VARCHAR(255) NOT NULL ,
  `age` INT NOT NULL ,
  `created_at` INT NOT NULL ,
  `updated_at` INT NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;
(2)
FuelPHPのDB設定(db.php)を済ませます。

(3)
単一のテーブルを指定してscaffoldを生成してみます。
$ php oil r fromdb:scaffold parents
以下、都合上"-f(--force)"オプションをつけていませんが、作成済みのファイルを上書きする場合に必要です。
詳しくは
$ php oil r fromdb:help
をご覧ください。

(4)
複数のテーブルを指定してscaffoldを生成してみます。カンマ区切りで指定します。
$ php oil r fromdb:scaffold parents,children
(5)
全テーブルに対してscaffoldを生成してみます。"--all"オプションを付けます。
DBドライバでPDOは使用出来ません。PDOドライバはテーブル一覧の取得に非対応です。
$ php oil r fromdb:scaffold --all
(6)
指定DBに対してscaffoldを生成してみます。DBは"--db=xxx"形式で指定します。
$ php oil r fromdb:scaffold --all --db=default
以下、"--all"や"--db"オプション含め、テーブルの指定方法は同様です。尚、前述の"-f(--force)"と"--all"を組み合わせると編集途中のファイルも問答無用で上書きされるので注意して下さい。

(7)
admin用のscaffoldを生成してみます。
$ php oil r fromdb:scaffold parents --admin
(8)
model(ORM)を生成してみます。
$ php oil r fromdb:model parents
(9)
model(Crud)を生成してみます。
$ php oil r fromdb:model parents --crud



以下、簡単な経緯です。

fromdbの元になったタスクは、結構前に自分用に作成してGitHubに保存して有りました。
http://madroom-project.blogspot.jp/2012/06/fuelphpscaffoldtaskgithub.html

本家にも要望があったようで、kenjiさんが紹介してくれました。
https://github.com/fuel/oil/issues/103

その後、kenjiさんにテーブルプレフィックスやCrudに関する検証にご協力いただき、再度、僕の方から本家にコメントしました。

以後、暫く音沙汰がなかったのですが、本家から"コミットで返信"がありました。
https://github.com/fuel/oil/commit/fcb51348c7d4c401895d4e10119fd795fdc57a94

とても有難い結果になりました :)

January 20, 2013

FuelPHP1.5(develop)で気になっている点のメモ

いろいろと機能が強化されるっぽいので、1.5/developで気になっている点をメモしておきます。

▼ORMで、マスター/スレーブをサポートするようです。
https://github.com/fuel/orm/commit/57e10250b0f6d08d4f60a192e7d27c468eea14d0

▼ORMで、論理削除がサポートされるようです。
「FuelPHPのModel_Softで論理削除をやってみた」
http://d.hatena.ne.jp/kaitoh07/20130115/1358219271

▼oilで、実在テーブルからのscaffold/model生成タスクが実装されるようです。
「FuelPHP 1.5で既存DBからのスキャフォールドが実装されるようです。」
http://madroom-project.blogspot.jp/2013/01/fuelphp-15db.html

▼Logクラスがパッケージになるようです。これまでのLogクラスは削除されています。
https://github.com/fuel/log
https://github.com/fuel/core/commit/31478fb5afb5b1c01c2ea12f1252caaacdc1df4d
* 今現在、Logパッケージを有効にしないと"Fatal error: Class 'Log' not found"が出ます。

▼あと、1.4から実装されたORMのEAVが見れていないなー。
http://fuelphp.com/docs/packages/orm/eav.html

--

その他:
「FuelPHP1.5とユニットテスト時のFuel::$envについて」
http://madroom-project.blogspot.jp/2013/01/fuelphp15fuelenv.html

January 19, 2013

FuelPHPでテストケースの雛形を作成するTaskをGitHubに置いておきました。

以下になります。
https://github.com/mp-php/fuel-myapp/blob/master/tasks/testcase.php

php oil r testcase:generateでapp/classesに対するテストケースの雛形をまとめて作成します。
既に作成されているテストケースはスキップします。
今のところ、引数は有りません。
ネーミングはMakeGoodの意識もしていますが、簡単に変えられるようにしてあります。

試しに、DLした直後のFuelPHP(1.5/develop)に対して実行してみます。
$ php oil r testcase:generate
"/xxx/fuel/app/tests/controller/welcome_Test.php" was generated.
"/xxx/fuel/app/tests/view/welcome/404_Test.php" was generated.
"/xxx/fuel/app/tests/view/welcome/hello_Test.php" was generated.
app/tests/controller/welcome_Test.phpを削除して、再度実行してみます。
$ php oil r testcase:generate
"/xxx/fuel/app/tests/controller/welcome_Test.php" was generated.
"/xxx/fuel/app/tests/view/welcome/404_Test.php" already exists, skipped generation.
"/xxx/fuel/app/tests/view/welcome/hello_Test.php" already exists, skipped generation.

作成されたソースを見てみます。

* app/tests/controller/welcome_Test.php
<?php

/**
 * Controller_Welcome class tests
 *
 * @group App
 */
class Test_Controller_Welcome extends TestCase
{

    /**
     * Tests Controller_Welcome::test_action_index()
     *
     * @test
     */
    public function test_action_index()
    {
        //TODO: test_action_index() has not been implemented yet.
        $this->markTestIncomplete(
            'test_action_index() has not been implemented yet.'
        );
    }

    /**
     * Tests Controller_Welcome::test_action_hello()
     *
     * @test
     */
    public function test_action_hello()
    {
        //TODO: test_action_hello() has not been implemented yet.
        $this->markTestIncomplete(
            'test_action_hello() has not been implemented yet.'
        );
    }

    /**
     * Tests Controller_Welcome::test_action_404()
     *
     * @test
     */
    public function test_action_404()
    {
        //TODO: test_action_404() has not been implemented yet.
        $this->markTestIncomplete(
            'test_action_404() has not been implemented yet.'
        );
    }

}
* app/tests/view/welcome/404_Test.php
<?php

/**
 * View_Welcome_404 class tests
 *
 * @group App
 */
class Test_View_Welcome_404 extends TestCase
{

    /**
     * Tests View_Welcome_404::test_view()
     *
     * @test
     */
    public function test_view()
    {
        //TODO: test_view() has not been implemented yet.
        $this->markTestIncomplete(
            'test_view() has not been implemented yet.'
        );
    }

}
* app/tests/view/welcome/hello_Test.php
<?php

/**
 * View_Welcome_Hello class tests
 *
 * @group App
 */
class Test_View_Welcome_Hello extends TestCase
{

    /**
     * Tests View_Welcome_Hello::test_view()
     *
     * @test
     */
    public function test_view()
    {
        //TODO: test_view() has not been implemented yet.
        $this->markTestIncomplete(
            'test_view() has not been implemented yet.'
        );
    }

}

FuelPHP1.5とユニットテスト時のFuel::$envについて

FuelPHPでユニットテストを実行すると、Fuel::$envは"test"になります。但し、v1.4まで、config.phpのみ、config/developmentディレクトリがロードされていました。
https://github.com/fuel/core/issues/1287

上記を解決する為、core/phpunit.xmlに以下の修正が行われました。
https://github.com/fuel/core/commit/5af5b18ee2cfbc35bf91e02a9c8c6c2e6d85c520

伴い、core/bootstrap_phpunit.phpで不要となった、Fuel::$envへの"test"の代入が削除されます。
https://github.com/fuel/core/commit/eaa00a098406d0aa29583718449a8c5a0de342c9


上記の修正から、v1.5に移行する際、以下の確認が必要なります。

(1)
core/phpunit.xmlをapp/phpunit.xmlにコピーして使用している場合、app側もcore側と同様の修正を行う必要があります。

(2)
EclipseやNetBeans等から、phpunit.xmlを介さずにbootstrapファイルを指定してユニットテストを実行している場合、bootstrapで$_SERVER['FUEL_ENV']に"test"をセットする必要があります。
https://github.com/mp-php/fuel-myapp/blob/master/bootstrap_makegood.php#L17

JenkinsにMantis Pluginをインストールしてみた

以下、行った設定のメモです。

(1)
システム設定のMantis設定
* URL
* Mantisのバージョン
* 使用するアカウントとパスワード
を入力します。
使用するアカウントは、管理者権限でJenkins専用のアカウントを作成すると楽です。

(2)
ジョブの設定で
* Mantisサイトを選択
* チケットIDパターンを入力 (URLベタ張りの場合の例: 「/view.php?id=%ID%」)
プロジェクトとカテゴリは、チケットの更新であれば必要ないです。
ビルド失敗時のチケット発行時に使用されるかと。
尚、プロジェクトのリストが出なければ、認証に失敗しています。

(3)
Post-build ActionsにUpdated relevant Mantis issuesを追加
* Keep note private: コメントを非公開にする
* Record changelog to note: 変更履歴をコメントに登録する


コミットメッセージがチケットIDパターンにヒットすると、該当チケットにコメントを登録してくれます。
(コミットメッセージに改行が含まれている場合、2行目以降は無視される??)

また、ビルド失敗時に新規チケットの発行も出来るようです。(こっちは未確認。)

非常に便利です。感謝。

January 14, 2013

FuelPHPのタスクとオプションの値を確認してみる

まず、テストタスクを作成します。実はoilでも生成出来ます。(確かv1.4から。)
$ php oil g task xxx yyy
        Preparing task method [Yyy]
    Creating tasks: /hoge/fuel/app/tasks/xxx.php
app/tasks/xxx.phpが生成され、デフォルトのfunction runと、コマンドで指定したfunction yyyが用意出来ました。
参考: http://www.fuelphp.com/docs/packages/oil/generate.html#tasks

"arg1"〜"arg5"をDebug::dumpするように書き足します。
public static function yyy($args = NULL)
{
     echo "\n===========================================";
     echo "\nRunning task [Xxx:Yyy]";
     echo "\n-------------------------------------------\n\n";

     /***************************
      Put in TASK DETAILS HERE
      **************************/
     \Debug::dump(\Cli::option('arg1'));
     \Debug::dump(\Cli::option('arg2'));
     \Debug::dump(\Cli::option('arg3', false));
     \Debug::dump(\Cli::option('arg4', 'default'));
     \Debug::dump(\Cli::option('arg5', false));
}
実行してみます。
$ php oil r xxx:yyy --arg1 --arg5=zzz

===========================================
Running task [Xxx:Yyy]
-------------------------------------------

bool(true)
NULL
bool(false)
string(7) "default"
string(3) "zzz"
* オプション名を入力するだけだとtrue (arg1)
* オプション名を入力せずCli::optionの第二引数に何も指定しないとnull (arg2)
* オプション名を入力せずCli::optionの第二引数に何か指定するとその値 (arg3/arg4)
* オプション名を値とセットで入力するとその値(arg5)
という結果になりました。
参考: http://www.fuelphp.com/docs/classes/cli.html#/method_option

January 13, 2013

FuelPHP 1.5で既存DBからのスキャフォールドが実装されるようです。

GitHubの該当Issueがcloseされ、正式に実装されるとのことです。
https://github.com/fuel/oil/issues/103

どんな感じのソースかなーと思って何の気なしに見てみると。。。
https://github.com/fuel/oil/blob/1.5/develop/tasks/fromdb.php

感激です!!


P.S.
1.5がリリースされ次第、ちゃんとした記事(使い方がメインになると思いますが)を書きたいと思います :)

--

関連:
FuelPHP - 既存DBからのScaffold
http://www.slideshare.net/mamoruotsuka/fuelphp-tokyo-vol220120923

FuelPHPで既存テーブルからScaffoldするTaskをgithubに。
http://madroom-project.blogspot.jp/2012/06/fuelphpscaffoldtaskgithub.html

FuelPHPのscafdbタスクを改良しました。
http://madroom-project.blogspot.jp/2012/11/fuelphpscafdb.html

MySQL Workbenchでalter tableを自動生成する

MySQL Workbenchでalter tableの自動生成が出来たので、手順をメモしておきます。

MySQL Workbenchは以下からDL出来ます。(要アカウント。)
http://dev.mysql.com/downloads/workbench/
ログイン(サインアップ)画面の"No thanks, just start my download."からアカウント無しでDL可能です。(Twitterでご教示頂きました。有難うございます。)


(1)
MySQL Workbenchで以下のような設計をして、DBを作成します。
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

CREATE SCHEMA IF NOT EXISTS `mwb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mwb` ;

-- -----------------------------------------------------
-- Table `mwb`.`users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mwb`.`users` (
  `id` INT NOT NULL ,
  `name` VARCHAR(255) NOT NULL ,
  `age` INT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;



SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
(2)
MySQL Workbenchで以下のような設計に修正します。修正内容は適当です。尚、MySQL Workbench上で修正しただけで、実際に実行はしません。
* users.nameをnull可に
* users.nameにインデックス"idx"を追加
* users.school_idを追加(外部キー)
* users.ageをusers.school_idの下に
* users.ageをnull不可に
* schoolsテーブル追加
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';


-- -----------------------------------------------------
-- Table `mwb`.`schools`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mwb`.`schools` (
  `id` INT NOT NULL ,
  `name` VARCHAR(255) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `mwb`.`users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `mwb`.`users` (
  `id` INT NOT NULL ,
  `school_id` INT NOT NULL ,
  `age` INT NOT NULL ,
  `name` VARCHAR(255) NULL ,
  PRIMARY KEY (`id`) ,
  INDEX `fk_users_schools_idx` (`school_id` ASC) ,
  INDEX `idx` (`name` ASC) ,
  CONSTRAINT `fk_users_schools`
    FOREIGN KEY (`school_id` )
    REFERENCES `mwb`.`schools` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;



SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
(3)
現在、DBは(1)の状態です。つまり、(2)にするalter tableが欲しい状態です。
MySQL Workbenchで Database > Synchronize Model...と進んで、接続情報を入力して、Continueをクリックします。その後の画面を指示通りに進めると、以下のSQLが出力されました。Executeを押すと実際に実行されるので注意して下さい。
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

ALTER TABLE `mwb`.`users` CHANGE COLUMN `age` `age` INT(11) NOT NULL  AFTER `school_id` , CHANGE COLUMN `name` `name` VARCHAR(255) NULL DEFAULT NULL  , ADD COLUMN `school_id` INT(11) NOT NULL  AFTER `id` , 
  ADD CONSTRAINT `fk_users_schools`
  FOREIGN KEY (`school_id` )
  REFERENCES `mwb`.`schools` (`id` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
, ADD INDEX `fk_users_schools_idx` (`school_id` ASC) 
, ADD INDEX `idx` (`name` ASC) ;

CREATE  TABLE IF NOT EXISTS `mwb`.`schools` (
  `id` INT(11) NOT NULL ,
  `name` VARCHAR(255) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_swedish_ci;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
alter tableが正しく出力されない場合は、MySQL WorkbenchのSchema Nameと実際のDB名が一致していない可能性があります。

P.S.
ER MasterはDBインポートからのドキュメント自動生成専用で使うことにする。。。

duplicityでバックアップを取ってみる

参考:
duplicityを使って暗号化バックアップ
http://ambiesoft.ddo.jp/blog/archives/1766

以下、コマンドのメモです。とりあえず、ローカルの適当な場所にfrom、to、restoreという3つのディレクトリを作成します。fromをtoにバックアップして、toからrestoreにリストアしてみます。

# インストール
$ sudo apt-get install -y duplicity

# 準備
$ cd ~/tmp/
$ mkdir from
$ mkdir to
$ mkdir restore
$ touch from/test.txt

# fromをtoにバックアップ
$ duplicity from/ file:///home/xxx/tmp/to/
Import of duplicity.backends.sshbackend Failed: No module named paramiko
Import of duplicity.backends.giobackend Failed: No module named gio
Synchronizing remote metadata to local cache...
Deleting local /home/xxx/.cache/duplicity/cf916ece6cdee728e6def39a70bc3db8/duplicity-full-signatures.20130112T171351Z.sigtar.gz (not authoritative at backend).
Deleting local /home/xxx/.cache/duplicity/cf916ece6cdee728e6def39a70bc3db8/duplicity-full.20130112T171351Z.manifest (not authoritative at backend).
Last full backup date: none
GnuPG passphrase: 
Retype passphrase to confirm: 
No signatures found, switching to full backup.
--------------[ Backup Statistics ]--------------
StartTime 1358011229.58 (Sun Jan 13 02:20:29 2013)
EndTime 1358011229.59 (Sun Jan 13 02:20:29 2013)
ElapsedTime 0.00 (0.00 seconds)
SourceFiles 2
SourceFileSize 4096 (4.00 KB)
NewFiles 2
NewFileSize 4096 (4.00 KB)
DeletedFiles 0
ChangedFiles 0
ChangedFileSize 0 (0 bytes)
ChangedDeltaSize 0 (0 bytes)
DeltaEntries 2
RawDeltaSize 0 (0 bytes)
TotalDestinationSizeChange 215 (215 bytes)
Errors 0
-------------------------------------------------

$ ls -la to/
total 20
drwxrwxr-x 2 xxx xxx 4096 Jan 13 02:20 .
drwxrwxr-x 5 xxx xxx 4096 Jan 13 02:13 ..
-rw------- 1 xxx xxx  234 Jan 13 02:20 duplicity-full-signatures.20130112T172025Z.sigtar.gpg
-rw------- 1 xxx xxx  189 Jan 13 02:20 duplicity-full.20130112T172025Z.manifest.gpg
-rw------- 1 xxx xxx  215 Jan 13 02:20 duplicity-full.20130112T172025Z.vol1.difftar.gpg

# toをrestoreにリストア
$ duplicity restore file:///home/xxx/tmp/to/ restore/
Import of duplicity.backends.sshbackend Failed: No module named paramiko
Import of duplicity.backends.giobackend Failed: No module named gio
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: Sun Jan 13 02:20:25 2013
GnuPG passphrase: 
$ ls -la restore/
total 8
drwxrwxr-x 2 xxx xxx 4096 Jan 13 02:13 .
drwxrwxr-x 5 xxx xxx 4096 Jan 13 02:13 ..
-rw-rw-r-- 1 xxx xxx    0 Jan 13 02:13 test.txt
上手くいっているような失敗しているような。。。様子を見ながら使っていこう。。。

PHP_CodeSnifferにFuelPHP/CodeIgniter/CakePHPのルールをインストールする

それぞれのルールをDLして、必要なディレクトリを所定の場所に移動させる方法でやってみます。尚、フレームワーク名の並び順に悪意は有りません。

それぞれのルールは以下からDL出来ます。

FuelPHP
https://github.com/eviweb/fuelphp-phpcs

CodeIgniter
https://github.com/thomas-ernest/CodeIgniter-for-PHP_CodeSniffer

CakePHP
https://github.com/cakephp/cakephp-codesniffer

以下、手順です。(DLで発生するmaster.zipは都度、削除して下さい。)


最初の状態
$ phpcs -i
The installed coding standards are PEAR, Zend, PSR2, MySource, PHPCS, PSR1 and Squiz
FuelPHPのルールをインストール
$ cd ~/tmp/
$ wget https://github.com/eviweb/fuelphp-phpcs/archive/master.zip
$ unzip master.zip
$ cd fuelphp-phpcs-master/Standards/
$ sudo mv FuelPHP/ /usr/local/php/latest/lib/php/PHP/CodeSniffer/Standards/
$ phpcs -i
The installed coding standards are PEAR, FuelPHP, Zend, PSR2, MySource, PHPCS, PSR1 and Squiz
CodeIgniterのルールをインストール
$ cd ~/tmp/
$ wget https://github.com/thomas-ernest/CodeIgniter-for-PHP_CodeSniffer/archive/master.zip
$ unzip master.zip
$ cd CodeIgniter-for-PHP_CodeSniffer-master/
$ mv src/ CodeIgniter
$ sudo mv CodeIgniter/ /usr/local/php/latest/lib/php/PHP/CodeSniffer/Standards/
$ phpcs -i
The installed coding standards are PEAR, FuelPHP, Zend, PSR2, CodeIgniter, MySource, PHPCS, PSR1 and Squiz
CakePHPのルールをインストール
$ cd ~/tmp/
$ wget https://github.com/cakephp/cakephp-codesniffer/archive/master.zip
$ unzip master.zip
$ mv cakephp-codesniffer-master/ CakePHP
$ sudo mv CakePHP/ /usr/local/php/latest/lib/php/PHP/CodeSniffer/Standards/
$ phpcs -i
The installed coding standards are PEAR, FuelPHP, Zend, PSR2, CodeIgniter, MySource, PHPCS, CakePHP, PSR1 and Squiz

January 12, 2013

CapistranoのオレオレGitデプロイをJenkins(ブラウザ)上から実行してみた

前回書いたCapistrano用のスクリプトを、Jenkins(ブラウザ)上から実行してみます。

CapistranoでオレオレGitデプロイをしてみた
http://madroom-project.blogspot.jp/2013/01/capistranogit.html

この方法はCapistranoを用いたデプロイの一例です。環境により、上記スクリプトそのものや、以下の設定"以外の設定"の調整が、別途必要になるかもしれません。飽くまで参考としてお願いします。


(1)
https://github.com/mp-php/cap4git をDLします。

config/deploy.rbの設定を行います。最低限、以下の修正が必要です。
set :local_user, "xxxxx"
"local_app_dir"は一度削除されるので注意して下さい。

config/deploy以下の環境別設定ファイルの設定を行います。最低限、以下の修正が必要です。
set :git_uri, ""
set :remote_user, "xxxxx"
#set :password, "xxxxx"
role :remote, "#{remote_user}@example.com"
"remote_app_dir"は一度削除されるので注意して下さい。

設定が終わったら、"capistrano"というディレクトリ名で、ZIPにします。このZIPは、後で使います。


(2)
Jenkinsに"Build Secret Plugin"をインストールします。


(3)
Jenkinsで新規ジョブを作成します。このジョブは、以後に作成するジョブの雛形とします。このジョブからはデプロイは行いません。

This build is parameterizedにチェックを入れて、以下の設定をします。
▼Choice
Name: ENV
Choices: staging[改行]production
▼Choice
Name: MODE
Choices: update[改行]rollback
▼String Parameter
Name: CHECKOUT
Default Value: master

Disable Buildにチェックを入れます。

Build EnvironmentのBuild Secretにチェックを入れて、Environment variableに"CAPISTRANO"と入力します。
* この時点でZIPはアップロードしません。

BuildのExecute shellのCommandに以下を入力します。
cd $CAPISTRANO/capistrano
cap $ENV deploy_ -s _mode=$MODE -s _checkout=$CHECKOUT
Saveします。

以下、設定のキャプチャです。
1585x2196(311KB)



(4)
(3)のジョブをコピーして新規ジョブを作成します。実際にデプロイを行うジョブです。
Disable Buildのチェックを外します。
Build EnvironmentのBuild Secretに(1)のZIPをUPしてSaveします。


(5)
ビルドします。


(6)
新たにジョブを作成する場合、(1)と(4)のみでOKです。


以下、ビルド時のログです。一部、Gitコマンドの出力とか、特に問題ないものが何故か"err"と出ていますが。。。尚、ローカルからローカルに対して実行したログになります。(パス等、一部、書き換えています。)

1回目。remote_deploy_toに".git"ディレクトリが無いのでgit initが行われます。
Started by user admin
Building in workspace /var/lib/jenkins/jobs/TEST/workspace
[workspace] $ /bin/sh -xe /tmp/hudson4292648394511032628.sh
+ cd /var/lib/jenkins/secrets/7e022c8d-762c-4c1c-9981-b64b37504d19/capistrano
+ cap staging deploy_ -s _mode=update -s _checkout=master
    triggering load callbacks
  * executing `staging'
    triggering start callbacks for `deploy_'
  * executing `multistage:ensure'
  * executing `deploy_'
  * executing `cleanup_'
  * executing `cleanup_local_'
  * executing "rm -rf /home/xxxxx/capistrano/cap4git/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 231ms
  * executing "mkdir -p /home/xxxxx/capistrano/cap4git/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing `cleanup_reomote_'
  * executing "rm -rf /home/xxxxx/capistrano/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 5ms
  * executing "mkdir -p /home/xxxxx/capistrano/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing `tar_'
  * executing "git clone --bare https://github.com/mp-php/cap4git /home/xxxxx/capistrano/cap4git/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
 ** [out :: xxxxx@localhost] Cloning into bare repository '/home/xxxxx/capistrano/cap4git/repo'...
    command finished in 4293ms
  * executing "tar -cvzf /home/xxxxx/capistrano/cap4git/repo.tar.gz -C /home/xxxxx/capistrano/cap4git/ repo >& /dev/null"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 9ms
  * executing `upload_'
    servers: ["localhost"]
 ** scp upload /home/xxxxx/capistrano/cap4git/repo.tar.gz -> /home/xxxxx/capistrano/repo.tar.gz
    [localhost] /home/xxxxx/capistrano/cap4git/repo.tar.gz
  * scp upload complete
  * executing "tar xvzf /home/xxxxx/capistrano/repo.tar.gz -C /home/xxxxx/capistrano/ >& /dev/null"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 9ms
  * executing "if [ -e /home/xxxxx/repo/.git ]; then echo 'true'; fi"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing `git_init_'
  * executing "if [ -e /home/xxxxx/repo/ ]; then echo 'true'; fi"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing "mkdir -p /home/xxxxx/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing "cd /home/xxxxx/repo/ && git init ."
    servers: ["localhost"]
    [xxxxx@localhost] executing command
 ** [out :: xxxxx@localhost] Initialized empty Git repository in /home/xxxxx/repo/.git/
    command finished in 6ms
  * executing `git_remote_'
  * executing "cd /home/xxxxx/repo/ && git remote rm capistrano"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
*** [err :: xxxxx@localhost] error: Could not remove config section 'remote.capistrano'
    command finished in 5ms
  * executing "cd /home/xxxxx/repo/ && git remote add capistrano /home/xxxxx/capistrano/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 5ms
  * executing `git_pull_'
  * executing "cd /home/xxxxx/repo/ && git pull capistrano master"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
*** [err :: xxxxx@localhost] From /home/xxxxx/capistrano/repo
*** [err :: xxxxx@localhost] * branch            master     -> FETCH_HEAD
    command finished in 47ms
Finished: SUCCESS
2回目。remote_deploy_toに".git"ディレクトリが有るのでgit pullが行われます。
Started by user admin
Building in workspace /var/lib/jenkins/jobs/TEST/workspace
[workspace] $ /bin/sh -xe /tmp/hudson5519699631114845069.sh
+ cd /var/lib/jenkins/secrets/fc7237c2-57b0-41b9-a91c-6dc3ec9b8d57/capistrano
+ cap staging deploy_ -s _mode=update -s _checkout=master
    triggering load callbacks
  * executing `staging'
    triggering start callbacks for `deploy_'
  * executing `multistage:ensure'
  * executing `deploy_'
  * executing `cleanup_'
  * executing `cleanup_local_'
  * executing "rm -rf /home/xxxxx/capistrano/cap4git/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 233ms
  * executing "mkdir -p /home/xxxxx/capistrano/cap4git/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing `cleanup_reomote_'
  * executing "rm -rf /home/xxxxx/capistrano/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 5ms
  * executing "mkdir -p /home/xxxxx/capistrano/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 8ms
  * executing `tar_'
  * executing "git clone --bare https://github.com/mp-php/cap4git /home/xxxxx/capistrano/cap4git/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
 ** [out :: xxxxx@localhost] Cloning into bare repository '/home/xxxxx/capistrano/cap4git/repo'...
    command finished in 3222ms
  * executing "tar -cvzf /home/xxxxx/capistrano/cap4git/repo.tar.gz -C /home/xxxxx/capistrano/cap4git/ repo >& /dev/null"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 9ms
  * executing `upload_'
    servers: ["localhost"]
 ** scp upload /home/xxxxx/capistrano/cap4git/repo.tar.gz -> /home/xxxxx/capistrano/repo.tar.gz
    [localhost] /home/xxxxx/capistrano/cap4git/repo.tar.gz
  * scp upload complete
  * executing "tar xvzf /home/xxxxx/capistrano/repo.tar.gz -C /home/xxxxx/capistrano/ >& /dev/null"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 8ms
  * executing "if [ -e /home/xxxxx/repo/.git ]; then echo 'true'; fi"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 3ms
  * executing `git_remote_'
  * executing "cd /home/xxxxx/repo/ && git remote rm capistrano"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 4ms
  * executing "cd /home/xxxxx/repo/ && git remote add capistrano /home/xxxxx/capistrano/repo/"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
    command finished in 4ms
  * executing `git_checkout_'
  * executing "cd /home/xxxxx/repo/ && git checkout master"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
*** [err :: xxxxx@localhost] Already on 'master'
    command finished in 5ms
  * executing `git_pull_'
  * executing "cd /home/xxxxx/repo/ && git pull capistrano master"
    servers: ["localhost"]
    [xxxxx@localhost] executing command
*** [err :: xxxxx@localhost] From /home/xxxxx/capistrano/repo
*** [err :: xxxxx@localhost] * branch            master     -> FETCH_HEAD
 ** [out :: xxxxx@localhost] Already up-to-date.
    command finished in 29ms
Finished: SUCCESS

January 10, 2013

CapistranoでオレオレGitデプロイをしてみた

ここ最近、Jenkinsで色々と自動化しているので、ついでにデプロイについても考えてみました。Capistranoが便利そうだったので、使ってみました。


最新のソースは以下になります。ちまちまと改良していければと思います。(Rubyは初めてだったので、おかしな書き方があるかもしれませんが。。。)
https://github.com/mp-php/cap4git
コマンドは、上記のconfig/deploy.rbの"Usage:"を御覧ください。READMEは後日書く予定です。

アプリケーション毎に必ず設定すべき箇所は、config/deployディレクトリ以下の環境別設定ファイルと、config/deploy.rbの"Change me."です。尚、local_app_dirとremote_app_dirは一度rmするので、注意して下さい。


想定する環境は
(1) レポジトリは非公開サーバに配置
(2) 非公開サーバから公開サーバはsshでアクセス可、逆は不可
です。

やりたいことは
(3) 公開サーバからpullして更新
です。


* 以下、Capistranoの知識が浅いので、間違っていたらすみません。

Capistranoは、scmをgit、deploy_viaをremote_cacheにすると、(3)のようにレポジトリから直接pullして更新を行うようです。ただし、(2)の理由からNGでした。

deploy_viaをcopyにすると、レポジトリを公開サーバに転送して、そのレポジトリをcloneして更新を行うようです。具体的には、毎回、公開サーバ側で"releases"というディレクトリ下に新規ディレクトリを作成、そのディレクトリにclone。そして、そのディレクトリに対して、"current"というシンボリックリンクを貼るようです。また、currentを過去のリリースディレクトリに貼り替えることで、ロールバックを実現しているようです。

この仕組みは、例えば、ログファイルやキャッシュファイルが出力されるディレクトリ以下をgitignoreしている場合、それらのファイルがrelease毎に分散してしまいます。更に、公開サーバ側でcurrentとreleasesというディレクトリ構成を意識しなくてはいけません。ですので、この方法もNGでした。


上記を踏まえて、以下の方法を考えてみました。
(1) 非公開サーバのテンポラリな場所にgit clone --bareでレポジトリを複製
(2) 複製したレポジトリをtar.gzにして公開サーバにscpで転送
(3) 公開サーバのテンポラリな場所で解凍、デプロイ先からpull
* デプロイ先に".git"ディレクトリが存在しない場合はgit initを行います。

この方法なら、公開サーバ側から非公開サーバ側へのアクセスは発生しません。

既にGitでの更新を行なっているシステムでも使えるようにしたかったので、毎回
git remote rm capistrano
して
git remote add capistrano [(3)で解凍した場所]
しています。つまり、これまでoriginからpullしていたのがcapistranoからpullするようになるだけです。originとcapistranoの歴史が同一であれば、スムーズに移行出来るはずです。(はずです。というのは、実際には、まだ未確認です。。。)スムーズに移行出来ます。ついでに、pullで更新するのみでなく、指定したブランチ / タグ / ハッシュ値等をgit checkoutするrollback機能も書いておきました。

結局、sshやscp周りをCapistranoに任せて、その他は独自で実装した感じです。


以下、主な必要環境です。

▼非公開サーバ側
* Capistranoが実行できる環境
* Gitが実行できる環境
* localhost(非公開サーバ自身)に対して鍵認証(パスワード不要)によるssh接続ができる環境

▼公開サーバ
* Gitが実行できる環境

尚、処理は/bin/bashで進む想定です。


メール送信などの環境依存する問題を調査する際、公開(試験)サーバ上で直接編集、あるいはSFTP等でのアップロードから、一時的な差分が発生する場合が有ります。この差分を正としたい場合、公開サーバ上でremote capistranoにpush、ローカルからpull、非公開サーバのレポジトリにpushというフローを取らなければいけません。


次回は、このスクリプトをJenkinsからキックしてみます。

2013/01/12 Jenkinsから実行してみました。
http://madroom-project.blogspot.jp/2013/01/capistranogitjenkins.html

January 6, 2013

FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた 2

2013/01/06 GitHubに最新のメモを追加しました。
https://github.com/mp-php/fuel-myapp/blob/master/jenkins.md

--

以下の続きです。

FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

Template for Jenkins Jobs for PHP Projects ( http://jenkins-php.org/ ) を参考にして、Checkstyle(PHP_CodeSniffer)/JDepend(PHP_Depend)/Plot(phploc)を追加してみました。内容を把握しきれていないものもありますが、とりあえず入れておくことにします。尚、phpcsコマンド、pdependコマンド、phplocコマンドは依存関係から既にインストールされていました。

build.xmlについては、以下を参考にして頂ければと思います。
https://github.com/mp-php/fuel-myapp/blob/master/build.xml
(相変わらずコマンド直書きですみません。。。)


▼Checkstyle(PHP_CodeSniffer)
(1) PHP_CodeSniffer Fuel PHP Standardをインストール
$ cd ~/tmp
$ wget https://github.com/eviweb/fuelphp-phpcs/archive/master.zip
$ unzip master.zip
$ cd fuelphp-phpcs-master/Standards/
$ sudo mv FuelPHP/ /usr/local/php/latest/lib/php/PHP/CodeSniffer/Standards/
$ phpcs -i
The installed coding standards are PEAR, FuelPHP, Zend, PSR2, MySource, PHPCS, PSR1 and Squiz
"FuelPHP"が表示されていればOKと思います。

(2) phpcsのコマンド例
phpcs --standard=FuelPHP --report-checkstyle=checkstyle.xml fuel/app/

(3) Jenkinsの設定
Checkstyle Pluginをインストールして、ジョブの設定からpost-build actionにPublish Checkstyle analysis resultsを追加。
Checkstyle resultsに出力ファイルを指定。

(4) build.xmlを編集してビルドして結果の確認
ジョブの画面に"Checkstyle Warnings"が表示されます。


▼JDepend(PHP_Depend)
(1) pdependのコマンド例
pdepend --jdepend-xml=jdepend.xml fuel/app/

(2) Jenkinsの設定
JDepend Pluginをインストールして、ジョブの設定からpost-build actionにReport JDependを追加。
Pre-generated JDepend Fileに出力ファイルを指定。

(3) build.xmlを編集してビルドして結果の確認
ビルドの画面に"JDepend"が表示されます。


▼Plot(phploc)
(1) phplocのコマンド例
phploc --log-csv plot.csv fuel/app/

(2) Jenkinsの設定
Plot Pluginをインストールして、ジョブの設定からpost-build actionにPlot build dataを追加。
Plot groupに任意なグループ名を入力。
Data series fileに出力ファイル名を指定。
Load data from csv fileを選択。

(3) build.xmlを編集してビルドして結果の確認
ジョブの画面に"Plots"が表示されます。

Jenkinsで便利そう/面白そうなプラグインのメモ

Jenkinsで便利そう/面白そうなプラグインを探してみました。(それ系の記事を参考にさせて頂いただけですが。。。)尚、ブラグインは一度インストールすると、アンインストール出来ない(?)ので、一度、検証環境で試すのが良いと思います。



▼Jenkins がもっと便利になるおすすめプラグイン 8 つ
http://blog.fenrir-inc.com/jp/2012/12/jenkins_plugins.html
を参考にさせて頂き、以下を試してみました。

* Shelve Project Plugin
プロジェクト画面のサイドバーの"Shelve Project"からプロジェクトをアーカイブ出来ました。また、トップ画面の"Shelved Projects"から戻せました。但し、どういうワケか http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html のプロジェクトはアーカイブ化出来ませんでした。("Shelve Project"のリンクが表示されませんでした。)

* Locale Plugin
設定は、システム設定で出来ました。
Default Language: ja
Ignore browser preference and force this language to all users: チェック
で、英語設定のブラウザも日本語表示になりました。



▼ゲーミフィケーションでJenkinsにアクセスしてもらおう
http://d.hatena.ne.jp/lino/20111204/1322929498
を参考にさせて頂き、以下を試してみました。

* JSGames Plugin
サイドバーの"JS Games"からアクセス出来ました。

* Emotional Jenkins Plugin
有効化は、プロジェクト設定の"Add post-build action"から出来ました。

* The Continuous Integration Game plugin
有効化は、プロジェクト設定の"Add post-build action"から出来ました。

January 5, 2013

FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた

2013/01/06 GitHubに最新のメモを追加しました。
https://github.com/mp-php/fuel-myapp/blob/master/jenkins.md

--

2013/01/05 必要なJenkinsプラグインと必要なPHPモジュール等を追記しました。
2013/01/05 Phing用のテンプレート(コビー用)ジョブについて追記しました。

--

これまで、Jenkins + Phing + FuelPHP + αで、以下を確認しました。

JenkinsとPhingとPHPUnitでFuelPHPのHTMLカバレッジレポートを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpunitfuelphphtml.html

JenkinsとPhingとPHPUnitでFuelPHPのテスト統計を作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpunitfuelphp.html

JenkinsとPhingとphpDocumentor 2でFuelPHPのPHPDocを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpdocumentor-2fuelphpphpdoc.html

JenkinsとPhingとPHPMDでFuelPHPのPMDレポートを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpmdfuelphppmd.html

JenkinsとPhingとPHPCPDでFuelPHPのCPDレポートを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpcpdfuelphpcpd.html


上記を、以下の方法で全自動化してみます。(とりあえず、DL直後のFuelPHPでやってみます。)とは言っても、各手順は上記の通りなので、この記事は、主に、後述するbuild.xmlに対する設定のメモになります。(build.xmlは、上記のURLの内容から修正されています。)

Gitoliteに触れずにGitLabのhookからJenkins側でビルドする
http://madroom-project.blogspot.jp/2013/01/gitolitegitlabhookjenkins.html


尚、以下のように、Jenkins側で権限設定を行なっていても特に問題有りませんでした。

Jenkinsの権限設定メモ
http://madroom-project.blogspot.jp/2013/01/jenkins_5.html

--

以下、手順等です。


JenkinsとGitLabは同一サーバ上で、以下のようにアクセスするイメージです。
* http://example.com/jenkins/
* http://example.com/gitlab/


必要なJenkinsプラグインは、以下になります。
* HTML Publisher plugin
PHPUnitのHTMLカバレッジレポートとPHPDoc用
* xUnit Plugin
PHPUnitのテスト統計用
* PMD Plugin
PHPMDのPMDレポート用
* DRY Plugin
PHPCPDのCPDレポート用


必要なPHPモジュール等は、以下になります。
* PHPUnit
http://madroom-project.blogspot.jp/2013/01/ubuntuphpunit.html
* Xdebug
http://madroom-project.blogspot.jp/2013/01/ubuntuxdebug.html
* Phing
http://madroom-project.blogspot.jp/2013/01/ubuntuphing.html
* phpDocumentor 2とGraphViz
http://madroom-project.blogspot.jp/2012/12/phpdocumentor-2macwin.html
* PHPMDとPHPCPD
PHPUnitとPhingを-a(--alldeps)オプション付きでインストールしたら入っていました。


この記事で使用するbuild.xmlとphpunit.xmlは、以下にUPしてあります。
* https://github.com/mp-php/fuel-myapp/blob/master/build.xml
* https://github.com/mp-php/fuel-myapp/blob/master/phpunit.xml
一応、2013/01/05現在の内容を貼っておきます。
-- build.xml --
<?xml version="1.0" encoding="utf-8"?>
<project name="FuelPHP Project" basedir="." default="all">

    <property name="phing_dir_name" value="phing" />
    <property name="phpunit_dir_name" value="${phing_dir_name}/phpunit" />
    <property name="phpdoc_dir_name" value="${phing_dir_name}/phpdoc" />
    <property name="phpmd_dir_name" value="${phing_dir_name}/phpmd" />
    <property name="phpcpd_dir_name" value="${phing_dir_name}/phpcpd" />

    <target name="init">
        <delete dir="${phing_dir_name}" includeemptydirs="true" />
        <mkdir dir="${phing_dir_name}" />
    </target>

    <target name="phpunit">
        <mkdir dir="${phpunit_dir_name}" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html ${phpunit_dir_name}/coverage/html
            --log-junit ${phpunit_dir_name}/junit.xml
        "/>
    </target>

    <target name="phpdoc">
        <mkdir dir="${phpdoc_dir_name}" />
        <exec dir="." command="
            phpdoc
            -d fuel/app/
            -t ${phpdoc_dir_name}/
        "/>
    </target>

    <target name="phpmd">
        <mkdir dir="${phpmd_dir_name}" />
        <exec dir="." command="
            phpmd
            fuel/app/
            xml
            codesize,design,naming,unusedcode
            --reportfile ${phpmd_dir_name}/pmd.xml
        "/>
    </target>

    <target name="phpcpd">
        <mkdir dir="${phpcpd_dir_name}" />
        <exec dir="." command="
            phpcpd
            --log-pmd ${phpcpd_dir_name}/cpd.xml
            fuel/app/
        "/>
    </target>

    <target name="all" depends="init,phpunit,phpdoc,phpmd,phpcpd" />

</project>
-- phpunit.xml --
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" stopOnFailure="false" bootstrap="../core/bootstrap_phpunit.php">

    <php>
        <server name="doc_root" value="../../"/>
        <server name="app_path" value="fuel/app"/>
        <server name="core_path" value="fuel/core"/>
        <server name="package_path" value="fuel/packages"/>
    </php>

    <testsuites>
        <testsuite name="core">
            <directory suffix=".php">../core/tests</directory>
        </testsuite>
        <testsuite name="packages">
            <directory suffix=".php">../packages/*/tests</directory>
        </testsuite>
        <testsuite name="app">
            <directory suffix=".php">../app/tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <blacklist>
            <directory suffix=".php">../core</directory>
            <directory suffix=".php">../packages</directory>
            <directory suffix=".php">../app/vendor</directory>
        </blacklist>
    </filter>

</phpunit>

(1)
http://www.fuelphp.com/ からzipをDLします。
解凍したディレクトリ(以下、"ルート")のfuelディレクトリ、publicディレクトリ、oilファイルのみを残して、他を削除します。
ルートにbuild.xmlを配置します。
fuel/app/にphpunit.xmlを配置します。

(2)
GitLabの任意なグループ(仮に"xxx"とします。)にプロジェクト(仮に"FuelPHP"とします。)を作成して、(1)一式をpushします。
また、このプロジェクトには http://madroom-project.blogspot.jp/2013/01/gitolitegitlabhookjenkins.html のように、jenkins用ユーザをReporter以上で登録しておきます。
hookの設定も済ませておきます。以下を入力します。
http://example.com/jenkins/git/notifyCommit?url=git@example.com:xxx/fuelphp.git

(3)
Jenkinsのシステム設定で"Git plugin"の"Global Config user.name Value"と"Global Config user.email Value"を入力します。
Jenkinsで"Build a free-style software project"な新規Jobを作成します。
"Source Code Management"は"Git"を選びます。
レポジトリのURLは"git@example.com:xxx/fuelphp.git"になります。
"Repository browser"は"gitlab"を選択して、URLは"http://example.com/gitlab/xxx/fuelphp/"になります。
"Repository browser"の右側辺りの"Advanced..."で"Skip internal tag"にチェックを入れます。
"Build Triggers"の"Poll SCM"にチェックを入れます。
"Build"に"Invoke Phing targets"を追加して、"Targets"を"all"とします。

Post-build Actionsに以下を追加します。

▼Publish PMD analysis results
"PMD results"は"phing/phpmd/pmd.xml"です。

▼Publish duplicate code analysis results
"Duplicate code results"は"phing/phpcpd/cpd.xml"です。

▼Publish HTML reports(PHPUnit用)
"HTML directory to archive"はphing/phpunit/coverage/html"です。
"Index page[s]"はindex.html"です。
"Report title"は"Coverage"です。(ここは何でも良いです。)

▼Publish HTML reports(PHPDoc用)
"HTML directory to archive"はphing/phpdoc"です。
"Index page[s]"はindex.html"です。
"Report title"は"PHPDoc"です。(ここは何でも良いです。)

▼Publish xUnit test result report - PHPUnit-3.x (default)
"Pattern"は"phing/phpunit/junit.xml"です。

"Save"して"Build Now"します。1度では右側にTrendが表示されないようなので、2度行います。

"Coverage"、"PHPDoc"、"PMD Trend"、"Duplicate Code Trend"、"Test Result Trend"が表示されたことを確認します。

(4)
適当に何らかの修正を行い、GitLabにPushして、ビルドが走る事を確認します。


P.S.
長かった。。。ところでJenkinsのJob設定は雛形を作れないのかなー。

--

上記の(3)を毎回行うのは面倒そうなので、コピー用のジョブを作りました。差分のみ記述します。

1. Project name: PhingTemplate
2. Disable Build: チェック
3. GitのRepository URL: 適当なURL
4. Repository browser: 適当なURL
その他の設定は、上記の(3)と同様です。

コピー後は、上記の2/3/4を修正するのみです。

最後に、タイトルには"FuelPHP"とありますが、FuelPHPに依存しているのはbuild.xml(と、build.xmlで指定しているphpunit.xml)のみで、他はPhing周りの話になります。なので、build.xmlを差し替えるだけで、他のPHPプロジェクトでも使えるかなと。

2013/01/06 続き書きました。

FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた 2
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins-2.html

Gitoliteに触れずにGitLabのhookからJenkins側でビルドする

GitLabのプロジェクトの"Services"に"Jenkins CI An extendable open source continuous integration server Not implemented yet"という表示があるので、そのうち対応するのかなという楽観から、とりあえず、Gitoliteを触らない方法を取りました。尚、この方法は、GitLabのプロジェクト毎に、後述のJenkins用のユーザを"Reporter"以上で登録する必要があり、その点は面倒です。

JenkinsとGitLabは同一サーバ上で、以下のようにアクセスするイメージです。
* http://example.com/jenkins/
* http://example.com/gitlab/


-- Linux(Ubuntu)での作業 --
(1)
/var/lib/jenkins/.ssh/gitlab/id_rsa(パーミッションは600)と/var/lib/jenkins/.ssh/gitlab/id_rsa.pubを用意します。
* /var/lib/jenkins/はjenkinsユーザのホームディレクトリです。
* 同一サーバ上で作成した公開鍵だと後述のGitLabへの登録時に"Key can't be fingerprinted"というエラーが出て登録出なかったので、とりあえず、他所で鍵を作って、それを登録しました。

(2)
/var/lib/jenkins/.ssh/config を編集します。
Host example.com
User git
Hostname example.com
IdentityFile /var/lib/jenkins/.ssh/gitlab/id_rsa


-- GitLabでの作業 --
(1)
任意のグループにプロジェクト(レポジトリ)を作成して、初期化コミットしておきます。以下、仮に"xxx"グループに"yyy"レポジトリを作成したとします。
* 何のコミットも無いと、後述の、プロジェクトへのメンバー追加が出来ませんでした。

(2)
HookのURLを、以下の形式で設定をしておきます。
http://example.com/jenkins/git/notifyCommit?url=git@example.com:xxx/yyy.git

(3)
GitLabにJenkins用のユーザを作成します。

(4)
(1)で作成したプロジェクトに、(2)で作成したJenkins用のユーザを"Reporter"以上で登録します。
* ある意味、最強の"Reporter"です。。。

(5)
Jenkinsユーザでログインしなおして公開鍵を登録します。この公開鍵は、前述の"/var/lib/jenkins/.ssh/gitlab/id_rsa.pub"です。


-- Jenkinsでの作業 --
(1)
Jobを"Build a free-style software project"で新規作成します。

(2)
"Source Code Management"で"Git"を選択して"git@example.com:xxx/yyy.git"を入力します。

(3)
"Advanced..."から"Skip internal tag"にチェックを入れます。
Manage Jenkins > Configure System > Git plugin で
"Global Config user.name Value"と"Global Config user.email Value"を入力します。

(4)
"Build Triggers"で"Poll SCM"にチェックを入れます。

(5)
"Build Now"してビルドが成功すれば、Jenkins側の設定はOKです。また、GitLabにコミットして、Jenkins側でビルドが走れば一通りOKです。

--

これで、Phingとつなげれば。。。

Jenkinsの権限設定メモ

メモです。かなり細かく設定できるみたいですが、とりあえず
* 全操作が可能なアカウント(admin)
* プロジェクト関係の全操作が可能なアカウント(dev)
の二つを用意してみます。

(1)
Manage Jenkins > Configure System > Enable security にチェック
* セキュリティを有効化します。

(2)
Security Realm > Jenkins's own user database にチェック > Allow users to sign up のチェックを外す
* Jenkins上にユーザを作成します。ユーザによるサインアップは許可しません。

(3)
Authorization > Matrix-based security にチェック
* その下のProject-based Matrix Authorization Strategyだとプロジェクト単位で権限管理が可能なようですが、今回はシンプルにこちらで。

(4)
User/group to add:にadminと入力 > Addをクリック > 全権限にチェック > Save をクリック
* とりあえず、管理者を作成しておきます。

(5)
初期ユーザ作成画面が出るのでUsernameを"admin"にして、作成します。

(6)
(4)と同様の手順で"dev"ユーザを作成します。与える権限は、OverallのRead、Jobの全て、Runの全てとしました。

尚、複数ブラウザを使って同一アカウントで同時ログインできました。これで、adminでログイン時は全操作が可能、devでログイン時はプロジェクト関係の全操作が可能。となったはず。たぶん。。。


Jenkinsで誰もログイン出来なくなってしまったら

Jenkinsは権限設定をうっかり間違えると、誰もログイン出来なくなってしまうようです。実験がてら、実際にやってみました。

この場合の対策ですが、以下に書いてありました。
https://wiki.jenkins-ci.org/display/JENKINS/Disable+security

Jenkinsを停止して、$JENKINS_HOMEのconfig.xmlを以下のように編集します。
* useSecurityをfalseにする
* authorizationStrategyとsecurityRealmを削除する

編集が終わったらJenkinsを起動します。

尚、$JENKINS_HOMEはUbuntuだと/var/lib/jenkinsでした。

January 4, 2013

JenkinsとPhingとPHPCPDでFuelPHPのCPDレポートを作成する

2013/01/05 以下に、まとめ記事を書きました。
FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

--

前回の内容に、PHPCPDによるCPDレポートの出力を加えてみます。
* 「JenkinsとPhingとxxxでFuelPHPのyyyを作成する」シリーズはこれで落ち着きます。。。

JenkinsとPhingとPHPMDでFuelPHPのPMDレポートを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpmdfuelphppmd.html

尚、前回のPHPMDと同様、PHPCPDはPEARでインストールできますが、PHPUnit(あるいはPhing??)を-a(--alldeps)オプション付きでインストールすると、一緒に入ってくるようです。既に入ってました。


PHPCPDは、PHPのコードの重複を自動で検出してくれます。
PHPCPD公式??(GitHub): https://github.com/sebastianbergmann/phpcpd


(1)
Jenkinsで"DRY Plugin"をインストールします。


(2)
Jobの設定からPost-build Actionsで"Publish duplicate code analysis results"を選択して、以下を入力します。
Duplicate code results: phpcpd/cpd.xml


(3)
build.xmlを編集します。(前回の内容に、「target name="phpcpd"」を追加して、「target name="all"」の"depends"に"phpcpd"を追加しています。)
<?xml version="1.0" encoding="utf-8" ?>
<project name="FuelPHP Project" basedir="." default="all">

    <target name="phpunit">
        <delete dir="phpunit" includeemptydirs="true" />
        <mkdir dir="phpunit" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html phpunit/coverage/html
            --log-junit phpunit/junit.xml
        "/>
    </target>

    <target name="phpdoc">
        <delete dir="phpdoc" includeemptydirs="true" />
        <mkdir dir="phpdoc" />
        <exec dir="." command="
            phpdoc
            -d fuel/app/
            -t phpdoc/
        "/>
    </target>

    <target name="phpmd">
        <delete dir="phpmd" includeemptydirs="true" />
        <mkdir dir="phpmd" />
        <exec dir="." command="
            phpmd
            fuel/app/
            xml
            codesize,controversial,design,naming,unusedcode
            --reportfile phpmd/pmd.xml
        "/>
    </target>

    <target name="phpcpd">
        <delete dir="phpcpd" includeemptydirs="true" />
        <mkdir dir="phpcpd" />
        <exec dir="." command="
            phpcpd
            --log-pmd phpcpd/cpd.xml
            fuel/app/
        "/>
    </target>

    <target name="all" depends="phpunit,phpdoc,phpmd,phpcpd" />

</project>

(4)
ビルド後、サイドメニューに"Duplicate Code"が表示されれば成功です。尚、問題がない場合(空のディレクトリをスキャンした等)、表示されませんでした。(2回実行すると右側に"Duplicate Code Trend"と出ました。)



とりあえず、これで残すはGitLabのhookからの全自動化か。。。

JenkinsとPhingとPHPMDでFuelPHPのPMDレポートを作成する

2013/01/05 追記:
以下に、まとめ記事を書きました。
FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

--

前回の内容に、PHPMDによるPMDレポートの出力を加えてみます。

JenkinsとPhingとphpDocumentor 2でFuelPHPのPHPDocを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpdocumentor-2fuelphpphpdoc.html

PHPMDは、PHPのコードの問題を自動で検出してくれます。
PHPMD公式: http://phpmd.org/

尚、PHPMDはPEARでインストールできますが、PHPUnit(あるいはPhing??)を-a(--alldeps)オプション付きでインストールすると、一緒に入ってくるようです。既に入ってました。


(1)
Jenkinsで"PMD Plugin"をインストールします。
* HTMLレポートも出力できるので、前回と同様"HTML Publisher plugin"を用いても良いですが、情報量の観点から、今回は"PMD Plugin"を使います。


(2)
Jobの設定からPost-build Actionsで"Publish PMD analysis results"を選択して、以下を入力します。
PMD results: phpmd/pmd.xml


(3)
build.xmlを編集します。(前回の内容に、「target name="phpmd"」を追加して、「target name="all"」の"depends"に"phpmd"を追加しています。)
<?xml version="1.0" encoding="utf-8" ?>
<project name="FuelPHP Project" basedir="." default="all">

    <target name="phpunit">
        <delete dir="phpunit" includeemptydirs="true" />
        <mkdir dir="phpunit" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html phpunit/coverage/html
            --log-junit phpunit/junit.xml
        "/>
    </target>

    <target name="phpdoc">
        <delete dir="phpdoc" includeemptydirs="true" />
        <mkdir dir="phpdoc" />
        <exec dir="." command="
            phpdoc
            -d fuel/app/
            -t phpdoc/
        "/>
    </target>

    <target name="phpmd">
        <delete dir="phpmd" includeemptydirs="true" />
        <mkdir dir="phpmd" />
        <exec dir="." command="
            phpmd
            fuel/app/
            xml
            codesize,controversial,design,naming,unusedcode
            --reportfile phpmd/pmd.xml
        "/>
    </target>

    <target name="all" depends="phpunit,phpdoc,phpmd" />

</project>

(4)
ビルド後、サイドメニューに"PMD Warnings"が表示されれば成功です。 尚、PHPMDのルールで"controversial"を指定するとキャメルケース関係の警告が出るようになります。今回は、サンプルということで書いてありますが、FuelPHP 1.xのコーディング規約はスネークケースなので、必要に応じて外して下さい。

参考: http://phpmd.org/rules/index.html


JenkinsとPhingとphpDocumentor 2でFuelPHPのPHPDocを作成する

2013/01/05 追記:
以下に、まとめ記事を書きました。
FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

--

前回の内容に、phpDocumentor 2によるPHPDocの出力を加えてみます。

JenkinsとPhingとPHPUnitでFuelPHPのテスト統計を作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpunitfuelphp.html


phpDocumentor 2のインストールは、以下を参考にして下さい。

phpDocumentor 2のインストール手順(Mac/Win/Linux)
http://madroom-project.blogspot.jp/2012/12/phpdocumentor-2macwin.html


(1)
Jobの設定のPost-build ActionsのPublish HTML reportsに、以下を追加します。
HTML directory to archive: phpdoc
Index page[s]: index.html
Report title: PHPDoc


(2)
build.xmlを編集します。(前回の内容に、「target name="phpdoc"」を追加して、「target name="all"」の"depends"に"phpdoc"を追加しています。)
<?xml version="1.0" encoding="utf-8" ?>
<project name="FuelPHP Project" basedir="." default="all">

    <target name="phpunit">
        <delete dir="phpunit" includeemptydirs="true" />
        <mkdir dir="phpunit" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html phpunit/coverage/html
            --log-junit phpunit/junit.xml
        "/>
    </target>

    <target name="phpdoc">
        <delete dir="phpdoc" includeemptydirs="true" />
        <mkdir dir="phpdoc" />
        <exec dir="." command="
            phpdoc
            -d fuel/app/
            -t phpdoc/
        "/>
    </target>

    <target name="all" depends="phpunit,phpdoc" />

</project>

(3)
ビルド後、"PHPDoc"が表示されれば成功です。


コマンド直書きでゴリ押し気味。。。

JenkinsとPhingとPHPUnitでFuelPHPのテスト統計を作成する

2013/01/05 追記:
以下に、まとめ記事を書きました。
FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

--

前回の内容に、テスト統計の取得を加えてみます。

JenkinsとPhingとPHPUnitでFuelPHPのHTMLカバレッジレポートを作成する
http://madroom-project.blogspot.jp/2013/01/jenkinsphingphpunitfuelphphtml.html


(1)
Jenkinsに"xUnit Plugin"をインストールします。


(2)
Jobの設定からPost-build Actionsで"Publish xUnit test result report"を選択して、"PHPUnit-3.x (default)"をAddして、以下を入力します。
Pattern: phpunit/junit.xml

* "Publish JUnit test result report"でも似たようなことができますが、以下のエラーが出てしまいました。
Build step 'Publish JUnit test result report' changed build result to UNSTABLE
Finished: UNSTABLE

(3)
build.xmlを編集します。(前回の内容に、"--log-junit phpunit/junit.xml"を付け足しただけです。)
<?xml version="1.0" encoding="utf-8" ?>
<project name="FuelPHP Project" basedir="." default="all">

    <target name="phpunit">
        <delete dir="phpunit" includeemptydirs="true" />
        <mkdir dir="phpunit" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html phpunit/coverage/html
            --log-junit phpunit/junit.xml
        "/>
    </target>

    <target name="all" depends="phpunit" />

</project>

(4)
ビルド後、画面右側に"Test Result Trend"と表示されれば成功です。(2回目以降に表示されます。)

JenkinsとPhingとPHPUnitでFuelPHPのHTMLカバレッジレポートを作成する

2013/01/05 追記:
以下に、まとめ記事を書きました。
FuelPHPとGitLabとJenkinsで継続的インテグレーションする雛形を考えてみた
http://madroom-project.blogspot.jp/2013/01/fuelphpgitlabjenkins.html

--

以下が済んでいる環境で、手順を確認しました。

UbuntuにPHP 5.4.10をインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntu550alpha2.html

UbuntuにPHPUnitをインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntuphpunit.html

UbuntuにXdebugをインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntuxdebug.html

UbuntuにPhingをインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntuphing.html

JenkinsとPhingの連携サンプル
http://madroom-project.blogspot.jp/2013/01/jenkinsphing.html

なので、要点は
* コマンドでPHPUnitによるカバレッジレポートの作成が出来る
* Phingのインストールが完了している
になります。

以下、FuelPHPのHTMLカバレッジレポートを作成する手順です。


(1)
Manage Jenkins > Configure System > Global properties > Environment variables で以下のように入力して、PHPにパスを通します。
name: PATH
value(例): ${PATH}:/usr/local/php/latest/bin/

Manage Jenkins > Configure System > Jenkins URL が正しいか確認します。間違っていると、後で出力するHTMLレポートのリンクがおかしくなります。


(2)
Jenkinsに"HTML Publisher plugin"をインストールします。インストール後、Jobの設定からPost-build ActionsでPublish HTML reportsを選択して、以下を入力します。
HTML directory to archive: phpunit/coverage/html
Index page[s]: index.html
Report title: Coverage


(3)
build.xmlを作成します。(今回は、コマンド直書きしました。)
<?xml version="1.0" encoding="utf-8" ?>
<project name="FuelPHP Project" basedir="." default="all">

    <target name="phpunit">
        <delete dir="phpunit" includeemptydirs="true" />
        <mkdir dir="phpunit" />
        <exec dir="." command="
            phpunit
            -c fuel/app/phpunit.xml
            --coverage-html phpunit/coverage/html
        "/>
    </target>

    <target name="all" depends="phpunit" />

</project>
尚、fuel/app/phpunit.xmlは、以下の内容を想定しています。
https://github.com/mp-php/fuel-myapp/blob/master/phpunit.xml
また、後々、"--log-junit"とかを追加する予定です。(後ほど、別記事で書く予定です。)


(4)
Jobの設定をします。具体的には、以下の「3. Jobの設定」を参考にして下さい。尚、今回の場合、Targetsは"all"となります。
http://madroom-project.blogspot.jp/2013/01/jenkinsphing.html
* "../core"と"../packages"と"../app/vendor"を除外していますが、必要に応じて調整して下さい。


(5)
ビルドを実行後、リロードして、"Coverage"が表示されていれば成功です。


build.xmlのちゃんとした書き方を覚えなくては。

January 3, 2013

JenkinsとPhingの連携サンプル

Phingのインストールについては、以下を御覧ください。
http://madroom-project.blogspot.jp/2013/01/ubuntuphing.html

1. Jenkinsのプラグインをインストール
/pluginManager/available から"Phing Plugin"をインストールします。

2. build.xmlの作成
* ファイル名の競合を避けるために、とりあえずbuild.xml.jenkinsとしました。
-- /var/lib/jenkins/jobs/xxx/workspace/build.xml.jenkins --
<?xml version="1.0" encoding="utf-8" ?>
<project name= "phing_test" basedir= "." default= "main">
    <target name="main" depends= "init"></target>
    <target name="init" >
        <delete dir= "./phing_test_dir" includeemptydirs= "true" />
        <mkdir dir= "./phing_test_dir" />
    </target>
</project>
3. Jobの設定
Build > Add build step > Invoke phing targets と進み、以下のように入力しました。
Targets: main
Phing Build File: build.xml.jenkins

4. ビルド実行
以下のエラーが出ました。
FATAL: command execution failed.Maybe you need to configure the job to choose one of your Phing installations?
java.io.IOException: Cannot run program "phing" (in directory "/var/lib/jenkins/jobs/xxx/workspace"): java.io.IOException: error=2, No such file or directory
とりあえずシンボリックリンクで回避しました。
$ sudo ln -s /usr/local/php/latest/bin/phing /usr/bin/phing
参考: http://renoiv.com/blog/2012/06/

5. 再度、ビルド実行
workspace直下に"phing_test_dir"が作成されました。

UbuntuにPhingをインストールする

依存関係を含めてインストールしてみます。(なんか色々入りました。。。)
$ sudo pear channel-discover pear.phing.info
$ sudo pear install -a phing/phing
$ phing -v
Phing 2.4.14
次の記事で、Jenkinsと連携させてみます。

---

参考:
Users/Installation – Phing
http://www.phing.info/trac/wiki/Users/Installation

Phingをjenkinsと連携させてみる
http://log.miraoto.com/2012/04/503/

UbuntuにXdebugをインストールする

メモです。

1. Xdebugのインストール
$ sudo pecl install xdebug
$ sudo vim /usr/local/php/php-5.4.10/lib/php.ini

# 以下を記述
zend_extension="/usr/local/php/php-5.4.10/lib/php/extensions/no-debug-zts-20100525/xdebug.so"
"zend_extension"ではなく"extension"で指定すると、後述の「2. コマンドラインから確認」で、以下の警告が出ました。
PHP Warning: Xdebug MUST be loaded as a Zend extension in Unknown on line 0
参考: http://stackoverflow.com/questions/2350965/php-throwing-xdebug-errors-only-in-command-line-mode

2. コマンドラインから確認
$ php -v
PHP 5.4.10 (cli) (built: Jan  2 2013 03:26:39) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans
3. ブラウザから確認
$ sudo service apache2 restart
phpinfoで以下のような表示がされること。
This program makes use of the Zend Scripting Language Engine:
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans

関連: UbuntuにPHPUnitをインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntuphpunit.html

Androidの公式Gmailアプリ4.2.1で指定したGmailアドレスの受信トレイを開く

以前は、以下の方法で、指定したGmailアドレスの受信トレイを開けました。
Intent i = new Intent();
i.setPackage("com.google.android.gm");
i.setAction(Intent.ACTION_MAIN);
i.putExtra("account", "[対象のGmailアドレス]");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(i);
公式Gmailアプリ4.2.1では、上記の方法では開けなくなっていました。実際には、もう少し前のバージョンからかもしれません。

以下のように書き換えると、公式Gmailアプリ4.2.1でも、指定したGmailアドレスの受信トレイを開けました。尚、labelの識別子さえわかれば、受信トレイ以外も開けるはずです。
Intent i = new Intent(Intent.ACTION_VIEW);
i.setComponent(new ComponentName("com.google.android.gm", "com.google.android.gm.ConversationListActivityGmail"));
i.setData(Uri.parse("content://gmail-ls/account/[対象のGmailアドレス]/label/^i"));
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(i);
P.S.
Flag周りはあまり関係ないかもしれません。

January 2, 2013

MacでAndroidのdebug.keystoreのkey hashを生成する

コマンドのメモです。
$ keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore > /tmp/android/cert.txt
$ openssl sha1 -binary /tmp/android/cert.txt > /tmp/android/sha1.txt
$ openssl base64 -in /tmp/android/sha1.txt
表示されたhash値を、Facebook側のアプリ設定で登録したりします。

--

参考:
アプリのKey Hashをfacebookに登録

Androidでtwitter4jを使っていたらgetOAuthRequestToken()でNetworkOnMainThreadException

久しぶりにAndroidネタです。

AndroidManifest.xmlのandroid:minSdkVersionとandroid:targetSdkVersionを調整しただけなのですが、twitter4jのgetOAuthRequestToken()でNetworkOnMainThreadExceptionが発生するようになってしまいました。

getOAuthRequestToken()の直前に、以下を書いたら回避できました。
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
実際には、twitter4j云々というより、ネットワーク周りの話になると思います。

Androidも、いつかしっかり再学習しないとなー。

参考:
http://stackoverflow.com/questions/12621638/asynctask-with-facebook-and-twitter4j
http://stackoverflow.com/questions/12297233/twitter4j-code-doent-work-on-ics-and-jellybean-help-me

UbuntuにPHPUnitをインストールする

PHP 5.4.10をインストールしたUbuntuにPHPUnitをインストールしてみます。
$ sudo pear install -a pear.phpunit.de/PHPUnit
$ phpunit --version
PHPUnit 3.7.10 by Sebastian Bergmann.
関連:
UbuntuにPHP 5.4.10をインストールする
http://madroom-project.blogspot.jp/2013/01/ubuntu550alpha2.html

UbuntuにPHP 5.4.10をインストールする

追記:
最初、PHP 5.5.0alpha2のインストールをしたのですが、PEARのインストールが上手く行かず、5.4.10をインストールしなおしました。関連箇所を修正しています。

--

以前、以下の記事を書きました。

UbuntuにApacheとPHPとPEARをインストールする
http://madroom-project.blogspot.jp/2012/12/ubuntuapachephp.html

手順は簡単なのですが、PHPのバージョンがPHP 5.3.10と古かったので、5.4.10をインストールし直してみました。尚、make installにはpacoを使っています。また、予め、上記のURLでインストールした余計なパッケージを削除しました。
$ sudo apt-get autoremove php5 libapache2-mod-php5 php-pear
--

1. インストール
$ cd ~/tmp/src/
$ wget http://jp2.php.net/get/php-5.4.10.tar.gz/from/jp1.php.net/mirror -O php-5.4.10.tar.gz
$ tar xfvz php-5.4.10.tar.gz
$ cd php-5.4.10/
$ './configure' \
'--prefix=/usr/local/php/php-5.4.10' \
'--with-apxs2=/usr/bin/apxs2' \
'--enable-mbstring' \
'--with-mysql' \
'--with-mysqli' \
'--with-pdo-mysql' \
'--with-xsl' \
'--with-mcrypt' \
'--enable-pcntl' \
'--with-curl' \
'--with-zlib' \
'--with-openssl'
$ make
$ sudo paco -D make install
* オプションについては別途まとめようと思っています。とりあえずスカスカです。。。
* --with-xslは、phpDocumentor 2で必要でした。
* --with-mcryptはphpMyAdminで必要でした。(先にlibmcrypt-devをインストールする必要がありました。)
* --enable-pcntlはPHPUnitのインストール時、PHP_Invokerというものを併せてインストールするのに必要でした。
* --with-zlibとwith-opensslはDokuWikiのプラグインインストールに必要でした。

参考:
中心となる configure オプションのリスト
http://php.net/manual/ja/configure.about.php

2. php.iniの編集
$ sudo vim /usr/local/php/php-5.4.10/lib/php.ini
 
# 以下を記述
date.timezone="Asia/Tokyo"
3. パスを通す
# シンボリックリンクを作成
$ sudo ln -s /usr/local/php/php-5.4.10 /usr/local/php/latest

$ vim ~/.bashrc
# ~/.bashrcに以下を追記
PATH=/usr/local/php/latest/bin:$PATH
alias sudo="sudo env PATH=$PATH"

# 反映
$ source ~/.bashrc
* "alias sudo"の箇所については、以下を参考にさせて頂きました。

rubyインストールしてあるのにsudoすると「/usr/bin/env: ruby: そのようなファイルやディレクトリはありません」と言われる
http://d.hatena.ne.jp/japanrock_pg/20090527/1243426081

4. コマンドから確認
$ php -v
PHP 5.4.10 (cli) (built: Jan  2 2013 03:26:39) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies

$ pear version
PEAR Version: 1.9.4
PHP Version: 5.4.10
Zend Engine Version: 2.4.0
Running on: Linux localhost 3.2.0-35-generic #55-Ubuntu SMP Wed Dec 5 17:42:16 UTC 2012 x86_64
5. Apacheをリスタート
$ sudo service apache2 restart
6. ブラウザから確認
phpinfo()で、"PHP Version 5.4.10"と表示されました。

7. ついでにPEARの設定など
# チャンネルを更新
$ sudo pear update-channels

# PEARをアップグレード
$ sudo pear upgrade -a PEAR

# パッケージをアップグレード
$ sudo pear upgrade-all

# 新規チャネルを自動的に探す
$ sudo pear config-set auto_discover 1

# キャッシュをクリア
$ sudo pear clear-cache

January 1, 2013

UbuntuでJenkinsを更新する

jenkins.warを更新した際の手順メモです。

1. Jenkinsを停止
$ sudo service jenkins stop
2. jenkins.warファイルのパスを確認
$ grep JENKINS_WAR /etc/default/jenkins
JENKINS_WAR=/usr/share/jenkins/jenkins.war
3. jenkins.warのバックアップと更新
$ sudo mv /usr/share/jenkins/jenkins.war /usr/share/jenkins/jenkins.war.yyyymmdd
$ sudo wget http://updates.jenkins-ci.org/download/war/[バージョン]/jenkins.war -O /usr/share/jenkins/jenkins.war
4. Jenkinsを起動
$ sudo service jenkins start

JenkinsでGitプロジェクトをビルドしてみる

試しにFuelPHPでやってみます。 とりあえず、Jenkinsでジョブを作成して、Gitからソースをビルドするだけです。尚、Mac OS Xで確認しています。
* 後ほど、Ubuntuでも確認しました。


1. Gitプラグインのインストールと再起動
--
Jenkins > Manage Jenkins > Manage Plugins > Available > "Git Plugin"にチェック > Download now and install after restart > "Restart Jenkins when installation is complete and no jobs are running"にチェック
* 後述の"3. ジョブの設定"で必要になります。
* Ubuntuでは、手動で再起動しました。

2. 新規ジョブ作成
--
Jenkins > New Job > Job nameは"FuelPHP" > "Build a free-style software project"にチェック > OK


3. ジョブの設定(Jenkins > FuelPHP > Configureより)
--
(1) Source Code Managementで"Git"にチェック > Repository URLを"https://github.com/fuel/fuel.git"に。

(2) "Repository browser"近くの"Advanced…" > "Skip internal tag"にチェック
Manage Jenkins > Configure System > Git plugin でGlobal Config user.name ValueとGlobal Config user.email Valueを入力。
* これをしないと、Mac/Ubuntu共に、後述の"Please tell me who you are."エラーが発生しました。
参考: http://stackoverflow.com/questions/11122913/jenkinsgit-tell-me-who-you-are-error-why-does-it-need-to-tag

(3) 画面最下部の"Save"で保存


4. ビルド
--
Jenkins > FuelPHP > Build Now


5. ワークスペースの確認
--
Jenkins > FuelPHP > Workspace


"Please tell me who you are."エラーのログ
ユーザーanonymousが実行
ビルドします。 ワークスペース: /Users/Shared/Jenkins/Home/jobs/FuelPHP/workspace
Checkout:workspace / /Users/Shared/Jenkins/Home/jobs/FuelPHP/workspace - hudson.remoting.LocalChannel@11513fd0
Using strategy: Default
Fetching changes from 1 remote Git repository
Fetching upstream changes from https://github.com/fuel/fuel.git
Seen branch in repository origin/1.0/master
Seen branch in repository origin/1.1/master
Seen branch in repository origin/1.2/develop
Seen branch in repository origin/1.2/master
Seen branch in repository origin/1.3/develop
Seen branch in repository origin/1.3/master
Seen branch in repository origin/1.4/develop
Seen branch in repository origin/1.4/master
Seen branch in repository origin/1.5/develop
Seen branch in repository origin/HEAD
Commencing build of Revision 8c69f6781d09ba4447cd529c655137b39eb82af1 (origin/1.0/master)
Checking out Revision 8c69f6781d09ba4447cd529c655137b39eb82af1 (origin/1.0/master)
FATAL: Could not apply tag jenkins-FuelPHP-3
hudson.plugins.git.GitException: Could not apply tag jenkins-FuelPHP-3
 at hudson.plugins.git.GitAPI.tag(GitAPI.java:829)
 at hudson.plugins.git.GitSCM$4.invoke(GitSCM.java:1270)
 at hudson.plugins.git.GitSCM$4.invoke(GitSCM.java:1231)
 at hudson.FilePath.act(FilePath.java:852)
 at hudson.FilePath.act(FilePath.java:825)
 at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1231)
 at hudson.model.AbstractProject.checkout(AbstractProject.java:1325)
 at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:676)
 at jenkins.scm.SCMCheckoutStrategy.checkout(SCMCheckoutStrategy.java:88)
 at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:581)
 at hudson.model.Run.execute(Run.java:1543)
 at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
 at hudson.model.ResourceController.execute(ResourceController.java:88)
 at hudson.model.Executor.run(Executor.java:236)
Caused by: hudson.plugins.git.GitException: Command "git tag -a -f -m Jenkins Build #3 jenkins-FuelPHP-3" returned status code 128:
stdout: 
stderr: 
*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: empty ident  <jenkins@macbook.local> not allowed

 at hudson.plugins.git.GitAPI.launchCommandIn(GitAPI.java:897)
 at hudson.plugins.git.GitAPI.launchCommand(GitAPI.java:858)
 at hudson.plugins.git.GitAPI.launchCommand(GitAPI.java:868)
 at hudson.plugins.git.GitAPI.tag(GitAPI.java:827)
 ... 13 more

Macでsudoに続くコマンドの補完を有効にする

1. ~/.bash_profileを編集します。
sudo vim ~/.bash_profile
2. 以下を、適当な場所に追記します。
complete -cf sudo
3. ターミナルを再起動します。

これで、sudoの後も、タブキーで補完が可能になります。

--

関連:
Ubuntuで最初にやったことメモ
http://madroom-project.blogspot.jp/2012/12/ubuntu_26.html

MacにJenkinsをインストールして起動したり停止したり

インストールは簡単で http://jenkins-ci.org/ からpkgをDLして、指示に従い進めるだけです。

インストールが完了した後、ブラウザから http://localhost:8080 にアクセスするとJenkinsが表示されます。

停止と起動は、以下のコマンドで出来ました。
#停止
sudo launchctl unload /Library/LaunchDaemons/org.jenkins-ci.plist
#起動
sudo launchctl load /Library/LaunchDaemons/org.jenkins-ci.plist
参考:
Jenkins Mac OS X InstallerでJenkinsを入れる
http://www.iwazer.com/~iwazawa/diary/2011/11/jenkins-mac-os-x-installer.html

尚、/Users/Shared/Jenkins/Home/が作られていて、この中に"jobs"とか"plugins"とかありました。

--

関連:
Ubuntu 12.04にJenkinsをインストールしてApacheでポート80で動かす
http://madroom-project.blogspot.jp/2012/12/ubuntu-1204jenkinsapache80.html

Ubuntuにnode.jsとsocket.ioをインストールする

手順のメモ。

* "~/tmp/src"は適当なディレクトリです。
* pacoは任意です。
* "~/node"は適当なディレクトリです。
* * socket.ioはとりあえずローカルインストールしてみました。(-gオプションを付けない。)
$ cd ~/tmp/src
$ sudo apt-get install -y python g++ make paco
$ wget -N http://nodejs.org/dist/node-latest.tar.gz
$ tar xzvf node-latest.tar.gz && cd `ls -rd node-v*`
$ ./configure
$ sudo paco -D make install

$ sudo curl http://npmjs.org/install.sh | sudo sh
$ cd ~/node
$ sudo npm install socket.io