Windows版Redmineをサービスに登録してブート時に起動させる(宿題あり)
あらすじ
タイトル通り、サービスに登録してよろしく起動してほしい。mongrelを使えばサービスから起動できる……らしいが、名前は聞いたことあるけど、mongrelが何かは知らない……。
Ruby + C(拡張ライブラリ) で書かれた httpd。
http://d.hatena.ne.jp/keyword/mongrel
なるほど。
環境
- Windows XP
- Ruby 1.9.3
- Bundler 1.0.21
- Mongrel 1.2.0.pre2
- Redmine 1.4
手順
インストールから起動まで
gem "mongrel"
$ bundle install Fetching source index for http://rubygems.org/ Using rake (0.9.2.2) Using activesupport (2.3.14) Using rack (1.1.3) Using actionpack (2.3.14) Using actionmailer (2.3.14) Using activerecord (2.3.14) Using activeresource (2.3.14) Installing cgi_multipart_eof_fix (2.5.0) Using coderay (1.0.6) Installing gem_plugin (0.2.3) Using i18n (0.4.2) Installing mongrel (1.1.5) Using mysql2 (0.2.18) Using net-ldap (0.3.1) Using pg (0.13.2) Using rails (2.3.14) Using ruby-openid (2.1.8) Using sqlite3 (1.3.6) Using tzinfo (0.3.33) Using bundler (1.0.21) Your bundle is complete! It was installed into ./vendor/bundle
- bundle exec ruby ...で起動…しようとするとエラー
msvcrt-ruby18.dll が見つからなかったため、このアプリケーションを開始できませんでした。アプリケーションをインストールし直すとこの問題は解決される場合があります。
- 【Ruby1.9】msvcrt-ruby18.dll が見つからなかったため、このアプリケーションを開始できませんでした。・・・とエラーが。。。 | ぐるらん という事らしいので、jsonを消してみることに……ただ、バージョンが違うんだよなあ。
$ gem list ... json (1.5.4) ...
$ gem uninstall json Successfully uninstalled json-1.5.4
- で、再起動……だめだった!!
- Windowsでrails3.0をMongrelで動かす | simultechnology.blog によると、さっきいれてたmongrel 1.1.5 はRuby 1.8のモジュールを使っているという事らしい
- 新しいバージョン(今はプレリリース版)を入れることで解決できる。Gemfileを修正しbundle install
-gem "mongrel" +gem "mongrel", ">= 1.2.0.pre2"
$ bundle install ... Installing mongrel (1.2.0.pre2)
=> Booting WEBrick
=> Booting Mongrel
に変わった!
サービスに登録
- mongrel_serviceをGemfileに登録
gem "mongrel_service"
- インストールできたらmongrel_railsというコマンドが追加される(今回はbundlerでインストールしたので、Redmineのrootまで行ってbundle exec mongrel_rails)
[C:\redmine-1.4.0] $ be mongrel_rails Usage: mongrel_rails <command> [options] Available commands are: - restart - start - stop - service::install - service::remove
- Serviceに追加
オプション | 意味 |
---|---|
-N | サービス名 |
-c | Redmineのルート |
-p | 起動ポート |
-e | Railsの起動モード |
$ be mongrel_rails service::install -N "Redmine" -c C:\redmine-1.4.0 -p 3000 -e production ** Copying native mongrel_service executable... Redmine service created.
- 登録に成功したのでWin+rからservices.mscを呼び出して確認……
- あった!
- スタートアップの種類が手動になっていたので自動に変更
- マシン再起動!
起動しない……だと……?
サービスから起動できなかった
C:\RUBY_ROOT\bin\ruby.exe: No such file or directory -- C:/RUBY_ROOT/bin/mongrel_rails (LoadError)
うーん。RUBY_ROOTのbin下にmongrel_railsを探しに行ってる? ……でも今回はbundlerで入れたからREDMINE_ROOT/vendor/bundle下を見に行ってほしいんだけどなぁ。
ちょっと試しにbundlerからmongrel, mongrel_serviceをはずして、gemで直接Mongrelをインストールしてみる。
$ gem install mongrel --pre $ gem install mongrel_service
これで
ということになり、RUBY_ROOTにMongrelがあるので、再起動すればサービスから起動してくれるはず……。
再々起動…起動した!
まとめ
- 一応、サービスから起動させる事はできた
- ただし、直接gem installしたものに限る。サービスから起動させるとRUBY_ROOTを見にいってしまうようなのでbundlerで入れるとLoadErrorになってしまう
Fluentdというログ収集ツールを使ってApacheのログを取得するまで
あらすじ
Fluentdとは
Log everything in JSON
http://fluentd.org/
Oh...シンプルイズベスト…。
Fluentd is a log collector daemon written in Ruby. Fluentd receives logs as JSON streams, buffers them, and sends them to other systems like MySQL, MongoDB, or even other instances of Fluentd.
Rubyで作られたログ収集ツール。ただし、JSONで……?
参考サイト
手順
とりあえずbundlerで動かしてみるためにGemfileを作成。
$ cat Gemfile source :rubygems source "http://rubygems.org" gem 'fluentd'
インストール。
$ bundle install --path ./vendor/bundle Fetching gem metadata from http://rubygems.org/.... Fetching gem metadata from http://rubygems.org/.... Installing iobuffer (1.1.2) with native extensions Installing cool.io (1.1.0) with native extensions Installing http_parser.rb (0.5.3) with native extensions Installing json (1.7.3) with native extensions Installing msgpack (0.4.7) with native extensions Installing yajl-ruby (1.1.0) with native extensions Installing fluentd (0.10.24) Using bundler (1.1.3) Your bundle is complete! It was installed into ./vendor/bundle
OK。*1
実行
- 設定ファイルなどのテンプレートを指定先に作ってくれる。
$ bundle exec fluentd --setup ./fluent Installed ./fluent/fluent.conf.
- コンフィグファイル指定+traceモードで起動
$ bundle exec fluentd -c ./fluent/fluent.conf -vv & [1] 12973 2012-07-10 21:37:47 +0900: fluent/supervisor.rb:153:supervise: starting fluentd-0.10.24 2012-07-10 21:37:47 +0900: fluent/supervisor.rb:235:read_config: reading config file path="./fluent/fluent.conf" 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered buffer plugin 'file' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered buffer plugin 'memory' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'exec' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'forward' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'gc_stat' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'http' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'object_space' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'status' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'tcp' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'unix' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'syslog' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered input plugin 'tail' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'copy' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'exec' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'exec_filter' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'file' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'forward' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'null' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'roundrobin' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'stdout' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'tcp' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'unix' 2012-07-10 21:37:47 +0900: fluent/plugin.rb:85:register_impl: registered output plugin 'test' 2012-07-10 21:37:47 +0900: fluent/engine.rb:63:block in configure: adding source type="forward" 2012-07-10 21:37:47 +0900: fluent/engine.rb:63:block in configure: adding source type="http" 2012-07-10 21:37:47 +0900: fluent/engine.rb:79:block in configure: adding match pattern="debug.**" type="stdout" 2012-07-10 21:37:47 +0900: plugin/in_forward.rb:60:listen: listening fluent socket on 0.0.0.0:24224 2012-07-10 21:37:47 +0900: plugin/in_http.rb:74:start: listening http on 0.0.0.0:8888
- ログを送ってみる
$ echo '{"json":"message"}' | bundle exec fluent-cat debug.test 2012-07-10 21:40:02 +0900: plugin/in_forward.rb:139:initialize: accepted fluent socket object_id=14145560 2012-07-10 21:40:02 +0900 debug.test: {"json":"message"} 2012-07-10 21:40:02 +0900: plugin/in_forward.rb:180:on_close: closed fluent socket object_id=14145560
Apacheのログを集めてみる
集めるログ……自鯖のApacheのログをfluentdで集めてみよう。
- コンフィグファイルにはじめからコメントアウトされている設定があったので、これを利用
## File input ## read apache logs with tag=apache.access <source> type tail format apache path /var/log/httpd-access.log tag apache.access </source>
- typeにはInput Pluginを指定するらしい。種類はhttp, tail, forward, execなど
- format(必須)はLogのフォーマットを指定。今回はApacheのログなのでapache
- path(必須)はLogのパスかな
- tag(必須)はfluentd内で使うタグ? myapp.accessみたいにドットで分けるらしい
上記の条件にマッチしたものを、今度はmatchタグに従ってoutputしている……のかな?
## match tag=apache.access and write to file <match apache.access> type file path /home/kk_Ataka/log </match>
では動かしてみよう。
$ sudo bundle exec fluentd -c fluent/fluent.conf
Apacheへアクセス。(Redmineがいるので、Redmineホームにアクセスしてみる)
…。
…。
結果
Apacheの方でいつもどおり作られたログ
xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET / HTTP/1.1" 200 4371 xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /themes/alternate/stylesheets/application.css?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /javascripts/controls.js?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /javascripts/effects.js?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /javascripts/prototype.js?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /javascripts/dragdrop.js?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /javascripts/application.js?1339785657 HTTP/1.1" 304 - xxx.xxx.xxx.xxx - - [10/Jul/2012:22:20:30 +0900] "GET /stylesheets/scm.css?1339785657 HTTP/1.1" 304 - ::1 - - [10/Jul/2012:22:20:36 +0900] "OPTIONS * HTTP/1.0" 200 -
見慣れたもんが出ました。
fluentdで作られたログ
2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/","code":"200","size":"4371"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/themes/alternate/stylesheets/application.css?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/javascripts/controls.js?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/javascripts/effects.js?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/javascripts/prototype.js?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/javascripts/dragdrop.js?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/javascripts/application.js?1339785657","code":"304","size":"-"} 2012-07-10T22:20:30+09:00 apache.access {"host":"xxx.xxx.xxx.xxx","user":"-","method":"GET","path":"/stylesheets/scm.css?1339785657","code":"304","size":"-"} 2012-07-10T22:20:36+09:00 apache.access {"host":"::1","user":"-","method":"OPTIONS","path":"*","code":"200","size":"-"}
自動で全部jsonにparseされている! さすがLog everything in JSONと公式に書いているだけの事はある!
こうなってくると、MongoDBとかの知識も必要になってくるな。
JenkinsでAdmin権限を持つユーザのパスワードを全て忘れた時の復旧方法
あらすじ
- ローカルで動かしているJenkinsでAdministrator権限を持っているユーザ、およびそのパスワードを忘れたので、色々な事ができなくなった
- また、Administrator権限を持つユーザがいない = Jenkinsの管理画面が開けなくなった事で権限復旧もできなくなった
環境
- Windows XP
- Jenkins 1.470
- ユーザ情報: Jenkinsのユーザデータベース
- 権限管理: 行列による権限設定
- ローカルで運用している
- JenkinsはWindowsサービスに登録している
原因と解決手順
気づき
! 内容符号化 (Content-Encoding) に問題があります 不正または不明な形式で圧縮されているため、ページを表示できません。 ・この問題を Web サイトの管理者に報告してください。 [再試行]
- 試しにChromeでもやってみたがこう
このウェブページにアクセスできません http://localhost:8080/manage のウェブページは一時的に停止しているか、 新しい http://localhost:8080/manage に移動した可能性があります。 エラー 330 (net::ERR_CONTENT_DECODING_FAILED): 不明なエラーです。
- まさかのIE6。ログイン画面からレイアウト崩れてて(さすがにサポートしてないよなぁ)とか思いつつアクセスすると…
アクセスできません kk_Ataka には、Administer パーミッションがありません。
なんだと!? …でも管理画面にいけないんだから、権限も振れないよ。どうしよう。
TDD Boot Camp 大阪 1.0( #tddbc ) に参加しました
概要
- TDD Boot Camp 大阪 1.0( #tddbc ) : ATND
- なかなかスケジュールの都合がつかず、近場で開催されても参加できないことが多かったので、「次こそは!」と思った矢先の大阪開催だったので参加しました
まとめ
- 楽天カフェテリア@大阪、非常に素晴らしい会場でした。素晴らしい会場でした!
- カフェテリアは木製の椅子のため、半日近いイベントの場合腰が悪い人は座布団を持って行ったほうがいいですね
- TDDとペアプロに関しての経験をつむことができた
- よしおかさん、関さん、和田さんを独占していたRubyのテーブル…
- その中でも恐れ多くも関さんと和田さんを独占してしまった。会場撮影されていた様子^^; goyo (goyoki) on Via.Me
- 成果物はStep3のはじめまでGitHubにあげました
- よしおかさん、関さん、和田さんを独占していたRubyのテーブル…
- 他の言語でどう書くか、書き方などを見て、自分のメイン言語のテスティングフレームワークでも出来るかな? と調べる事が大事
- ねんがんのグリーンバンドを手に入れたぞ!
- TDDは一人でも出来るので、どんどん書いて量を質に転化させていく!
- 主催の@Mitsuyuki Shiiba (@bufferings) op Twitter さん、TAの皆さん、スピーカーである@Takuto Wada (@t_wada) op Twitter さん、@Hiro Yoshioka (@hyoshiok) op Twitter さん、@seki at druby.org (@m_seki) op Twitter さん、Ruby島の皆さんお疲れ様でした!
以下、時系列にそったまとめ
TDDのこころ @Takuto Wada (@t_wada) op Twitter さん
BootCampとは
- 新兵に教官が優しく教える
- しかしスライドの画像*1は2012年現在もはや厳しい…
今日やること
- ペアプログラミングを体験してみる
- コードレビュー大会
- 同じコードを同僚と解くという機会はほぼない
- 同じお題を他の人はどう考えるのか、他の言語ではどうなるのか
ふりかえり
- KPT形式でフィードバック
ソフトウェア開発の三本柱
- バージョン管理、テスティング、自動化
- RPGのノーセーブクリア=バージョン管理なしの開発
- 今コードが動いているのか動いていないのか=テスティング
- 人間が手作業でやっているものをシェル化、Jenkinsで回したりで機械に任せる=自働化、自動化
- 機械がうまくいってない時だけ教えてくれる
「テスト」とは
- 誰が、なんのためにテストをするのかで簡単に分類
- Developer Testing
- 開発者が開発促進のため
- Customer Testing
- 顧客が進捗管理のため(受入テストとか)
- QA Testing
- 品質保証担当者が品質保証のため
- Developer Testing
「TDD」とは
TDDのサイクル
- テストを書き
- テストを実行して失敗させ(Red)
- 目的のコードを書き
- テストを成功させ(Green)
- そのテスト通るまま中を綺麗にしていく(Refactor)
- これを繰り返す
TDDのやり方
- 大きな問題は切り分けて1つずつ
- たくさんの問題も1つずつ
- 何をテストすればよいのか
- 開発を進めにくくする要因→何かわからないもの、不安
TDDをすることにより
- 即座にフィードバックを得る
- 書いたコードへの自信持つ
- これから書くコードに自信を持つ
TDDの真の目的
- 不安の克服
- 健康
- コードの健康=仕様変更に対応できる
- チームの健康=仕様変更に備える事ができる
ペアプロ
- Ruby島は4人でした
- お題はこれ。結構複雑 TDD Boot Camp(TDDBC) - TDDBC大阪1.0
- テーブルにバリバリ使ってるぜ! という人がいなかったのでどう組もうかー相談していたら、なんとよしおかさんと関さんが「Ruby席に混ぜて」という状況に
- 恐れ多くも関さんとペアプロさせて頂く事態に((((;゜Д゜)))
- RSpecでどうテスト書こうかというところで、どういう単位でテストを作るかのような話になり、色んな書き方があるのだなと感じました。
- 僕は「小さい自前のスクリプトに対してのテスト」くらいの使い方しかしていなかったから一個一個の振る舞いに対して1つずつit "〜できる、it "〜する"と実装していこうと考えていた
- 対して、関さんは一つのテストをシナリオで考えていたので、はじめにこうしてこうやって最後にこうという感じ
昼休み
- 楽天デリバリによるお弁当サービス
- 結構種類が豊富だった
昼休み2 実際の事例(和田さんの午前セッションの続き)
- TDDを採用したときのTDDを採用していない類似プロジェクトと比較
- 例えばIBM、15%~20%くらいテストコードのための実装時間が増えたが、4割くらい欠陥が減った
- Visual Studioがすごい!欠陥密度0.09
- テストコードを書く時間は増えるが、軽微なミスが減るため、デバッグの工数は減る→トータルで開発工数を減らす事ができると考えられる
昼休み3 LT
午後の部開始 QA
- テストメソッドの名前はどうやって考えているか
- 日本語で書いている、英語の場合はxx is … when …
- テスト名のテストの中身が重複していたらDRY的にはどう?
- RSpecの場合構造だけでテストの意味がわかるようにしている
- 入れ子構造で意味がわかるようにするのが最近のテストのトレンド
- 状況は詳しく書くけど何をの部分はサッパリと書く
- enclosed
- プライベートメソッドのテストをしたい…
- プライベートメソッドはパブリックメソッド経由でテストできるはずなので、プライベートメソッドをテストしたいといっている時点で設計がおかしい
開発者の皆さん、テストを書こう よしおかさん
事例 Oracle8の開発現場
事例2 DEC Rdb
- 米国で開発されたソフトウェアを日本語へ
- ソフトウェア国際化のあるべき姿の議論
ペアプロ午後の部
- 後ほど発表があるということで関さん離脱。ありがとうございました
- なんとバトンタッチは和田さん((((;゜Д゜)))
- 和田さんが午前中に書いていたテストをガンガン洗練させていく!
- 黄金の回転で一番難しいと思っているRefactorの部分を間近で見ているのでマジでためになる!
- 今回教えて頂いたのはitの中は簡潔になるように心がけるというもの
- テストのための準備をbeforeで書く!
- contextでは「この時、これを確認、これを確認」レベルで済ませるように書く。
- contextの中身はlet, its, itsで!
- という事らしい。確かに見やすい
- これで、他の状態の時にこうあるべきというのも一行追加でいける
describe "投入金額に注目" do before do @vending = Vending.new @change = @vending.enter(input) end subject { @vending } context "だめな硬貨だけのとき" do let(:input) { [1,5,2000] } it { @change.should == [1,5,2000] } its(:show) { should == 0 } end context "1000円札を入れたとき" do let(:input) { [1000] } it { @change.should == [] } + its(:show) { should == 1000 } #この状態の時にも end
TDDとは 関さん@seki at druby.org (@m_seki) op Twitter
TDDのおさらい
- 今日楽しかった?
TDDのサイクル
- 次の目標を考える
- その目標を示す
- 黄金の回転…
- これを繰り返す
TDDはなんだっけ
- テストによって導かれた開発の事
- 今日のは実装例の一つかも
TDDの変形
もうひとつのテスト
- Checking
- 既知の情報の確認
- Testing
- 新しい情報、未知の情報を探す
ご提案
- Red Green Refactor
- ちょっとずつ仮設の上に仮設を重ねる
- Destroy
- この実装ならバグが出るだろみたいなのを
- たまに破壊的な思考を持ち込む
QA
終わりに 和田さん
- ペアプログラミングをやってテストのサイクルを回す
- コードレビュー大会
- 「あの言語でこんな事出来るんだ」発見→「俺の言語でもできんじゃん!」
- 黄金の回転
- 各象限を越えるときの心持ち
- 本をたどる
- 2人目がいないので広めるのに心が折れちゃう
- まず一人でやって見せて背中を見せる
- 量は質に転化する
そして懇親会へ…
- ピザが一瞬でとけた
Jenkins,Redmine使いこなし勉強会に参加しました と、ちょっとプラグイン作ってみた #jen_red
Redmineプラグイン活用入門 - @Kokawa Takashi (@Kokawa_Takashi) op Twitterさん
注意:Redmine開発環境が安定していないので、すぐ陳腐化してしまう事がある!
プラグインの探し方・おすすめ
- Redmineプラグイン集 - r-labs
- Plugins - Redmine
- 一つだけおすすめを… Wiki Extensions Plugin
- オートプレビュー
- 任意のページをメニューに
- 任意のページを埋め込み 等々…
- 他のおすすめ
- CodeRevirew
- Backlogs
- TimeTracker
REST API
- 自動でチケットを作ったりできる
- チケット一覧を取得できたり
- この一連の流れができたらJenkinsに任せる事ができる
- 期日が間近のチケットのメール通知などもできる
プラグインを作る
- Redmine1.4 or 2.0が対象(Ruby1.9,Bundler対応している/これ以前はしていない)
- プラグイン開発環境構築がつらいので
Ruby環境
- WindowsならRubyInstaller + DevKit
- MacならRVM
- 自分でも少しまとめている 複数のRuby環境の管理・切替ができるrvmをインストールした - kk_Atakaの日記
Redmineインストール
- 公式を参考に
- rmagickを除外する
bundle install -without development test rmagick -path vendor/bundle
NetBeans
- ただし、公式サポートは6.9.1が最終
一つだけシンプルなプラグインを
- Redmineのメニューからヘルプを消す
- スケルトンを作ってinit.rbに一文足すだけ
- 最後に試してみるよ
Jenkinsプラグイン活用入門- @さぼてん(さぼ福)しんざき 佐藤太一 (@cactusman) op Twitterさん
Jenkinsとは
- 高性能Cron
プラグインの探し方
- 探す前に…
- shやbatなどをうまく組み合わせられないかなどをまず考える
- Jenkins自体の昨日もうまく使う
- プラグイン自体は本家に登録されている
- Jenkins Plugin Hub
- ソフト、ツール名などでとりあえず引っ掛けてみる
プラグインの使い方
- すごくメンテされているものとほったらかされているものでまちまち
- コミットやDL数を見てみる
- TackScanerPlugin
- キーワードを拾う(TODOなど)
- 最後に入れてみる
- DickUsagePlugin
- Jenkinsのディスク使用量を見る
- JobConfigHistoryPlugin
- 設定ファイルのバックアップ、差分表示
プラグインのハック
- エクステンションポイントを継承する
- Notifierを継承すれば通知系の事ができる
- mvnにおまじないを追加する
- Jenkinsの公式Pluginが参考になる
実際にやってみる(Redmine)
メニューの一部を消してみる。
環境
- Windows XP
- Ruby 1.8.7
- Redmine 1.0.0.stable (SQLite)
手順
- はじめにRedmine Pluginのスケルトンを作成する。名前はdelete_menuとした
$ cd REDMINE_ROOT $ ruby script\generate redmine_plugin delete_menu ./script/../config/../vendor/rails/railties/lib/rails/gem_dependency.rb:119:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010. Use #requirement create vendor/plugins/redmine_delete_menu/app/controllers create vendor/plugins/redmine_delete_menu/app/helpers create vendor/plugins/redmine_delete_menu/app/models create vendor/plugins/redmine_delete_menu/app/views create vendor/plugins/redmine_delete_menu/db/migrate create vendor/plugins/redmine_delete_menu/lib/tasks create vendor/plugins/redmine_delete_menu/assets/images create vendor/plugins/redmine_delete_menu/assets/javascripts create vendor/plugins/redmine_delete_menu/assets/stylesheets create vendor/plugins/redmine_delete_menu/lang create vendor/plugins/redmine_delete_menu/config/locales create vendor/plugins/redmine_delete_menu/test create vendor/plugins/redmine_delete_menu/README.rdoc create vendor/plugins/redmine_delete_menu/init.rb create vendor/plugins/redmine_delete_menu/lang/en.yml create vendor/plugins/redmine_delete_menu/config/locales/en.yml create vendor/plugins/redmine_delete_menu/test/test_helper.rb
- vendor/pluginにredmine_delete_menuというフォルダができている
$ ls ... redmine_delete_menu/ ... $ cd redmine_delete_menu $ ls README.rdoc assets/ db/ lang/ test/ app/ config/ init.rb* lib/
- init.rbに例の一文を挿入
Redmine::Plugin.register :redmine_delete_menu do ... + delete_menu_item :top_menu, :help end
- そして起動
$ cd REDMINE_ROOT $ ruby script\server -e production => Booting WEBrick => Rails 2.3.5 application starting on http://0.0.0.0:3000 ./script/../config/../vendor/rails/railties/lib/rails/gem_dependency.rb:119:Warning: Gem::Dependency#version_requirements is deprecated and will be removed on or after August 2010. Use #requirement => Call with -d to detach => Ctrl-C to shutdown server [2012-05-28 19:15:50] INFO WEBrick 1.3.1 [2012-05-28 19:15:50] INFO ruby 1.8.7 (2010-12-23) [i386-mswin32] [2012-05-28 19:15:50] INFO WEBrick::HTTPServer#start: pid=4640 port=3000
- http://localhost:3000 にアクセスすると…おお! 消えてる!
手順その2
- いきなりgenerateしようとしたらbundle installしろと言われた
$ ruby script\generate redmine_plugin delete_menu Some gems may need to be installed or updated. Please run `bundle install --without development test`.
- なのでbundle install
$ bundle install --without development test --path ./vendor/bundle Fetching source index for http://rubygems.org/ Installing rake (0.9.2.2) Installing activesupport (2.3.14) Installing rack (1.1.3) Installing actionpack (2.3.14) Installing actionmailer (2.3.14) Installing activerecord (2.3.14) Installing activeresource (2.3.14) Installing coderay (1.0.6) Installing i18n (0.4.2) Installing mysql2 (0.2.18) Installing net-ldap (0.3.1) Installing pg (0.13.2) Installing rails (2.3.14) Installing rmagick (2.13.1) with native extensions
- rmagickが入らず止まりっぱなし……そういえば、rmagickは使わなければwithoutしてしまってもいいです的な事を言われていた気がするのでそれをプラス
$ bundle install --without development test rmagick --path ./vendor/bundle Fetching source index for http://rubygems.org/ Using rake (0.9.2.2) Using activesupport (2.3.14) Using rack (1.1.3) Using actionpack (2.3.14) Using actionmailer (2.3.14) Using activerecord (2.3.14) Using activeresource (2.3.14) Using coderay (1.0.6) Using i18n (0.4.2) Using mysql2 (0.2.18) Using net-ldap (0.3.1) Using pg (0.13.2) Using rails (2.3.14) Installing ruby-openid (2.1.8) Installing sqlite3 (1.3.6) Installing tzinfo (0.3.33) Using bundler (1.0.21) Your bundle is complete! It was installed into ./vendor/bundle
- 再度。先ほどbundlerを使ったのでbundle exec
$ bundle exec ruby script\generate redmine_plugin delete_menu C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.14/lib/active_support/inflector.rb:3:in `<top (required)>': iconv will be deprecated in the future, use String#encode instead. NOTE: Gem.source_index is deprecated, use Specification. It will be removed on or after 2011-11-01. Gem.source_index called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/gem_dependency.rb:21. NOTE: Dependency.new w/ a regexp is deprecated. Dependency.new called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails_generator/lookup.rb:211 NOTE: Gem.cache is deprecated, use Gem::source_index. It will be removed on or after 2011-08-01. Gem.cache called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails_generator/lookup.rb:212. NOTE: Gem.source_index is deprecated, use Specification. It will be removed on or after 2011-11-01. Gem.source_index called from C:/rubies/Ruby-193-p0/lib/ruby/1.9.1/rubygems.rb:1154. NOTE: Gem::SourceIndex#search is deprecated with no replacement. It will be removed on or after 2011-11-01. Gem::SourceIndex#search called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/vendor_gem_source_index.rb:119. NOTE: Gem::SourceIndex#search is deprecated with no replacement. It will be removed on or after 2011-11-01. Gem::SourceIndex#search called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/vendor_gem_source_index.rb:119. NOTE: Gem.cache is deprecated, use Gem::source_index. It will be removed on or after 2011-08-01. Gem.cache called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails_generator/lookup.rb:234. NOTE: Gem.source_index is deprecated, use Specification. It will be removed on or after 2011-11-01. Gem.source_index called from C:/rubies/Ruby-193-p0/lib/ruby/1.9.1/rubygems.rb:1154. NOTE: Gem::SourceIndex#each is deprecated with no replacement. It will be removed on or after 2011-11-01. Gem::SourceIndex#each called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/vendor_gem_source_index.rb:123. NOTE: Gem::SourceIndex#each is deprecated with no replacement. It will be removed on or after 2011-11-01. Gem::SourceIndex#each called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/vendor_gem_source_index.rb:124. create vendor/plugins/redmine_delete_menu/app/controllers create vendor/plugins/redmine_delete_menu/app/helpers create vendor/plugins/redmine_delete_menu/app/models create vendor/plugins/redmine_delete_menu/app/views create vendor/plugins/redmine_delete_menu/db/migrate create vendor/plugins/redmine_delete_menu/lib/tasks create vendor/plugins/redmine_delete_menu/assets/images create vendor/plugins/redmine_delete_menu/assets/javascripts create vendor/plugins/redmine_delete_menu/assets/stylesheets create vendor/plugins/redmine_delete_menu/lang create vendor/plugins/redmine_delete_menu/config/locales create vendor/plugins/redmine_delete_menu/test create vendor/plugins/redmine_delete_menu/README.rdoc create vendor/plugins/redmine_delete_menu/init.rb create vendor/plugins/redmine_delete_menu/config/locales/en.yml create vendor/plugins/redmine_delete_menu/test/test_helper.rb
- deprecateがやまほど出たけど、一応スケルトンは作れたみたい。で、init.rbを編集。ここは同じ
Redmine::Plugin.register :redmine_delete_menu do ... + delete_menu_item :top_menu, :help end
- で、起動。ここでもbundle exec
$ bundle exec ruby script\server -e production C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.14/lib/active_support/inflector.rb:3:in `<top (required)>': iconv will be deprecated in the future, use String#encode instead. => Booting WEBrick => Rails 2.3.14 application starting on http://0.0.0.0:3000 NOTE: Gem.source_index is deprecated, use Specification. It will be removed on or after 2011-11-01. Gem.source_index called from C:/redmine-1.4.0/vendor/bundle/ruby/1.9.1/gems/rails-2.3.14/lib/rails/gem_dependency.rb:21. => Call with -d to detach => Ctrl-C to shutdown server [2012-05-28 20:03:32] INFO WEBrick 1.3.1 [2012-05-28 20:03:32] INFO ruby 1.9.3 (2011-10-30) [i386-mingw32] [2012-05-28 20:03:32] INFO WEBrick::HTTPServer#start: pid=3248 port=3000
1.4台でもいけた!
実際にプラグインを入れてみる(Jenkins)
Task Scanner Pluginを入れてみよう。
環境
- Windows XP
- Jenkins 1.450
手順
- Jenkinsの管理 => プラグインの管理 => 利用可能タブ => Task Scanner Pluginをチェックしインストール
- Static Code Analysis Plug-insも同時にDLされるみたい
- 再起動
- Jenkinsプロジェクト => 設定 => ビルド後の処理 => 未解決タスクの集計*1にチェック
- 保存してビルド
- 一度ビルドするとJenkinsプロジェクトのメニューに【未解決タスク】のリンクが表示される
- 今回設定した//TODOがまとめられてる!
- 後、//TODO hogehogeとキーワードの後ろに何か書いておくとメッセージとしてどんなTODOなのかも表示される!
SlideShareのAPIを叩いてスライドをDLするRubyスクリプトをHerokuにデプロイした
あらすじ
slideshareを社内から閲覧する事を禁じられているので、ワンクッションおいてスライドのpptを落とせるようにしたい
流れ
API申請
- slideshare -> Developer & APIのページからApply for API keyに移動
- ログイン or 新規アカウント作成
- Name、E-Mail、How do you want to use the API?を入力し送信。頑張って英文書く。
I want to get slideshare's slide from API.
- 送信されたメールに貼られているAPI KeyとShared Secretを控える
パラメータ
- slideshare -> Documentationを見ながら必要なパラメータを調べる
api_key | さっきのAPI Key |
---|---|
ts | タイムスタンプ*1 |
hash | さっきのShared Secretとこれから取得するtsでハッシュを作る*2 |
(username) | 登録ID |
(password) | パスワード |
全然関係ないけど、Documentationのページ内にあるi.e.って単語を初めて見たのでググってみた。論文中の「e.g.」「i.e.」の意味は何? - Diary@一色政彦WebSite that is ... すなわちとかそういう意味らしい。e.g.で例えば、for example的な。
ソース
ソースはこんな感じ。
require 'openssl' require 'uri' require 'net/http' url = 'http://www.slideshare.net/api/2/get_slideshow' param = Hash.new param["slideshow_url"] = 'http://www.slideshare.net/gishi/wicket-presentation' param["api_key"] = 'XXXXXXXX' param["sharedsecret"] = 'XXXXXXXX' # ts param["ts"] = Time.now.to_i.to_s # hash param["hash"] = Digest::SHA1.hexdigest(param["sharedsecret"]+param["ts"]) uri = URI.parse(url) Net::HTTP.new(uri.host).start do |http| #Net::HTTP.new(uri.host, 80, ENV["PROXY"], 8080).start do |http| uri_param = param.sort.map {|i|i.join('=')}.join('&') res = http.get(uri.path + '?' + uri_param) puts res.body end
成功するとこんな感じの内容が返ってくる。
<?xml version="1.0" encoding="UTF-8"?> <Slideshow> <ID>579496</ID> <Title>Wicket体験談</Title> <Description>第1回Wicket勉強会のライトニングトーク発表資料</Description> <Status>2</Status> <Username>gishi</Username> <URL>http://www.slideshare.net/gishi/wicket-presentation</URL> <ThumbnailURL>http://cdn.slidesharecdn.com/wicket-1220375587470160-8-thumbnail</ThumbnailURL> <ThumbnailSmallURL>http://cdn.slidesharecdn.com/wicket-1220375587470160-8-thumbnail-2</ThumbnailSmallURL> <Embed><div style="width:425px" id="__ss_579496"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/gishi/wicket-presentation" title="Wicket体験談">Wicket体験談</a></strong><object id="__sse579496" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=wicket-1220375587470160-8&stripped_title=wicket-presentation&userName=gishi" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><param name="wmode" value="transparent"/><embed name="__sse579496" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=wicket-1220375587470160-8&stripped_title=wicket-presentation&userName=gishi" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" wmode="transparent" width="425" height="355"></embed></object><div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/gishi">Hiroto Yamakawa</a>.</div></div></Embed> <Created>Tue Sep 02 10:14:12 -0500 2008</Created> <Updated>Tue Sep 02 10:16:15 -0500 2008</Updated> <Language>ja</Language> <Format>ppt</Format> <Download>1</Download> <DownloadUrl>http://s3.amazonaws.com/ppt-download/wicket-1220375587470160-8.ppt?response-content-disposition=attachment&Signature=ABs151smgWZ9213%2FyFq81fnMc6A%3D&Expires=1328606581&AWSAccessKeyId=AKIAJLJT267DEGKZDHEQ</DownloadUrl> <SlideshowType>0</SlideshowType> <InContest>0</InContest> </Slideshow>
おー取れた。んで、xmlの中のDownloadUrlからpptをゲットできた! これをSinatraでWebアプリケーションにしてHerokuにデプロイすれば職場から行けるかな!?
BPStudy#57に参加しました #bpstudy
第一部 新たな価値観へのITビジネス視点での転換 萩本順三さん
- 政治的な話は無し
- 私が技術顧問として最適化計画を見た時、「古いな〜」と思った
- 問題があるプロジェクトに入り込んで、どうするかというのが仕事
- 火を吹いた時に入り込んでいく => はじめにオフィスへ入り込んで資料を見た時「これやめないんですか?」と聞いたほど
- 問題があるプロジェクトに入り込んで、どうするかというのが仕事
- かなりはじめの段階からダメと周りの人にも言っていたが……
何が問題か?
根底の問題は?
- IT業界の負のビジネス慣習
- ユーザ、開発両者のスキル不足
- お客さんに教えながらモデル化をしていくものなのに
- ユーザ、開発両者のスキル不足
- コスト配分が開発者寄りになり、たとえいいものを作ったとしてもユーザさんが使いこなせない
- うまく要件を引き出せないと、正しくないシステムができてしまう
- 是正しなければ
意識改革 コタツモデル
- ユーザから話を聞いてシステム開発に入るが、ユーザは必ず正しいのか
- 以下の3つから"将来"の価値を取りに行く視点を持つ
- 戦略的視点(偉い人)
- 業務問題解決の視点(業務担当の偉い人)
- IT活用の視点(開発の出来る人)
- しかし、偉い人は現在の価値を取りに行きがちだし、業務担当の偉い人は業務問題解決の視点しか持っていないことが多い
- 戦略的視点から業務解決、IT活用をしていくと、偉い人も「あ、俺業務知らなかったな」と感じで同じコタツに入ってくれる => 要求が収束する
- Howの手探り
- ビジネス戦略から
- Howの突き上げ
- テクノロジーを使うともしかしたら業務がいらなくなるかもしれない => 戦略に結びつける
- 最適化
- 切ってつなげて並行でスピーディに走らせる
- 常に価値で問う
- 設計ドキュメントなどは誰に対して価値があるのかを問う。説明できなければいらないじゃない?(ただし、技術的に説明できない場合もある)
- 自分が持っている知識をお客さんに魅力的に見えるものとする
- 自分のやりたいこと(How)を実現していこう(What)
- 自動車メーカ、ファッション業界ではできているのになぜソフトウェア業界でできない
- システム要求の牢屋に閉じ込められていたらできっこない
5年後のIT業界
- 巨大システムの開発(一枚岩)からアクセサリ化に
- コーディネート化する必要がある
- 開発者が一番強い。なぜならHowを握っているから
- ピラミッド型組織から分散自立型組織に
- 優秀な人は残して優秀じゃない人は返す、返された人は価値に敏感になれるように
- 学び、勇気を持って行動してください
第二部 執筆プロジェクトの継続的ビルド @shimizukawaさん、@cactusmanさん
この本はSphinxで書きました
- 執筆はreST
- 社内レビューはhtml
- 社外レビューはpdf
- 見た目を自由に変えられる
- 見た目を変えると誤記などに気づける
編集さんに提出
まとめ
- 提出現行の明確な仕様を決めておけばよかった
- 編集と差分管理しやすいテキストで
- レビュは別のビューで
- 環境は自動化で
Jenkins
- Jenkinsのプラグインで文中のTODOを拾える
- TODOの状態がグラフでわかる!
■■のススメ @urasokoさん
- 以前高橋メソッドを使いLTで10分、今回は5分を切る
- SIer(大規模)につとめ、普段は調整等のお仕事をしていた……が、4/末日に「選職」しました
- 「小さなチーム、大きな仕事」に感銘を受けた
- 社会に何を求めるか、どうありたいか、何を成したいか
- 会社の上でではなく、社会の上で選び続ける
- 作りたいのは技術集団なのか、役人集団なのか
- 結局LTは10分近く……
懇親会で萩本さんから、「御社の偉い人にも今回と同じような話する機会があったよ、結構感銘を受けてた(意訳)」と聞き衝撃を受けた。多分ホントにエライ人しかしらないんじゃないかなぁ。
ともあれ、萩本さんがFacebookで要求開発アライアンスの資料も公開(要求開発の発展と展開、そして課題)されています。BPStudyの資料もアップされるとの事だった。これ読んで下から突き上げてみようかなぁ。