GradleでEclipseプラグインをビルドする
Eclipseプラグインを作り続ける人もいる、このロクでもない世の中に向けて。
基本的には下記を参考に。 mikamikuh.hatenablog.com
自分の環境で実行したら、META-INF/MANIFEST.MFファイルが、Gradleがjarタスク実行する時に自動生成するMANIFEST.MFに置き換えられてしまっていた。
ので、jar.manifestの設定で、Eclipseが生成するMANIFEST.MFを出力するよう指定した。
Eclipseプラグインフォルダをどう指定するかが悩みどころ。
ちゃんとやるなら、Gradleのwuffプラグイン(Maven TychoのGradle移植)を使うべきだろうけど、社内プロキシに阻まれてインストール出来なかったので、簡易的にコッチでも大丈夫かな?(まだHello Worldプラグインでしか動作確認していない)
[フェス] サマソニ予習用サービスを作りました
紹介
コレは何?
最近のセットリストから、ライブで演奏しそうな曲を調べるもの。
フェスで知らないアーティストいっぱいですが、定番曲ぐらいは知っておきたい時にどぞー。
検索窓つけてますが精度が悪く、検索結果が無い場合が多いです。
「Mastodon」なら検索できるはずです(サマソニ関係無い)
どんなもの?
setlist.fm - the setlist wiki というものがあります。
これは、登録したユーザがライブで演奏したセットリストを書き込んで共有するサービス。
setlist.fmのAPIを叩いて、最近のセットリストからよく演奏している曲を探しています(単純に加算してパーセンテージ出してるだけ)。
よく演奏している曲の動画をYouTube Data APIを使って、ページに埋め込んでいます。
もっと詳しく
使ってる技術
使用しているAPI
-
- アーティスト名からMusic Brainz IDというものを取ってきます
- 22 req / 20 sec など制限があるようです
-
- Music Brainz IDを元にセットリストを検索します
-
- 「アーティスト名 + 曲名」で検索して、一番先頭の動画をページに埋め込んでます
心残り
いっぱいあります
Music Brainzの検索精度
結構辛いです。
例えばMUSE。 Search Results - MusicBrainz
Fuji Rockにも来る、UKバンドのMUSEが来て欲しいところですが、そのMUSEはスコア 98 で、他にスコア 100 のグループが5つヒットします。
どういう基準でスコアが付けられてるのかよくわかりません。
また、コレが辛いところですが、同じアーティストのIDが2つあることがあります。
斉藤和義 - MusicBrainz
斉藤和義 - MusicBrainz
酷いことにMusic Brainzの検索で見つかるIDとsetlist.fmで保持してるIDが別物ということもあり、悲しい思いをしました。
IDと言ったな。アレは嘘だ。
最初はサマソニのサイトのHTMLから自動で~ってのを考えてましたが、結局半分ぐらいは手動検索でMusic Brainz IDを探してました。
音楽関係のサイトが全てMusic Brainz IDベースになれば、もう少し精度上がると思うんだ。
setlist.fm のコンテンツ
ユーザベースのサービスということもあり仕方ないことですが、セットリストの登録が少々残念です。
特に日本のアーティスト。
BABYMETALやDIR EN GREYなんかの海外でも話題のアーティストについてはちゃんと登録がありますが、サマソニの出番的にBABYMETALより格上のRADWIMPSなんかは寂しい感じ。
音楽好きにはなかなか良いサービスだと思うので、もう少し日本でも流行って欲しいです。
D'ANGELO AND THE VANGUARD
シングルクオートのせいでJSONが壊れるのでやめてください
おわりに
フジロックのメニューも作ろうとしたけど、HTML見るとヘッドライナークラスがimgタグのロゴ表示しか無いので萎えました。
altぐらい…
commandモジュールがパイプを使えないことを経験した
という話。
LibreOfficeインストール用のPlaybookを書いてる時に、複数のrpmファイルをlocalinstallする必要があったので、こんなタスクを書いた。
- command: find LibreOffice_{{ detail_version }}_Linux_x86-64_rpm/RPMS/ -name *.rpm | xargs yum -y localinstall
エラーになった。
TASK [command] ****************************************************************** fatal: [192.168.33.14]: FAILED! => {"changed": true, "end": "2015-06-08 09:53:27.678648", "stdout": "", "cmd": ["find", "LibreOffice_4.4.3.2_Linux_x86-64_rpm/RPMS/", "-name", "*.rpm", "|", "xargs", "yum", "-y", "localinstall"], "start": "2015-06-08 09:53:27.662475", "delta": "0:00:00.016173", "stderr": "find: paths must precede expression: |\nUsage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]", "rc": 1, "invocation": {"module_name": "command", "module_args": {"_raw_params": "find LibreOffice_4.4.3.2_Linux_x86-64_rpm/RPMS/ -name *.rpm | xargs yum -y localinstall"}}, "stdout_lines": [], "warnings": []}
findの-name
オプションの引数 *.rpm
をダブルクオートで囲ってないのが原因だと思って調べまくってたけど解決できず、ようやくcommandモジュールにパイプやリダイレクト等を使用できないことを知る。
ansibleでshellやcommandを使う時の注意点 - Qiita
commandモジュールじゃなくてshellモジュールを使えばいいだけだった。
- shell: find LibreOffice_{{ detail_version }}_Linux_x86-64_rpm/RPMS/ -name *.rpm | xargs yum -y localinstall
shellモジュールの方が出来ること多いから、commandモジュールいらなくね?って疑問に言及しているエントリを見つけた。
Ansibleのshellモジュールとcommandモジュールの使い分け | bacchi.me
shellモジュールは記述されたコマンドを/bin/shで実行するけど、commandは違うよという話。 ほんまかいな。
まぁ、使えるコマンド制限されてたほうがセキュリティ的に頑丈だよねってことだろうか。
shellモジュールとcommandモジュールの違いが気になってきたのでソースを見てみた。 (結果は、よくわかりませんでした)
ansible/mod_args.py at 5622fc23bc51eebde538b582b5e020c885511f31 · ansible/ansible
shellモジュールが使われてる場合は '_uses_shell' フラグを True にして、アクション名をcommandに書き換えている。 ということは、shellもcommandも同じ動きをする?
'_uses_shell' が使われている箇所を調べるためにansible-playbook実行した時のトレースを見てみる。 Python スクリプトの動作をトレースする - とあるSIerの憂鬱
[vagrant@localhost ~]$ python -m trace --trace /usr/local/src/ansible/bin/ansible-playbook -i hosts pptgallery-playbook.yml --ask-pass | grep '_uses_shell' SSH password: mod_args.py(125): args['_uses_shell'] = True
設定されてるだけで使われてなかった。。。
とりあえずここまで。
蛇足
来日行こうか迷う。
fluentd-plugin-lets-chatを作った
fluentdのプラグインを作るために色々調べたので備忘録。
背景
Gitbucketを遊びで使ってて、Gitbucketの飛ばすWebhookをLets Chatに飛ばしたかった。
- Let's ChatのREST APIではリクエストパラメータのJSONの中にtextフィールドを持ってなきゃいけない
- Messages · sdelements/lets-chat Wiki
- => なので、textフィールド付きでリクエストするOutputプラグイン書いた
- fluentdに対して `json={}` でない形式でデータを送った時に、fluentdのin_httpプラグインだと解析してくれない(ように見えた)
- Gitbucketの飛ばすwebhookの内容が大量なので、必要な情報だけをフィルターかけてLets Chatに飛ばしたかった
こう書くとFilterプラグインが必要そうだけど、Filterプラグインの使い方がいまいち掴めなかったので、InputプラグインとOutputプラグインでほげほげしてる。
調べたこと
Fluentdプラグインの書き方については下記を参考にした。
fluentdのためのプラグインをイチから書く手順(bundler版) - たごもりすメモ
- 自分の環境(Ruby2.0.0)では、上記のやり方に加えて development_dependencyに test-unit を追加する必要があった。
途中、プラグインをインストールしているはずなのに、Fluentd(td-agent)がプラグインを見つけてくれない問題が起こった時には、下記サイトのやり方で原因を見つけた。
Fluentdの自作プラグインがロードできないのでソースの中身を追ってみる… - kk_Atakaの日記
HttpInputプラグインを拡張するやり方、およびテストの書き方については fluent-plugin-heroku-syslog を参考にした
また、本家のin_http.rbなども参考にした。
おわりに
Let's ChatはUIもモダンな感じだし、簡易的だけどREST APIも付いてるので自分でホストできるチャットツールとしては優秀だと思う。
SlackやらHipChatを使える人はそっちで十分だと思うけど、色んなしがらみによって外部ツールが使いづらいひとは試してみてはどうでしょう(主にSIer方面)。
Fluentプラグインはコード量が多くならないし、Github見ればいくつもサンプルが転がってるのでコーディング方面ではあまり躓かないけど、どういう動きをしてるのかを掴むまでは辛いものがあった。
まぁ、そこら辺はFluentdのコード読めな話なので精進が足りなかったということで。
蛇足
Royal Thunder良い。
ログインフォームを使ってログインするようなページへのアクセ
Go-lang勉強。
ログインフォームのあるようなサイトにGo-langのhttpパッケージを使ってログインする。
ログインしたいのは Log in - Swipe。
フォームの情報送るにはPostForm使うと楽っぽいけど、今回は
- リファラを設定しないとログインさせてくれない
- cookieJar使ってログイン情報持ち回りたい
という背景があったので、PostFormだと上記が満たせない感じ。
なので、Request作ってフォームの情報はbodyに流し込む下記のような方法で。
package main import ( "net/http" "net/http/cookiejar" "io/ioutil" "bytes" ) func main() { cookieJar, _ := cookiejar.New(nil) client := &http.Client { Jar: cookieJar, } // Login to swipe.to var str = []byte("Email=hogehoge%40example.com&Password=foobar") req, _ := http.NewRequest("POST", "https://www.swipe.to/login", bytes.NewBuffer(str)) req.Header.Set("Referer", "https://www.swipe.to/home") req.Header.Set("Content-Type", "application/x-www-form-urlencoded") res, _ := client.Do(req) // Create New Doc req2, _ := http.NewRequest("POST", "https://www.swipe.to/edit/create", nil) req2.Header.Set("Referer", "https://www.swipe.to/home") res2, _ := client.Do(req2) body, _ := ioutil.ReadAll(res2.Body) defer res2.Body.Close() println(string(body)) }
なんか勘違いしてる感が拭えない。
社内勉強会でGradle布教活動をしてきた
結果
「Gradle使おうぜ!」 => 失笑
資料
次のステップとして、今のプロジェクトがEclipseな感じなので、akhikhl/wuff をベースにTychoとかOSGI周りとか良いかもしれない
compare-gradle-buildsプラグインについて
Gradle in ActionやGradle徹底入門で紹介されてて気になったので触って見てる。
checkstyleの設定ファイルが違った時にどのぐらいチェック結果が変わるのかを見れるかと思ったが、現在のバージョンだとZipアーカイブの比較しか出来ないっぽい。
64.2.2. Supported build outcomes Only support for comparing build outcomes that are zip archives is supported at this time. This includes jar, war and ear archives. Future versions will provide support for comparing outcomes such as test execution (i.e. which tests were executed, which tests failed, etc.)
今後に期待。
しかし、GradleないしGroovyは今後大丈夫だろうか。。。
Groovy 2.4 And Grails 3.0 To Be Last Major Releases Under Pivotal Sponsorship | Pivotal P.O.V.
ちなみに、compare-gradle-buildsプラグインでの比較時にデフォルトで実行されるのは
gradle clean assemble
だが、実行するタスクを変更するにはホストに下記のようなbuild.gradleを書けば良い。
apply plugin: 'compare-gradle-builds' compareGradleBuilds { sourceBuild { projectDir "Hoge" tasks = ["hoge","check"] } targetBuild { projectDir "Fuga" tasks = ["check"] } }