2017年9月16日

GitLab CIを使ってWebAPIのPDFドキュメント生成を自動化する

前回は Web APIに組み込んだSwaggerが生成する swagger.json ファイルからコマンドラインでPDF形式のドキュメントを生成するところまで出来ました。

今回はこの一連の処理をGitLab CIを使って自動化してみようと思います。

大まかな流れは次のようになります。


  1. GitLabにプロジェクトを作成する
  2. 「.gitlab-ci.yml」ファイルを作成する
  3. GitLabにプッシュしてCIが動作することを確認する
  4. Web APIをAzure App Servicesに自動デプロイする
  5. CIでPDFドキュメントを自動生成する
  6. 生成されたPDFドキュメントをダウンロードする



1. GitLabにプロジェクトを作成する


CIサービスと言えば、Circle CIやTravis CI、Werkerなどたくさんありますが、今回は GitLab CI を使うことにしました。

まだ gitlab.com にアカウントが無い場合はユーザー登録しましょう。
ログイン後、「New Project」ボタンを押して新規プロジェクトを作成します。GitHubに既にプロジェクトがある場合はそちらからそっくりインポートする事も可能です。


2. 「.gitlab-ci.yml」ファイルを作成する

ソリューションの直下に .gitlab-ci.yml と言う名前のファイルを作成します。

Visual Studioを使っている場合はソリューションを右クリックして「追加」をすればSolution Itemsの下に表示されます。


ファイルの内容はとりあえずこんな感じにしておきます。




Dockerのベースイメージとして、Ubuntu 14.04 を使っています。

before_script の部分で apt-get コマンドを使ってJavaとRubyのインストールを行ない、script の部分で動作確認のためにJavaとRubyのバージョンを出力しています。

.gitlab-ci.ymlファイルの仕様は下のページに載っています。
https://docs.gitlab.com/ce/ci/yaml/README.html#gitlab-ci-yml




3. GitLabにプッシュしてCIが動作することを確認する


この状態でGitLabにプッシュして見ます。Pipelinesというメニューをクリックすると自動的にPipelineが作成されている事が分かります。


Jobsというサブメニューを開いて実行されたJobをクリックして詳細を表示すると、黒い画面でコンソール出力の結果を確認する事が出来ます。JavaとRubyのインストールが正常に行われて、最後にバージョン情報が表示されていれば成功です。



リポジトリへのPushを検知してGitLab側で自動的にDockerコンテナを起動して指定のコマンドを実行してくれているわけですね。

Circle CIなど他のサービスを使わずに、しかも無料でこれが出来るというのがGitLabの良い所だと思います。

ちなみに「CI Runner」というものを自前のサーバーにインストールしておけば、Dockerコンテナをそのサーバー上で起動させる様にする事も可能なようです。(むしろ元々は自前で用意するのが基本だったようです。)



4. Web APIをAzure App Servicesに自動デプロイする



Web APIのデプロイ先はAWSやGoogle Cloudなどどこでも構わないのですが、今回はAzure App Servicesを使います。

Azure App Servicesに自動デプロイするにはいくつかの方法がありますが、ここではTravis CIが作成している dpl コマンドを使ってみます。

GitLab CIのジョブでdplコマンドを実行するための設定は次のようになります。



Ubuntu 14.04を起動した後 Rubyをインストールし、さらに gem install dpl で dpl コマンドをインストールしています。

その後、dpl --provider=AzureWebApps で実行します。


ちなみに、
only:
    - /^release-.*$/
の部分は、「release-」で始まるタグ付きでプッシュされた時だけこのジョブが起動されるようにするための設定です。この2行を削除するとプッシュするたびに毎回起動されます。


さて、上の設定ファイルではデプロイ先のURLやデプロイ用の認証情報などを一切指定していません。それらはGitLab内のプロジェクト毎の設定画面に「Secret variables」として登録しておきます。





dplコマンドは

  • AZURE_WA_SITE
  • AZURE_WA_USERNAME
  • AZURE_WA_PASSWORD

の3つの設定を自動的に読み込んで処理してくれます。

この状態で実際にGitLabにプッシュして見るとAzure App ServicesにWeb APIが自動デプロイされます。下はデプロイ成功時のジョブのログを表示したところです。



念のためAzure側のURLを開いてみると確かにWebAPIとSwagger UIが動いています。







5. CIでPDFドキュメントを自動生成する


さて、次はいよいよWeb APIのPDFドキュメントを自動生成します。設定ファイルにpdfというジョブを追加しました。




stages:
  - deploy
  - pdf
となっているので、「deployというステージが終わってからpdfというステージを実行する」という意味になります。ひとつのステージには複数のジョブを含める事が出来ますが、その場合はステージ内の各ジョブが並列実行されます。今回の設定ではそれぞれのステージに同名のジョブを一つずつ含んでいるだけという形になっています。

それぞれのジョブは別個のDockerコンテナとして起動されるので、pdfジョブの方でも再度Rubyのインストールが必要になります。こちらのジョブではJavaのインストールも必要なのでdeployジョブよりも少し時間がかかります。

cd ./MySampleWebApi.Doc && chmod +x *.sh && ./build.sh $SWAGGER_JSON_URL

MySampleWebApi.DocフォルダにあらかじめダウンロードしておいたJavaのコマンド(swagger2markup-cli-1.3.1.jar)やスクリプトを格納してあるので、そのフォルダに移動して build.sh を実行しています。

これで前回に実行したのと同じ一連の処理が動いて ./MySampleWebApi.Doc/pdf フォルダにPDFファイルが作成されます。

この時にSecret Variablesの設定から $SWAGGER_JSON_URL の値を読み込んでスクリプトに渡しています。

こうしておけばAzure側のデプロイ先が変わっても柔軟に対応出来るので便利ですね。



6. 生成されたPDFドキュメントをダウンロードする


最新の成果物へは下の形式のURLでアクセス可能になっています。

https://gitlab.com/(ユーザー名またはグループ名)/(プロジェクト名)/-/jobs/artifacts/master/browse?job=(ジョブ名)

このURLへはGitLabにログインした状態でかつ権限があるユーザーでないとアクセス出来ないので、実運用では .gitlab-ci.yml にさらにジョブを追加してAWSやAzureなどのストレージにアップロードするような処理を追加することになると思います。


あと、この設定のままだとジョブが起動される度に素のUbuntuに対してJavaやRubyのインストールから行っているので、終了するまでにかなり(数分程度)時間がかかってしまいます。

出来ればJava/Rubyが既に入った状態のイメージを探してくるか自分で作成するかして、それをベースイメージに指定した方が良いと思います。



今回作成したサンプルプロジェクトの全ソースコードは下記で参照可能になっています。

https://gitlab.com/mikehibm/AspNetCoreWebApiSwagger







2017年9月8日

SwaggerのAPI定義からPDFドキュメントを生成する

前回はASP.NET CoreのWeb APIプロジェクトにSwaggerを組み込んでAPIのドキュメントをブラウザ上に表示させるところまで実行しました。



これはこれで手軽にAPIの仕様を確認出来て便利なのですが、受託開発の際の納品物としてお客様に渡すには少し不便です。「納品は紙(PDF)で」と言われる事がまだありますよね?

ブラウザに表示されているものを印刷して渡してしまっても良いかもしれませんが、それだと今ひとつ見栄えが良くないので出来ればもう少しきれいなPDF文書を自動生成したいところです。

そこで調べたところ、次のような事が分かりました。

swagger2markup-cli を使えばSwaggerが生成するJSONファイルから静的なHTMLやMarkdown、AsciiDoc形式のドキュメントなどを生成する事が出来る。

asciidoctor-pdf を使えばAsciiDoc形式のドキュメントをPDFファイルに変換する事が出来る。

参考:
goa tips: swagger-ui がサービスできないときのドキュメントどうする問題 - 押してダメならふて寝しろ

asciidocをPDFに変換してみた(asciidoctor-pdf)


今回はこれらを使って
swagger.json → AsciiDoc → PDF
という流れでドキュメントを生成する事にします。


まず前提条件として、swagger2markup-cliを使うにはJavaのインストールが必要で、asciidoctor-pdfを使うにはRubyのインストールが必要になります。

Macで開発しているのあれば通常は両方とも既に入っていると思います。Windowsの場合はchocolateyを使えば簡単にインストール出来ると思います。



1. swagger2markup-cliでAsciiDocファイルを生成する

下のURLからjarファイルをダウンロードします。

https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup-cli/


ダウンロード後、コマンドラインから下記を実行します。

java -jar ./swagger2markup-cli-1.3.1.jar convert -i [swagger.jsonへのパス] -d ./adoc

[swagger.jsonへのパス]の部分は 「http://localhost:49879/swagger/v1/swagger.json」のようにURLを指定しても良いし、「./swagger.json」のようにあらかじめダウンロードしておいたJSONファイルを指定しても構いません。

エラーが出ずに成功すれば、adocフォルダには overview.adoc, paths.adoc, definitions.adoc, security.adoc の4つのファイルが出来ているはずです。ファイルが分かれていると次のステップで困るので、1ファイル(out.adoc)に結合しておきます。

cat adoc/overview.adoc adoc/paths.adoc adoc/definitions.adoc > adoc/out.adoc

(security.adocの内容は特に必要がなかったので除外しました。)




2. asciidoctor-pdfでPDFファイルを生成する

gemコマンドでasciidoctor-pdfをインストールします。

gem install --pre asciidoctor-pdf

あとは入力と出力を指定して実行するだけです。

asciidoctor-pdf -o pdf/out.pdf adoc/out.adoc

これでpdfフォルダにout.pdfファイルが生成されます。サンプルはこんな感じです。


デフォルトのスタイルが物足りなければ、テーマを自作して色々とカスタマイズ出来るようです。
asciidocをPDFに変換してみた(asciidoctor-pdf)


さて、ここまででWeb APIからPDFドキュメントを生成する事が出来ました。ただ、APIに変更が発生する度にコマンドを打ち込んでPDFを再生成するのはちょっと面倒です。

そこで次回は、今流行りの「Continuous Integration(CI)」なるものを使ってソースコードの変更をプッシュするだけで自動的にPDFドキュメントが更新される、という事にチャレンジしてみたいと思います。

次回: GitLab CIを使ってWebAPIのPDFドキュメント生成を自動化する





ASP.NET WebAPIにSwaggerを組み込む



1. ASP.NET Core Web APIを新規作成する


Visual Studio 2017でASP.NET CoreのWeb APIプロジェクトを新規作成します。


デフォルトでControllersフォルダの中にValuesControllerがあるので、この名前をProductsControllerに変更し、さらにUsersControllerを追加します。

新規にResourcesフォルダを作成してその中にProductクラスとUserクラスを作成しておきます。

その後ProductsControllerとUsersControllerを編集してダミーのデータをJSONで返す様にした状態のソースコードが下記になります。(コミットにbefore-swaggerタグが付いています。)

https://github.com/mikehibm/AspNetCoreWebApiSwagger/tree/before-swagger

Ctrl+F5キーで実行すると商品とユーザーの情報がJSONで返って来るのが分かります。


この状態でWeb APIとしては動いているので、次にSwaggerを組み込んでAPIのドキュメント(メタ情報)に外部からアクセス出来るようにしてみます。



2. Swaggerを組み込む


Visual Studio内でPackage Managerコンソールを開いて、次のコマンドを打ち込みます。

Install-Package Swashbuckle.AspNetCore

その後、下のサイトを参考にStartup.csファイルを編集します。と言っても数行を追加するだけなので簡単です。

ASP.NET Web API Help Pages using Swagger


編集後の Startup.cs は下の状態になります。




この状態でCtrl+F5キーを押して実行し、http://localhost:xxxxxxx/swagger/ のURLを開くと、Swagger UIの画面が開いてAPIのドキュメントを閲覧する事が出来るようになっています。



ただこの段階ではせっかくソースコードに書き込んだコメントが反映されていないので、次にそれらが反映されるようにします。



3. XMLコメントをSwaggerに反映させる


まず、プロジェクトの設定で「XMLドキュメントファイル」の自動生成を有効化しておく必要があります。



この状態で一旦プロジェクトをビルドすると、指定したファイル名でXMLファイルが出来るはずです。このファイルをVisual Studioのソリューションエクスプローラ上で右クリックして、「プロジェクトに含める」を選択しておきます。

さらに、XMLファイルを選択した状態でF4キーを押してプロパティウインドウを表示し、下のようにプロパティを変更しておきます。これは後でこのプロジェクトをPublishする際に必要になります。





次に、Startup.csファイルの中で services.AddSwaggerGen() メソッドを呼んでいる箇所があるので、そのブロック内に下の3行を追加します。

var basePath = PlatformServices.Default.Application.ApplicationBasePath;
var xmlPath = Path.Combine(basePath, "MySampleWebApi.xml");
c.IncludeXmlComments(xmlPath);

これで再度実行するとソースコード内でクラス単位やメソッド単位で「///」を使って書いたコメントがSwagger UIの画面にも反映されます。




4. まとめ


ASP.NET CoreのWeb APIプロジェクトにSwaggerを組み込んでAPIのドキュメントを表示させるようにする事は、上の通りかなり手軽に出来ます。

ASP.NET Coreでなく従来のASP.NET MVCのプロジェクトでもほぼ同じ手順でSwaggerの組み込みが可能です。

次回はSwaggerが生成した情報を使ってPDFドキュメントを生成する方法を書いてみたいと思います。





2017年7月30日

ビットコインは通貨として生き残るのか?


世間ではビットコインの分裂騒動が話題になっていますが、その話ではなく、

この本を読み終わってのメモです。




『これでわかったビットコイン [生きのこる通貨の条件]』 斉藤 賢爾  (著)


2014年の本ですがこれからビットコインについて知りたいという人には十分役に立ちます。

本書は「入門編」「使い方編」「そもそも編」「しくみ編」の4部で構成されています。この中で「そもそも編」ではビットコインに否定的な意見を持つ筆者の視点を知ることが出来ます。

BTCの発行量上限が2100万と決まっている事について、筆者は「インフレ撲滅への開発者の強い意志」が反映されたものだと述べ、「でもそもそもインフレって悪いこと?」と疑問を投げかけます。

"たしかに、貨幣を持っている人たちにとっては重大な問題でしょう。みずからの資産が目減りしていくことを意味しているからです。" (p.66)
"逆に、デフレ状態では、商品にたいして貨幣の価値が相対的に上がります。これは富める者たちにとっては資産が自動的に増えることを意味します。" (p.66)
"ビットコインではデフレが起きるような設計がされていますが、うがった見方をすると、富める者たちがそれを利用してさらに儲けようとしている、ともいえるかもしれません。" (p.66) 
"貨幣が希少で、かつ、貨幣がなければ何もできない世の中に生きていると、私たちは、どうにかしてそれを手に入れなければならなくなります。そして、貨幣を持っている人の言うことを聞くようになります。それは、自分が支配される立場におかれることを意味します...(略)" (p.69)

「通貨・貨幣とはなにか」について自分なりに考える良いきっかけになりました。

たしかに、発行数上限が近づくにつれて希少性が上がり「先行者有利」なまま「持てる者」と「持たざる者」の格差が指数関数的に広がっていく現状のビットコインの設計については、「これが本当に最善なのか」今一度じっくりと考えないと行けないのではないかと思いました。


この辺りの「より良い通貨の設計」というテーマについては岩村充教授の『中央銀行が終わる日: ビットコインと通貨の未来』でより詳細に議論されているのでこちらも一緒に読むと面白いです。



ビットコインのPoWの仕組み等についてさらに詳細に知りたい方には大石哲之さんの『ビットコインはどのようにして動いているのか?』(Kindle本)がオススメです。









2017年6月19日

Angularでサーバーから取得したPDFを表示する


Angularでサーバーから取得したPDFを表示するサンプルを作ってみました。


実際に動くものはこちら

全ソースコードはこちら。



サーバーからPDFファイルを取得する部分



サンプルではGitHub Pagesからスタティックなファイルをgetしていますが、Web Apiから動的に生成されたファイルを取って来る場合でも全く同じです。



受け取ったPDFファイルをクライアント側で表示する部分




URL.createObjectURL(blob) でblobからデータURLを生成して、それをHTML側で object タグの data 属性にバインドして表示しています。

ただそれだけだとAngularのセキュリティ制限でエラーになるので、DomSanitizerのbypassSecurityTrustResourceUrl()というメソッドを呼ぶ必要がありました。


あ、それからこのサンプルは現時点ではIEでは上手く動かない様です。

ChromeとFirefoxでは問題無く動作しました。

MacのSafariではobjectタグでの表示はされましたが、Downloadのリンクをクリックしても別タブで表示されるだけでダウンロードはされませんでした。

ブラウザ objectタグでの表示 aタグでのダウンロード
Chrome
Firefox
Safari
Edge ×
IE11 × ×











2017年6月13日

Lenovo Chromebook N22を購入

2ヶ月ほど前(2017年4月)に、Lenovo の Chromebook N22 を買いました。

LenovoのWebサイトを見ていたら、Outlet価格で$185(送料無料)になっていたので、タッチ対応でかつRAMが4GBである事を確認した上で即オーダーしました。

数日後に見たらサイトから無くなっていたので、即オーダーして良かったと思います。



軽いので持ち運びもラクラクです。液晶もきれいで見やすいです。

Web閲覧などで1日に1〜2時間ほど軽〜く使う感じであれば1回の充電で1週間ほど持ちます。

画面はここまで開きます。180度、と言いたい所ですが微妙にそこまで開かず、175度ぐらいまででしょうか。




実は一番気に入っている使い方はこれ(下)です。画面を一杯まで開いて、自分は寝転がってお腹のうえに本体を突き立てるようにして、片手で支えながらWebを見るのが最高に快適です。笑)

キーボード部分がちょうど良い支えになってくれるので、タブレットを空中で保持するよりずっと楽なのです。




さて、Chromebookを買った本来の目的は、「子供の勉強用」でした。学校にもChromebookが導入されているので、「これ使っていいよ」と渡すと何の違和感もなく早速使いこなしていました。

小・中学生に使わせるコンピュータとしては確かに最適だと思います。


そう言えば、初期化する時に「Devチャンネル」に設定しておいたからか、5月に入った頃から「Google Play Store」が使える様になりました。

試しにAndroidアプリをいくつか入れたりして見ましたが、全く問題無く動作しています。

自作のアプリも全て動作したので、結構感動してしまいました。


これからは、Androidタブレットにキーボードを接続してPCっぽく使えるようにするぐらいなら素直にChromebookを買うのが正解かも知れませんね。