appveyorで、.NET Core を試してみた

ご無沙汰しております。
Blog存在半分忘れかけておりました。
書きたくないわけでもなく、書きたい気持ちはありつつもなかなかタイミングがなかったというところで、実は、取り組んでいるものに節目がうまく出ていないのも一つかなというところです。
その場その場のことを書いていけるようにしていけたらいいのかなとか考えているところです。

というところで、本題です。

経緯

実は、.NET Coreでの開発をしていて、ある程度の規模になってきたときテストコードを自分のところで実行したり、dotnet packでnupkgを作るということをやりたいなと。ただ、継続的インテグレーションを構成したいと考えてましたところ、6月よりちょっと前だと、対応したと目立った情報もなく結構厳しいのかなと思ってました。毎回、手動で実行していければいいのですが、忘れたりまた、テストの結果が見えるようにできていないというのも、何か不透明な感じで面白くないなーと。
最近、@jsakamotoさんより、「appveyor」は「dotnetコマンドも使えるかも!?」と教えていただきまして、試してみました。

結論

使えたー!

設定したこと

既定ではslnファイルを読み込んでうまいことやろうとしてくれますが、
これだとテストも自動的に含まれてしまったり、うまく動作しなかったりとしたために、dotnetコマンドに置き換えました。

最初に、github上からAppVeyorのプロジェクトを作成しました。

  1. 左側リストのGeneral.プロジェクト名の設定 – ProjectName
    Bjd.xxxx
  2. 左側リストのGeneral.ビルドバージョンの設定 – Build version format
    1.0.{build} → 1.0.0-{build}
    ※気持ちの問題
  3. 左側リストのEnviromentは特になし
  4. 左側リストのBuildで、MSBUILDとなっているものをCMDに変更
    dotnet restore
    
    dotnet build Bjd.xxxx -c Release

    としました。

  5. 左側リストのTestで、「Script」「CMD」を選び、Buildと同じようにdotnetコマンドをdotnet test Bjd.xxxx -parallel all -maxthreads 3としました。オプション「-parallel all -maxthreads 3」はXunitに対するオプションです。並列化を有効にして最大スレッド数を設定してますが、設定しなくても動きます。BlackJumboDogでは、テスト実行にもSocket操作・サーバー動作を伴うとか、テスト実行時間が長くなりすぎないようにと考えたすえ、最大数を調整しました。
  6. Badgeの設定
    といっても、リンクをどこかに張り付けるだけです。私はGitHubのreadme.mdにはっつけてみました。
 
 なんか、それっぽい!という気持ちと、いまだにBjd.WebServer.CoreCLR.Testがpassingになったことはない!という現状を報告しておきます。

そのほか

これは、おどろいたことです。わかる人にはわかるとは思いますが、実はpathにperl.exeがいるらしく、cgiのテストが動作しました。
テストのタイムアウトは60分。普通のテストではそうそう、問題にならないような気がしますが、開発機のスペックと同等だと思わないほうがよいかと思います。テストを並列実行してる場合、コア数の違いで、実行時間がそのまま倍になったりしました。体感的に手持ちのSurfacePro4と同じくらいでした。
Slackへの通知もできます。ビルドの結果くらい通知しておくと、Commitの重みを感じつつ励みになります。(passingなら)
また、余談ですが、サーバーのスレッドが停止しないためにテストが終わらずに60分のタイムアウトを経験できたことは伏せておきます。
開発する環境以外での動作は思ったより大変な部分もありましたが、GitHubにプッシュするだけで、自動的にビルド、テストと動く環境があることで、リポジトリの状態を見えるようにできたことは、ぱっと見るだけで、状況を把握できて面白いかなーと思った次第です。

感謝

@jsakamotoさん、情報ありがとうございます!

オープンソースカンファレンス2016北海道にCLR/Hとして登壇させていただきました

こんばんは!

先日 6/18(土曜日)にオープンソースカンファレンス2016北海道がありました。
そこで、CLR/Hとして登壇させていただきましたので、報告レポートです。

「BlackJumboDog」+「.NET Core」で何かやってくださいとのことで
はじまりました。最初はテーマから悩んでましたが、CLR/Hの方と相談して決めたテーマがこれでした。

「Mac でも Linux でも動く! C#製ネットワークサーバーアプリ BlackJumboDog を .NET Core 上に移植した話 」

ということで、.NET Core、BlackJumboDog、クロスプラットフォーム、C#を全面に出したものでした。とはいえ、まだまだ正式リリースされたものでありませんので、
こういうものです!とも言えない状態でした。(当時はRC2さえもリリースされていなかった)

セッションは、BlackJumboDogとは?から始まり、.NET Coreを選んだ理由ということで、私の個人見解を最初に。実際のところ、RC2で劇的な変化があったために動かなくなった話も混ぜつつ、実際の動く環境のデモをさせていただきました。

特に、実際に動くということは大きな意味がありますし、テーマ・タイトルのMac Linuxはもちろん、Dockerというコンテナ仮想化で動くというのは、新しい形でのデプロイメントに何か可能性を感じます。このDockerでの実行開始までの速度が1分どころか、30秒かからないのは私自身驚いたことでもありました。

以下セッションの資料を公開してます。

ソースコード:githubDockerHub

なお、ソースコード、Dockerのイメージはその特性上、サーバーとして悪用されてしまう可能性もありますので、インターネットなど公開した状態で放置にならないようご注意くださいませ。UIが未実装であるため、すべてのサーバーがデフォルトで稼働するようになっております。

CLR/Hのみなさんのおかげで、セッションは無事に終了いたしました。資料の反響がものすごく驚きましたが、この.NET Coreに寄せてる期待は大きいものがあるのかなと感じます。考えていること目指していることがどこまで実現されるかはわかりませんが、.NET Standard Libraryが登場し、.NET Core App、ASP.NET Core App Xamarinなどの標準として動くようになっていけば、WebApp、コンソールアプリケーションに限らない世界が見えてくるかもしれないと期待しています。

BlackJumboDogでは、まだまだ完成したとはいえない状況ですので、継続して開発していきます。特にどこかのLTでも煽られておりますので、WebUIは・・・ASP.NETCoreで実装できないか・・・と妄想はしてます。

実はデモの50%はMicrosoft Azureの成分ができてましたので、そこも後々メモしておきます。

#もうちょっとBlog更新しよう

新しいdotnet-core(RC2)を味見したい人に!

おひさしぶりです。気付けば、1か月更新してませんでした。

今日は、de:codeに向けて「.NET Core」を「予習」「味見」したい人に向けて、私なりにVisualStudioで、利用可能になる方法を紹介します。

大まかにこんな感じ

0.事前準備.VisualStudio 2015 Pro程度ものが入った環境を用意する(たぶんcommunityでもいけるとは思う)

1.NuGetのリポジトリを追加します。

2.プロジェクトを用意します。

3.project.jsonを書き換えます

4.随時動かす!

 

NuGetのリポジトリを追加

  1. 開発のビルドリソース – dotnet-core .NET Core “dev” builds
  2. リリース向けのリソース – dotnet-core-rel Feed for the dotnet-core packages that we plan to release and publish to nuget.org

 

名前は適当に、ソースのURLは、上記リンク先から下記の部分を利用します

※VS2015は上。

プロジェクトを用意します

新しいプロジェクトの作成ですね。

何かかきます。とりあえずコンソールなので、、、

グレイトなメッセージを出力!テンションあがるねっ

 

project.jsonを書き換え

dnxのみにして、しまいます。こうすると.NETFrameworkでは動作しなくなる。

Devはちょっと修羅なので、リリース候補のrc2にしてみました。

保存で、パッケージが復元されます。あとは、実行!

れこそグレートなメッセージ!!!・・・化けたよ。

こんなときは、慌てずに中身を覗いてみましょう。

            Console.WriteLine(Console.Out.Encoding.WebName);

というわけで、エンコードがutf-8となっているために、コンソールはShiftjis。

なので化けたのだということですね。

そこでproject.jsonに以下を追加

        "System.Text.Encoding.CodePages": "4.0.1-beta-23516"

さらに、メインも以下のように

        public static void Main(string[] args)
        {
            Console.WriteLine(Console.Out.Encoding.WebName);

            // 標準出力の取得
            var s = Console.OpenStandardOutput();

            // コードページの取得
            var e = System.Text.CodePagesEncodingProvider.Instance.GetEncoding(932);

            // エンコード付きのストリーム
            var w = new System.IO.StreamWriter(s, e);

            // これを忘れると・・・すぐに出力されなくなる
            w.AutoFlush = true;

            // 設定
            Console.SetOut(w);

            Console.WriteLine(Console.Out.Encoding.WebName);
            Console.WriteLine("てすとめっせーじ");
            Console.Read();
        }

実行!

となりました!

とはいえ、この問題は公式なNuGetから落とせるものでも発生しますので、特別RC2がというわけではありません。

試行錯誤しながら、メンバーを眺めてみたりとすることもできるということで

興味のあるかたはぜひぜひ

それでは!

 

CoreCLRなBlackJumboDogにするとき仕組みを変更した理由と言訳 動的読み込みから組み立てに

前日からの続きです。日本各地で雪もすごい中、こんながあったりと。個人的にこれ賛成です。ASP.NET5って名称いつまでたっても、.NetFrameworkが5にならないか、いきなり6にいくかとかそういう偶数と奇数みたいなことでもしないとバージョン明記だけは無理があると思ってました。ただまぁ、次世代をいく、置き換えていくっていう願いが込められていたのではないかと思ったりもします。そこで、.Net Coreと同じようにCoreってつけたのいいと思いましたよ!名前と仕組みも一致した感じで。

.Net Core

以前、BlackJumboDogをはじめたところの記事でも書いていますが、GACとかってないんですね。基本すべて、NuGetからダウンロードなんですね。NuGetの参照って、名前とバージョンのみなんですが、これの実体となるDLLは、プラットフォームによって異なることが許されている。つまりDLLは動く環境によって変わる。言い方を変えると、DLLを参照するんじゃなくて、この名前を与えられているパッケージ(バージョンも指定可能)を必要としますっていう感じなんですよね。そうするとプラットフォーム用の実体が自動的に選ばれますよって。何を言いたいかというと、そもそも、実体のDLLに依存したものっていうのが静的(コンパイル)にはできない。また、参照として追加したいなら、DLLの形では難しいということなんですね。今はプロジェクトを参照する形で実現しているのが最初その違いに気づくのに時間がかかりました。NuGetだったので、ASP.NETみたいに、どっかにDLLあってみてるんだろーくらいに思ってたんですね。実行しているときはそうなるわけですが、コンパイル時には見てないってことをちゃんと理解していなかった。。。DLLとかライブラリ作ったならどこかで組み立てるプロジェクトがいないと話にならないなぁって思ったんですね。そこで、Bjd本体と実行イメージを作るプロジェクトを分けてみた(Bjd.Common.CoreCLRとBjd.CoreCLR)という結論を出してみました。これは、将来、BjdがNuGetに上がったりしたときに、利用する側がASPNETホストであるkestrelを動かすのと同じ感覚になることをイメージしてます。

そして、プラグインとしてDLLをReflectionを用いて拾い上げてプラグインを検索していたものを、ランタイム上に読み込まれているものからプラグインを検索する方法にしたというところでした。これはIssuesを見つけるまでどうしたもんかとひたすらネットサーフィンしてました。ここのServiceProviderっていうのを利用して、LibraryManagerなるものを取得、そこからプラグインを検索しています。できてしまえば、大したことないんですけどね。

こうして記事書きながら改めて振り返っているうちにEntryPointExecutor.csからActivatorUtilities.csを経由してMainは初期化されていく様子だということがわかったり。ServiceProvider.csという実体が見つかったりと、いろいろ面白い発見があったりするため、かなり楽しんでいます!ただ、この記事に書いている内容はソースをベースに話を進めているので、将来に渡っての仕様として明確なことではありません。ご了承ください。

それではまた!

CoreCLRなBlackJumboDogにするとき仕組みを変更した理由と言訳 System.Windows.Forms

こんにちは。BlackJumboDogの置き換えに着手して1か月近くが経過しました。そこで、近況ばかりだったここに、当初大きく変更した点を記していきます。自分のまとめと疑問が含まれていますので少し脱線する要素は多くなります。また、答えを求めていた方にはそぐわないものになるかもしれないことを、あらかじめご了承ください。

本家BlackJumboDog

Bjdというプロジェクトがすべての基本となる機能を持っていました。それはExeでWindowsFormsのGUIを持っていました。GUIは起動すると最初に表示されサーバーの設定もログもWindowsサービスのセットアップもこれ一つできるというオールインワンの仕様です。お手軽さとして非常に大きく価値あるものだと思っています。勝手ながらこの記事では、これをBjd本体と表現することにします。

次に、サーバーの機能は参照する他のプロジェクトで実装されていました。ここに実装された設定は、自動的にGUIを追加する機能をBjd本体が提供していました。また必要に応じてダイアログを追加するような土台もBjd本体が提供していました。サーバーの通信処理(Socket)もBjd本体が多くを提供していました。実装は設定と通信プロトコルに集中したものです。勝手ながらこの記事では、Bjdサービスと表現することにします。

Bjdサービスのプロジェクトは、コンパイルによってDLL(アセンブリ)となりそれらを所定のディレクトリに配置しました。実行時には、その特定名称となるDLLを自動的に読み込んでいました。このときに使っていたのがリフレクション(System.Reflection名前空間にある機能)です。このリフレクションとは、型に厳密であるC# VB.NETなど.NetFrameworkの言語に対して、実行時における動的な処理を追加する機能です。コンパイル時にはないものを実行することができる反面、実行するまで結果はわかりません。

アセンブリは通常ファイル名またはアセンブリ名を指定して読み込まれていきます。GAC(GlobalAssemblyCache)はその一つです。これは署名されたアセンブリでインストールされたものだけが格納されている特別な領域です。.NetFrameworkを使ったことのあるかたはご存知のSystem、System.Data、System.Netなどのアセンブリはここに格納されています。これらに格納されたアセンブリを参照したアセンブリで実行イメージを作った場合。実行イメージである.exeと同じディレクトリにアセンブリファイルが存在する必要はありません。サードパーティ製のアセンブリもここにインストールされていることもあります。サードパーティ製のものを使って実装したものが、違う環境では動かなかった。そんな経験を持っている人はかなり多いんじゃないか?と思います。その場合は、このGACに同じものが入るようにインストールするか、コピーしたアセンブリ(DLL)をExeと同じディレクトリに配置する必要がありました。これは、VisualStudioのプロジェクトの参照設定でいう「ローカルコピー」というやつで実現できました。

さて、少し長々と書きましたが、上記の構成では、CoreCLRで動く.Net Coreではいくつか難問がありました。

System.Windows.Formsは存在しない

実は、、、.Net Coreには存在してません。便利だったこのGUI(実際これ肝だったと思う)は削除することにしました。ただし、こうすることで、構成の変更はどうやってやるのか?という話になってくるかと思います。これは、元のBjd本体で作ったoption.iniをそのまま使えることを前提として、この機能を削除しました。ログはファイルに出力されますので、直接の問題にはならないでしょう。CoreCLRはプラットフォームを選ばないものとして作られているため、将来的にもこれが提供される可能性は低いのではないかと思います。あくまで個人的見解ですが・・・。そのまま動かすというのであれば、Monoという.NetFrameworkのCross platformなものがあります。それを選べばいいわけです。こんなところで、CoreCLRを選ぶからこそのメリットを明確にしていく必要が出てきたわけでした。

(続く)