AppVeyorのデプロイ先にMicrosoft Azure Blob Storageを使ってみたメモ

AppVeyorのドキュメントを眺めていて、デプロイの先としても使える場所に、AzureのStorageがありました。
Deploying to Azure blob storage

というわけで、AzureStorage(Microsoft Azure Storage の概要)に対して
デプロイしてみるメモです。

Microsoft Azure Storage

で、実際に使うとして、Azure Blob Storageっていうものになりますと、
このBlobには、「ホット」「クール」の種類があります。
Azure Blob Storage: ホット ストレージ層とクール ストレージ層
料金の違い)

ざっくりでいうと、クールは普段アクセスしないバックアップなどの用途に
ホットは、頻繁にアクセスする用途にという私の解釈です。
価格でみても、クールは容量単価が安く、
ホットはトラフィック、操作の単価が安くなっているようです。

デプロイするリソースは、頻繁に不特定多数にアクセスされる前提ですので
ホットにしてみようかと思います。

Azure側の準備

まずは、ポータルでBlobStorageを作ります。
+新規 > データ + ストレージ > ストレージ アカウント

名前:適当に入れますが、ホスト名に相当しインターネット上で一意である必要があります
デプロイモデル:リソースマネージャー
アカウントの種類:BLOBストレージ
アクセスレベル:ホット
ほか、お好みで。また、リソースグループは、その作業、やりたいこと、目的に応じて作っておいたほうが後で管理が楽です。(まとめて消すことができるとか)
作成で、しばらく待ちます・・・数十分もかかったことは今のところない

 

出来上がったら、さっそくコンテナ(実際にファイルを格納するもの)を作ります。
名前は適当にアクセスの種類はBlobです。そのほかのものは、今回使えないかと思います。

 

もう一つ、アクセスキーというのを控えておきます。
これは、書き込み削除のアクセスで、必要となる秘密のカギですので、見せないようにします。

どうでもいい余談ですが、これを間違って、公開してしまってひどい目にあうという話もあったりなかったりします。
過去、GitHubにあげてしまったとき、有志の人が機械的(?)にメール連絡してくれました。
(そのときは、サンプルのものでしたので、リポジトリごと削除した。)
もう一つ、キーを再生成するという方法もあります。

というところで、Azure側は準備完了!

AppVeyor側の準備

大きく2つあるように見えました、
プロジェクトごとのデプロイ先として設定するか、
Environmentとして全体に設定するか。

で、今回はEnvironmentとして設定しました。

Provider:Azure Blob Storage
Environment name:お好み
Storage account name:Azure側で作成したアカウント名
Storage access key:控えておいた秘密キーの1または2どちらか
Container name:Azure側で作成したコンテナ名
Folder:今回は何も入れない
Artifacts:デプロイしたい生成物の定義名

ビルド!

ビルドは成功!そしてアップロードされたらしきログがある!

追記(ここでProjects>[project]>Deployments>New Deployment)

Azureのポータル側でも確認

すっきり!これで、最新のpublish生成物を公開できるようになりました。

 

2016/07/23 追記
どうやら、自動にできたつもりが、手動でやったものが残っていただけらしい・・・(確認怠り
ひとまず、手動で
Projects>[project]>Deployments>New Deployment
でアップロードは確認した。

自動化するために必要なこと。
SettingsのDeploymentにEnvironmentsを設定する

AppVeyorの生成物を定義するメモ

定義するってなんぞや?というところですが、
基本的にビルドが終了するとすべてのものは消えてしまいます。
ビルドで、dllができたりnupkgができたりとするわけですが
これを定義して、リソースとして扱えるようにするもののようです。

公式のPackaging artifacts

で、yaml形式でもかけるようですが、WebUIを使っていきます。

Settings>Artifacts

ビルドコマンドで生成されたパスと、その名前を定義しておきます。
そして、ビルド実行!
結果にArtifactsが出てくれば成功

以下、BlackJumboDogのDockerImageでも利用している生成物と同じようにpublishで生成したリソースが出てきます。
https://ci.appveyor.com/project/darkcrash/bjd5-p6o91/build/artifacts

さぁ・・・これをどうしてくれようか

そしてDeploymentの道に続く・・・

AppVeyorで、ビルド結果をSlackに通知するメモ

先日の内容でビルドが自動化され、バッジも出たところですが
このままでは、終わったぜー!タイミングがわからないので、人的なポーリングが必要になってしまいます。もちろんメールで通知されますがメールは少し遅延があったりします。もっと即座にやってくれたほうがいろいろ使い勝手もいいかなぁと。
というわけで、Slackに通知させるようにします。

Slack側

配信先のチャンネルを用意します。もちろんすでにあるチャンネルでもよいです。
そして、Slack公式から「Incoming WebHooks」を準備します。

チャンネルごとに設定がありますので、その中からWebhook URL というのがありますので、控えておきます。

AppVeyor側

Slackを選びます。
控えておいた「Webhook URL 」を「Incoming webhook URL」に設定します。
投稿先のチャンネル名を入れます。

あとは、Saveボタンで保存!

ビルド~通知

何か適当にビルドを動かしましょう。手動でもトリガーでもいいので。
そうすると、ビルドの結果が投稿されてくるはずです。

という感じです。これ自体、.NET Coreとも関係ない世界ですが、一応のメモでした。

その他

カスタマイズとかは以下の情報が参考になりそうです。
http://www.appveyor.com/docs/notifications#slack

.NET Core WindowSocketのエラーメモ

とあるテストで、かつ1回目にしか発生しないエラーに遭遇したメモ

.NET Coreも内部ではSocketを使ってるわけで、以下のようなエラーが起きることがあるようです。
https://support.microsoft.com/ja-jp/kb/819124

今回遭遇したものは、

WSA_OPERATION_ABORTED (オペレーティング システムに依存)

  • 意味 : 重複した操作が取り消されました。
  • 説明 : ソケットが閉じているか、WSAIoctl (Wsapiref_6ik2.asp) の SIO_FLUSH コマンドが実行されたため、重複した操作が取り消されました。

でした。先のログ出力をしていってわかったことでした。
というのもこのエラー、デバッグで実行しても発生しない。
Consoleとして起動しても発生しない。
ので、実際に使う上では問題なさそうなものでした。
ただ、テストコードのようにmsで動く世界だとどうしてもシビアなのかなぁというところで、一つ一つトレースしてました。

[14:18:19.7113][  21][0][Info] ExecProcess: outputLength6087
[14:18:19.7123][  21][0][Info] HttpResponseBody.Set Length=6060
[14:18:19.7123][  21][0][Info] CgiHandler.CreateFromCgi 
[14:18:19.7133][  21][0][Info] WebServer.OnSubThread SEND
[14:18:19.7143][  21][0][Info] 33768781 SockTcp.Send 31
[14:18:19.7143][  16][0][Info] Detail Web-localhost:7188 ::1 0000004 response HTTP/1.1 200 Document follows
[14:18:19.7143][  27][0][Info] 55071656 SockTcp.EndReceive Length=31
[14:18:19.7143][  27][0][Info] 55071656 SockTcp.BeginReceive
[14:18:19.7143][   4][0][Info] 55071656 SockTcp.LineRecv 31
[14:18:19.7163][  28][0][Erro] 55071656 SockTcp.EndReceive Result.SocketErrorCode:OperationAborted
[14:18:19.7163][  28][0][Erro] 55071656 SockTcp.EndReceive Result.ExceptionType:System.Net.Sockets.SocketException
[14:18:19.7163][  28][0][Erro] 55071656 SockTcp.EndReceive Result.ExceptionMessage:スレッドの終了またはアプリケーションの要求によって、I/O 処理は中止されました。
[14:18:19.7163][  28][0][Erro] 55071656 SockTcp.EndReceive Result.ExceptionMessage:One or more errors occurred. (スレッドの終了またはアプリケーションの要求によって、I/O 処理は中止されました。)
[14:18:19.7163][  28][0][Erro] 55071656 SockTcp.EndReceive Result.StackTrace:
[14:18:19.7163][  28][0][Erro] SockTcp.SetError 55071656 SockTcp.disconnect
[14:18:19.7173][  21][0][Info] 33768781 SockTcp.SendNoTrace 173
[14:18:19.7183][  21][0][Info] HttpResponseBody.Send encode=True
[14:18:19.7183][  21][0][Info] 33768781 SockTcp.SendNoTrace 6060

という具合に、問題の箇所は突如として、謎のエラーが出てるというところです。
これを、SocketExceptionとしてキャスト、エラーコードを調べてみたところ上のエラーにいきついたというころでした。
この「OPERATION_ABORTED」というのは、Socketそのものが切断されたためのものではないため、再度受信待機に入ることで対策しました。

.NET Core xUnit 出力のメモ

今日はちょっとしたメモ

.NET CoreでVisualStudio上のテストエクスプローラーから実行した場合、それまでのテストツールであれば、出力で、Traceなどの出力を確認することができました。
しかし、新しいxUnit v2.xでは標準でサポートされなくなりましたと。

https://xunit.github.io/docs/capturing-output.html
If you used xUnit.net 1.x, you may have previously been writing output to Console, Debug, or Trace. When xUnit.net v2 shipped with parallelization turned on by default, this output capture mechanism was no longer appropriate; it is impossible to know which of the many tests that could be running in parallel were responsible for writing to those shared resources. Users who are porting code from v1.x to v2.x should use one of the two new methods instead.

要するに、並列実行されるようになって、どこのテストの結果から出たTraceかわからなくなったと。これに責任持てるような手段がないとのこと。

代替として・・・

As you can see in the example above, the WriteLine function on ITestOutputHelper supports formatting arguments, just as you were used to with Console.

テストコードのあるクラスのコンストラクタに、ITestOutputHelperを引数として渡す。それにWriteLineメソッドを呼び出せば標準出力のように動いてくれると。といっても、Traceしたいので、なんとなく作りました。

https://github.com/darkcrash/bjd5/blob/CoreCLR/Bjd.Common.CoreCLR.Test/Logs/TestOutput.cs

使い方は、コンストラクタで、ITestOutputHelper を引数としてインスタンス化。DisposeでDisposeです。とはいえ、これはこれで、出力がただ出てくれるというだけで、根本的な解決ではないと認識しています。

これを作った経緯として、個別のテストでエラー箇所を特定するために出したかったというものです。なので、一括に動作してきれいな形で出てくれるが目的ではないのです。

こんな感じ

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さん、情報ありがとうございます!