Redmineのデスクトップクライアント的なものをnode-webkitで作った②

前回の記事はこちら

Redmineのデスクトップクライアント的なものをnode-webkitで作った - suzan2号の戯れ

なんか凄い時間が立ってしまいましたが、チケットを表示・修正する機能をつけました。

suzan2go/RedNodeKit · GitHub

My Ticketsのタブから、現在自分に割り当てられているチケットの表示・更新ができます。
f:id:suzan2go:20141125002429p:plain

スマホアプリのように下にフックすることで更新もできます。
f:id:suzan2go:20141125002452p:plain

これにはhook.jsを使わせてもらいました。
本当にすごーく簡単にhookでの更新ができるようになりました。

jordansinger/Hook.js · GitHub

チケット一覧の画面でチケットをクリックすると、詳細な情報を表示できます。
f:id:suzan2go:20141125002603p:plain
更新履歴も出してますが、ステータスやメンバーの変更はidで表示されちゃいます。今後なんとかします。
f:id:suzan2go:20141125011439p:plain
以下、編集画面です。メンバーの変更とか、期日の変更とかステータスの変更など簡単な変更をここにすることを想定してます。注記に変更時のコメントを書く感じです。
f:id:suzan2go:20141125002608p:plain

更新したところ

前回の記事のあと今まで自分しか見てなかったんじゃね??というこのブログに200人以上が来てくれたりして、よっしゃー頑張るぞ!!となってたんだけど、仕事のピークも重なってしまい1ヶ月弱立ってしまいました。この3連休と先週末頑張ってやっと使って貰えそうなもんができました。

  • できるようになったこと
    • 自分が担当者のチケットをtwitterアプリ風(今は更新するとこだけだけど…)に表示する。
    • チケットを編集する
  • まだ出来ないこと
    • 自分が担当者のチケットが作成されたら通知する(でもコレは結構しんどい)。
    • 更新履歴の内容をちゃんと表示する(現在はメンバー変更も1とか2とかidで表示されてしまう)

ハマった点

あとはどこにはまったというより、自分のアプリ設計的なスキルの無さからくるものなんですが、ここもう少しうまく書けないかなぁーと色々と書きなおして結局スパゲチーに書いていたら時間がかなりかかっちゃいました。
rest.jsにチケットの取得・登録のrestをまとめてるんですが、いちいちajaxを毎回書いたりするし、restでデータ登録するとこはまとめてても、結局個別にhtmlのscript要素に似たようなコード沢山書いてしまったり。一回一からリファクタリングしたいと思ってます。javascriptデザインパターン的なものを勉強したい。

Redmineのデスクトップクライアント的なものをnode-webkitで作った

画面イメージ

f:id:suzan2go:20141103170647p:plain
f:id:suzan2go:20141103170642p:plain

api keyというのはredmineの個人設定ページ、右側にあるやつですね。
ちなみにapi keyを入力していないと、実行時にuser/パスワードを聞かれます。
f:id:suzan2go:20141103164612p:plain

githubにあげました。

suzan2go/RedNodeKit · GitHub

何故作ったか

この前、社内でnode-webkitを使った社内SNSのクライアントソフト(twitterのクライアントアプリ的なもの)を作ってる人を見かけ、自分もnode-webkit(初めて知った)を使って何か作ってみたくなりやっちゃいました。
作成したのはredmineをデスクトップアプリケーションから弄るツールです。名づけてRedNodeKit(redmine + node-webkit)。node-webkitとbootstrapで作りました。node.jsの機能なんて使わんかなーと思ってましたが、ファイル入出力とか簡単にできて結構便利ですね。

  • できたこと
    • rednodeからチケットを登録する
    • プロジェクトや担当者、トラッカーはredmineから自動で取得する
  • できなかったこと
    • 自分が担当者のチケットをtwitter風に表示する。
    • 自分が担当者のチケットが作成されたら通知する。
    • チケットを編集する

チケット登録しか出来ねえじゃねえか!という感じですが、忙しい上司などredmineをブラウザで開くことさえしてくれない方に気軽にチケット登録してもらうには良いのかなと。評判が良かったら機能を拡充させていきますので何卒…

ハマった点

箇条書きですが、ハマったところ。

  • node-webkitだとhtmlのjavascript要素とnode.jsのjavascriptが混ぜ混ぜに書けちゃうので、どっちも素人の自分からするとWEB上のサンプルコード見てもこれどっちなんだろう…となる。
  • node.jsからファイルを呼び出す/書き出す場合と、javascriptから読み出す場合でパスが違う場合がある。例えばファイルを読み込むときはjsファイルからの相対パスなのに、書き出すときにはnode-webkitを実行したところからのパスになるとか。(同じファイルに対して読み込むときと、書きだすときでパスが違う。きちんと試したわけではないので要検証)
  • ctrl + c 、ctrl + vとか基本的な機能が使えない!調べても出てこない!自分で実装しなければいけないの?となった。Macの場合はウインドウの一番上に出てくるネイティブメニューバーを表示させる設定にしないと、アプリ共通のctrl + zとかが使えないみたい(デフォルトは非表示)。

node.jsそのものよりもbootstrapでこれどーやればいいんだー!とか動かねー!となっていた時間の方が長かった気がする。

githubについて

今まで登録だけしてたんですが、初めて自分の作ったものを上げてみました。何か凄くドキドキしてますわ。初めてニコ動に動画を上げたときみたいな感じ。少しでも何か反応があると嬉しいなーと期待してます。色々上げてみようっと。

redmineで進捗率をステータスに連動させた場合でも、親チケットのステータスは小チケットの進捗率に連動させる方法

いま自分のグループのredmineの管理者をやっているのですが、進捗率ってみんな変えてくれないですよね。入れてくれても人によって進捗率の考え方がバラバラだったり。そこでチケットのステータスに応じて(対応中とかフィードバックとか)進捗率を自動で変えられるプラグインとかないかなーと思っていたのですが、実はプラグインではなくデフォルトの機能で実現できます(自分は1時間くらいプラグインがないかググっていました…)。以下は少し古い記事ですが、redmine2.5でも同様の設定が可能です。
小技(0.9): チケットのステータスで進捗率を更新する | Redmine.JP Blog

チケットの進捗率をステータスに連動させた場合の弊害

ただし進捗率をステータス連動にさせた場合は、通常小チケット全体の進捗率に連動して自動で計算される親チケットの進捗率も、親チケット自体のステータスに連動して設定されてしまいます。以下の小チケットを4つ持つチケットで考えてみましょう。

チケット
 >小チケット1:進捗率100%
 >小チケット2:進捗率100%
 >小チケット3:進捗率100%
 >小チケット4:進捗率0%

この場合の親チケットの進捗率は以下の様になります。

チケットの進捗率がステータス連動でない ⇛ 75%
チケットの進捗率がステータス連動 ⇛
 小チケットの進捗率に関わらず、親チケットのステータスによって決まる。

自分のとこのredmineもそうなのですが、小チケットを多用してプロジェクトの管理をしている場合、親チケットの進捗率は小チケットの進捗率と連動してた方が見栄えが良いですよね。親チケットのトラッカーを分ける(このトラッカーにはステータスに応じた進捗率を設定しない)ことで、親チケットの進捗率だけ小チケット連動にすることもできますが、自分はもっとシンプルに実現したかったのでredmineのソースを弄ってみることにしました。

2014年10月19日 ソースが会社のサーバの中なので、続きは別途書きます。
2014年11月1日 追記(大分遅くなってしまった…)

細かく書こうと思ったけどだるいのでdiffを貼り付けます。
変更したのは${redmine_home}/app/model/issue.rbの中身変更。
進捗率(=done_ratio)に関する部分の処理条件に、「小チケットを持たないこと」を追加しました。
(children?で小チケットを持つか否か判別できる。
http://www.rubydoc.info/github/edavis10/redmine/Issue
)

今のところ特に不具合などは出てないですが、変更するなら自己責任で。
本当はこういうのもプラグインで実現するべきなんだろうか?
というかプラグインでこういう中身の処理までいじれるのかしら?

@@ -547,7 +552,7 @@
   private :workflow_rule_by_attribute
 
   def done_ratio
-    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
+    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio && !self.children?
       status.default_done_ratio
     else
       read_attribute(:done_ratio)
@@ -629,7 +634,7 @@
   # Set the done_ratio using the status if that setting is set.  This will keep the done_ratios
   # even if the user turns off the setting later
   def update_done_ratio_from_issue_status
-    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio
+    if Issue.use_status_for_done_ratio? && status && status.default_done_ratio && !self.children?
       self.done_ratio = status.default_done_ratio
     end
   end
@@ -1352,7 +1357,7 @@
       end
 
       # done ratio = weighted average ratio of leaves
-      unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio
+      unless Issue.use_status_for_done_ratio? && p.status && p.status.default_done_ratio && !p.children?
         leaves_count = p.leaves.count
         if leaves_count > 0
           average = p.leaves.where("estimated_hours > 0").average(:estimated_hours).to_f

PowershellのInvoke-RestMethodをhttpsに実施すると失敗する

PowershellInvoke-RestMethodでhtppsのuriにRESTしようとしたらはまったのでメモ。Invoke-RestMethod自体はかなり便利でちょっと感動したので、前半はその紹介です。

Invoke-RestMethod

Powershell3.0からInvoke-RestMethodが追加され、WindowsからもLinux系でいうCurlのようなことができるようになりました。最近PowershellInvoke-RestMethodを使ったスクリプトを書いたのですが、json形式のデータをRESTで取得してゴニョゴニョするのはLinuxからCurlよりもはるかに簡単だと思います。
例えば、RESTで以下のようなjson形式のデータを取得する場合は、

{"name":"John","age":"25"}

こんな感じで書くことができます。

>$var = Invoke-RestMethod -Uri http://xxxxxx/api/userlist -Method Get
>echo $var.name
John

jsonのデータはPowershell側で勝手にパースしてくれます。Linuxからbashでやろうと思うとcurlでとってきたものをawkして…とかやらないとだめですが、Powershellなら不要です。

httpsのURLにInvoke-RestMethodをする場合の注意点

自分はこれで結構はまってしまいました。問題の切り分けができなくて半日くらいかかったと思います…
具体的にはInvoke-RestMethodのurihttpsで、かつ相手のSSLサーバ証明書が自己証明書の場合には以下のようなエラーが起こります。私の場合は内部の管理サーバ(自己証明書)に向けてInvoke-RestMethodしてたのでエラーになりました。

 Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
 At line:8 char:11

ググってみると以下のようにすればOK!と結構いろいろなところに書いてありますが、これだけではダメでした。

 [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

実際にこの状態で実行すると以下のようにエラーの表示が変わるだけ。

Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send. 

さらにググるとこんなページが!この人、自分とまったく同じ状況やんけ!

.net - Powershell v3 Invoke-WebRequest HTTPS error - Stack Overflow

結局、解としては以下のようです。

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

httpsの場合にはSSLサーバ証明書のチェックをしていて自己証明書の場合は弾くのがデフォルトのようです。
上のコードではCertificatePolicyの「CheckValidationResult」メソッドを上書きして無条件にTrueを返すようにしている…といった感じでしょうか。上記をスクリプトに追加したところhttpsでも問題なく動作するようになりました。

paizaに挑戦してみた

最近ではもうあんまり仕事でコードを書くことがなくなって寂しい限りですが、今の自分の実力がどんなもんか試してみました。
ITエンジニア・プログラマ向けの転職・就活・学習サービス【paiza(パイザ)】


最初はmac付属のvimで書いて、その後emacs、結局eclipse立ちあげて挑戦。というか久しぶりにemacs使うとショートカット全然覚えてないっすね…大学のときはeclipseのショートカットもemacsに合わせてたのに。

全部javaで挑戦したのですが結果はBでした!
上位30%の「一定基準以上のスキルを持っています。多くの企業で書類選考なしにカジュアル面談、面接へ進めます。」らしい。Aランクも1つ挑戦したんだけど、難しいっすね。何か高校入試の数学解いてる感じですわ。アルゴリズムという名の解法を知っていないと解けないというか何というか。大学の専攻が情報系じゃないだけに、その辺りの知識がないんですな。
Bランクでもスカウトが来るかしら…ひとまずAランク目指して頑張ろうと思います。久しぶりにプログラミングすると脳汁出まくりますね。初心者みたいなこと言いますけど、頭のなかで動きを組み立てて、コードにして動いたときのキタコレ感やばいです。

もっと会社でプログラミングしたいなぁ。クソみたいなエクセルファイル間の整合性取る仕事とか、実機のミドルのGUIから値コピペして集計する仕事とか、全部システム化したい。DBサーバ立てて値を入れていって集計のときにSQL書けば一瞬で終わる仕事を、エクセルファイルに値を入れていってさらにそれをマクロで…なんてことしてるから、みんな雑務に追われてるんだと思う。明治生命かどこかの社内PaaSとか本当うらやましい。結局サーバ個別に立てるとその運用が〜とかISOが〜とかなってしまうからなぁ。

Windows7にknife-solo + vagrant環境を作成しようとして疲弊した話

会社でchefを紹介することになり、knife-solo + vagrant環境を構築しようとしたのですが、細かい所で動かなくて大分疲弊しました。(このご時世にもchefのcの字も知らない同僚が多いのがSI企業の辛いとこです…)

結局諦めて、Windows上にChef用のCentOSとテスト用のCentOSを立ててしまったので、成功パターンではないのですがこれはダメだったというアンチパターン?ということで。

環境は以下となります。

  • Windows7 32bit
  • vagrant 1.6.3
  • knife-solo (失念しましたが2014/8/22の最新番)
  • VirtualBox  4.3.4 → 4.3.14(インストールがうまく行かず) → 4.3.12

やりたかったこと

  1. powershellからvagrant ssh (これはまあできた)
  2. powershellからknife solo cook <hostname>  ⇐これがどうしてもできなかった

要はChef実践入門の序盤のお試し環境Windows上で実現したかったわけです。Windowsでこれを実現するには、powershellから rsync + sshが実行できることが必要となります。私の場合はrsyncがどうしても動作してくれず、断念しました。

cygwin + knife-solo + vagrant 

「knife-soloはcygwinrsyncを使うこと前提にコードが書かれている」という話を聞いていたので、なら最初からそうしよう!と思ってチャレンジしたのがコレ。しかしながらsshもできなければ、rsyncも動作しなかった。sshvagrant以外の普通のサーバにも試してみたが、「Socket operation on non-socket」(だったと思う)が出てNG。当然、knife solo bootstrap <hostname>も knife solo cook <hostname>もダメでした…

mingw + knife-solo +vagrant

以下のサイト様を参考にして挑戦しました。

嗤うプログラマー: Windows に Vagrant + knife-solo環境を作る手順 2014年4月版

ちなみに最初に挑戦したのはこちらなのですが、どうしてもmingwGUIからパッケージがインストール出来なかったため一旦断念。どうやらどうも社内の認証プロキシに引っかかっていたっぽいです。GUIからではインストールできなかったのですが、powershellからmingw-getを実行することでプロキシの認証画面がポップアップ画面で表示され、問題なくDLできることを確認できました。

mingw-get install msys-openssh
mingw-get install msys-rsync

 環境変数mingw、msysのパスを通し、

vagrant ssh

つながった!

次に、knife-soloを実行するためにvagrantssh設定をpowershellで書き出します。

encoding -defaultを設定しないUTF16で書き出されてしまい、盛大に文字化けするので注意。

vagrant ssh-config --host <hostname> | out-file C:¥Users¥<User>¥.ssh¥config -encoding default

 ちなみにmingwssh自体はwindowsの$home配下を見に行ってないようなので、ssh <hostname>は上記では失敗します。以下のようにmsys-opensshのssh_configに設定を書き出す必要があります。

vagrant ssh-config --host <hostname> | out-file C:¥MinGw¥msys¥1.0¥etc¥ssh¥ssh_config -encoding default

上記設定の是非は別として、これでssh <hostname>でログインできました。

続いてvagrant上のVMにchefをインストール 。なんか最後、エラーが出てる気がしたが気にしないぜっ!

knife solo bootstrap <hostname>

ちなみにプロキシ環境では、vagrant上のVMに先にプロキシ設定を入れて置く必要があります。自分は/etc/environmentに以下の設定を通して、souceしました。

  • export http_proxy=ほにゃらら、export https_proxy=ほにゃらら
  • source /etc/environment 

そしていよいよknife soloを実行する!

knife solo cook <hostname>

しかし、rsyncがどうしても動かない!!というかbootstrapのときに出てたエラーもrsyncについてでした。

エラーメッセージを見ると、「Failed to dup/close」とのことですがGoogle先生に聞いても良く分からない。以下、ネットの成功パターンを見て自分が試したこと。

  1. cygwinrsyncを使う
  2. cwRsyncを使う(MinGWからrsyncを一旦アンインストール)

cwRsyncの中身はcygwinの一部っぽいので2つを試す意味は無かったような気がしますが…まあ結果はダメでしたよ。

丸2日ほど試行錯誤したあげく(VirtualBoxのバージョン変えたりしました…)、結局断念してWin上にVirtualBoxCentOSを二台立て、一台をknife-solo実行用、もう一台をvagrantで管理するテストVMという逃げ回避索をとりました。

上記のブログの方も書いていましたが、おとなしくChef環境をVMに立てるのがWindowsの場合はいいかもですね。あぁ会社でMac使いてえ。

Win PC上のVMware Playerに立てたESXiと、別筐体のESXiサーバをタグVLANで接続する

 会社でどうしても物理サーバが2台用意できず、物理サーバ上で構築したESXiサーバと、Windows PC上のVMware Playerに立てたESXiサーバで仮想化環境を構築しようとしたらタグVLANでハマった話。

構成はこんな感じ 

f:id:suzan2go:20140818223731p:plain

  • VMware PlayerのNW設定はブリッジ接続。
  • ブリッジ接続したWindows7上のnicipv4ipv6ともオフにする。

物理ESXiサーバ上に構築したvCenterからWinPC上のESXiサーバがどうしても見えない。タグVLANを辞めてポートVLANにすると接続できるので、タグVLANがうまくVMware Playerまで届いていない様子。

VMware Player上の設定を色々変えてみたりしたのですが、原因はWindows側でした。どうやらOS + NICの組み合わせによってはVLANタグを引っぺがしてOSに渡してしまうようです。以下のサイト様を参考にタグVLANをひっぺがさないようにしたところ、タグVLANで問題なく通信できるようになりました。

Wireshark + Intel NIC で tagVLAN の VLAN-ID を含めてキャプチャする方法 - ..たれろぐ..

Web系雑記: RealtekのNICでタグVLANのタグをパケットキャプチャで確認する

 

ブリッジ接続しているからVMware PlayerまではちゃんとタグVLANのパケットがながれているはず!と思い込んだため、解決まで結構時間がかかってしまいました。

VMware Playerでブリッジ接続にしていても、パケットをそのままVMware Player上の仮想マシンに流せるわけではないのですねー。勉強になりました。