2017年11月22日水曜日

CloudBees Jenkins Advisor をインストールしてみた


第11回 Jenkins勉強会」で知った CloudBees Jenkins Advisor をインストールしてみました。
勉強会参加報告はこちら→(ブログズミ: 「第11回 Jenkins勉強会」に参加してきました



SignUp してインストール
「USE IT FREE NOW!」からサインナップします。


完了すると以下のような画面になります。
Trial Period Overなのは、むかーし使ってたことがあるから。前と大分変わりましたね)


以前に登録していたので SignUp 手順が確認できませんでしたが、必要になってくるのはアカウント名とパスワードなので、それがあれば問題ありません。


プラグインインストール
プラグインのインストールは普通に Jenkins のプラグイン管理からできます。
「CloudBees Jenkins Advisor Plugin」があるので、いつもどおりインストールしましょう。



セットアップ
「Jenkins の管理」を開くと以下のようなメッセージが出ています。「Connect Now」をクリックしましょう。


接続設定画面が開くので、先程登録した「CloudBees」のアカウントメールアドレスとパスワードを入力します。
「Advanced configuration」がありますが、とりあえず使いたいだけなので特に設定せずに「Connect account」します。


すると、アカウントメールアドレスに以下のようなメールが来ます。
レポートが1日ごとに来るようなので、1日待ちましょう。


レポート




なんか出てますね・・・
とりあえず今回はインストールして使ってみただけなので、ゆくゆく調べながら対応していきますか。

最後に
Jenkins Advisor についてはこちらの CloudBees のブログにも書かれています。
Jenkins AdvisorでJenkinsのダウンタイムを防ぐ | Cloudbees Jenkins Solutions
ロードマップによれば、閉じられた環境の Jenkins の診断対応やダッシュボードの追加がされるようです。
こちらにも期待しつつ、インストールした状態でしばらく使ってみようと思います。

では。



2017年11月13日月曜日

「第11回 Jenkins勉強会」に参加してきました

どうも僕です。仕事が始まって1週間。こちらでの生活にも慣れてきました。
そんなこんなで「第11回 Jenkins勉強会」に参加してきました。
東京来て一発目の勉強会!久しぶりの参加報告って感じですね。

今回の講演は3つ + LT 3本立て。
「初めての自動テスト meets Jenkins」


最初は「初めての自動テスト ―Webシステムのための自動テスト基礎」を翻訳された玉川紘子(@nkns165)さんの講演。

原著者がアジャイルサムライを書いた人と一緒とか、CI の章がないが CI があっての自動テスト(あるの当たり前)とか、翻訳こぼれ話とか、興味深い話が聞けました。
自分も本に関わってみたいなぁー



「Jenkins World 2017 の報告」
2つ目は Jenkins World 2017 で「Most Valuable Advocate」受賞の中村知成(@ikikko) さん!
(そのへんは @ikikko さんのブログへ)



Jenkins Advisor はじめて知りました。さっそく使ってみようと思いました。

Jenkins world の動画はここかな?
https://www.youtube.com/user/CloudBeesTV


「Jenkins PipelineとBlue Oceanによる、フルスクラッチからの継続的デリバリ」
最後は川口さん!

↓は今回の講演と(たぶん)同じヤツ




#はい

when で任意ブランチでのみ stage できるっぽいので、iutest のパッケージビルドを Jenkinsfile にお引っ越ししようと思いました。


LT
ここから LT
遠くの"計画"よりも今日の"CD"(継続的デプロイ)


タミヤ カムプログラムロボット工作セットで作るXFD


開発者(個人)のためのJenkins 運用編


感想
参考になる話、知見、情報と持ち帰るものが予想以上にあってよかった。
LT はホントいつも面白いし、すごい!
懇親会でも色々いいお話聞けたのでとっても大満足。

最後に、テクマトリックスさん、スタッフのみなさん、そして講演者の方々、ありがとうございました~

2017年11月8日水曜日

[Appveyor] イメージを環境変数で指定する

今回は Appveyor で環境変数を使ったイメージの指定を紹介します。
iutest のテストでイメージごとにそれぞれ異なる環境変数を設定したかったときに、この方法に行き着きましたのでそれの紹介です。

テストではよくマトリックスを組んで複数の環境でテストをすることが多いと思います。
Appveyor なら、イメージが複数用意されているので、それぞれでテストを実行することになります。その場合はイメージを複数指定すれば OK です。
さらに環境変数を列として、イメージ×環境変数のマトリックスも組むこともできます。
さきにこちらの方法を紹介しておきます。

イメージと環境変数のマトリックス
まずイメージは「SETTINGS」「Environment」の「Build worker image」で複数設定することができます。
指定したイメージの分だけ、ジョブが実行されます。


さらに、同じく「Environment」の「Environment variables」で環境変数を指定できます。
「Add variable」だと、各イメージで共通の環境変数が設定されますが、「Add build matrix group」では環境変数のマトリックスを作成できます。


グループを追加すると「Environment variables - 1」「Environment variables - 2」のようにグループが増えていきます。
それぞれ「Add variable」から環境変数を設定できます。



テーブルにするとこんな感じです。
ENV_M valueVisual Studio 2015Visual Studio 2017
Environment variables - 111
Environment variables - 222

Visual Stduio 2015/2017 のイメージそれぞれに対して、ENV_M が 1 と 2 のジョブが実行され、計4つのジョブが実行されます。

iutest でやりたかった構成
さて、これに対して iutest でやりたかったことはこうです。
ENV_M valueVisual Studio 2015Visual Studio 2017
Environment variables - 11×
Environment variables - 2×2
※×印はジョブを実行しないという意味です
上と合わせて書きましたが、わかりやすくするとこうです。
Visual Studio 2015Visual Studio 2017
ENV_M value12
つまり、マトリックスにしたいわけではなく、イメージ対して一意な環境変数を設定したいわけです。



これができないか調べていたら、イメージのマトリックスを使わずに、「APPVEYOR_BUILD_WORKER_IMAGE」環境変数でイメージの指定ができることを知りましたので、これで解決しました。

イメージを環境変数で指定する
環境変数マトリックスでイメージを指定するので「Build worker image」は空にします。
次に、「Add build matrix group」で環境変数のグループを作成し、環境変数名「APPVEYOR_BUILD_WORKER_IMAGE」でイメージの名前を設定します。


これで実行すると「Environment variables - 1」のときだけ、イメージ設定が上書きされます。


環境変数が変わっただけでイメージが変わってないかもしれないので、以下のコマンドで確認しました。


結果、このようにイメージが変わっていることを確認。


まとめ
イメージに対して環境変数を別途指定したい場合は、環境変数のマトリックスと APPVEYOR_BUILD_WORKER_IMAGE を使うと実現できます。
イメージ×環境変数のマトリックスを組みつつ、イメージに対して個別で一意な環境変数をセットしたい場合は、APPVEYOR_BUILD_WORKER_IMAGE 環境変数を参照して判断するのが良さそうです。

マトリックス化する予定があるなら、最初から APPVEYOR_BUILD_WORKER_IMAGE を参照して分岐させるほうがいいかもしれないです。
このへんは好み、かなぁ・・・
ともあれ、APPVEYOR_BUILD_WORKER_IMAGE は ReadOnly じゃなくて Write もできるってことを覚えておくと今後役に立つかもしれません。(たぶん)


今回は以上です。では。

2017年11月1日水曜日

初出社

本日、初出社でございます。
報告記事でブログ更新回数を稼いでいますが、ここ1ヶ月ほどやることが多くて全くもってプログラムをしてませんでした。(引越前の駆け込み観光とか引越後の観光とか)インプットがないとアウトプットもなかなかないわけで…

休暇も終わってこれから新天地での生活ルーチンが構築されていくわけですが、これまで通り趣味プロやブログを書く時間を作っていきたいと思います。(早速この記事は通勤中に書いてます)

では、今後ともよろしくお願いしますm(__)m

2017年10月4日水曜日

[CI] Rocro 使ってみた

ソニーネットワークコミュニケーションズ、新会社「Rocro株式会社」を設立
ソフトウェア開発者向けサービス群「Rocro」のベータ版の提供を開始
~自動コードレビュー、自動APIドキュメント生成、自動負荷試験をSaaSで提供~
http://www.sonynetwork.co.jp/corporation/release/2017/pr20170914_0036.html



ちょっと見てみたら、C++ にも対応しているようだったので試してみました。

登録
Rocro にまずはアクセス。
INSPECODE LOADROID DOCSTAND の3つありますが、今回は INSPECODE を使ってみます。



「Sign in」ボタンを押すと Github か Bitbucket の選択肢が出てくるので好きな方を選んでください。
(※後述しますが、現時点では public リポジトリに対応してません)


今回は Github を選択しました。
ナビゲーション通り進めれば登録は完了するはずです。

完了すると、ダッシュボードが表示されます。

Repositories をクリックして検証したいリポジトリを登録しましょう。

リポジトリ登録
「Repositories」を開くと以下のように表示されました。


「As of now, only private repositories are supported. Public repositories will be supported soon.」
Public リポジトリに対応してませんでした(2017/10/2 現在)
いずれ対応するとのことなので、ひとまず今回は Bitbucket に private リポジトリを作って試してみることにします。



気を取り直して Bitbucket でサインインするとこのようになります。



無事、リストアップされましたので、解析したいリポジトリを選択して登録をします。

解析
リポジトリ登録すると自動で解析が始まります。









けっこう待ちます。
(Cppcheck がながいのかな?)







解析が終わりました。赤くなっているということは何かしら問題があったようですね。
アイコンをクリックして結果を見てみましょう。

解析結果を見る


まず開くとこのようなページが表示されます。
失敗原因は Cppcheck のようです。
下にスクロールしていくと出力からどこが原因かがわかります。


(ログから読み解くのではなく、Jenkins みたいに集計できるともっと便利ですが…今後に期待)




ついでなので、ほかの解析結果も見ていきましょう。
「View Report」ボタンを押してください。



まずは「Summary」

シンプルな感じ。

「Files」タブを開くと各ファイルのメトリクスを見れます。

各ファイルをクリックすると詳細が確認できます。(Issues とソースコードとメトリクスの詳細)

「Issues」タブを開くと問題の詳細が確認できます。(サマリーからも飛んでこれます)



うーん。「ブログズミ: 続・ソースコード中の単語からの略語/スペルミス検出に挑戦」で直しきれなかったミススペルが・・・(コメント中のミススペル。コメントもチェックするように変えようかなぁ…)

Settings
一応「Settings」でできることも紹介しておきます。
まず、「Notifications」では通知設定ができます。現時点では「メール」「Slack」「HipChat」の設定ができました。

「Bitbucket/Github」ではホスティングサービスとの連携周りのリセットができます。
(※Github は private リポジトリを持ってなかったため未確認)

「Branches」では、CI を回すブランチを指定することができます。


バッジ
最後にお約束のバッジの付け方です。
バッジも「Settings」の中にあり「Badges」タブを開くと以下のようにテキストが得られます。



今は赤いですが、そのうち対応したい・・・


最後に
まだ public リポジトリに対応していないため、私が使いたいリポジトリでは直ぐには実運用はできない状態ですが、private リポジトリで開発している方なら問題なく使っていけるかと。
特に Cppcheck がデフォルトでチェックされるのが便利ですね!(結果の見やすさ改善は今後に期待)
コードレビュー系の CI サービスで C++ をサポートしてるのって珍しい気がするので、とってもありがたいです。
public リポジトリ対応されたら、iutest での運用を開始しつつ、より深く触っていきたいと思います。

以上。



2017年9月28日木曜日

退職しました。

10月15日付けで退職しました
11月から新しい会社です。

ここ最近更新が滞ってますが、このブログは引き続きやっていこうと思ってますので、今後ともよろしくお願いします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">バイバイ京都 <a href="https://t.co/q5wAC2el6i">pic.twitter.com/q5wAC2el6i</a></p>&mdash; ずみっくす@東へ (@srz_zumix) <a href="https://twitter.com/srz_zumix/status/919141018754211840?ref_src=twsrc%5Etfw">October 14, 2017</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

2017年9月25日月曜日

[備忘録] Jenkinsfile 作成時に約に立ちそうなリンクまとめ

はじめに
最近、Jenkinsfile を書く機会ができて、実用での Jenkinsfile を書くことになったら、全然知らないこと・わかってないことが多くて調べたときのリンクをざっと貼り付けてみました。
このブログを読んでいただいている方でも、もしかしたら、参考になることがあるかも?
では、並べていきます。

自分用リンクまとめ

Pipeline Steps Reference
各ステップのリファレンス。
基本的な使い方はここに書いてある。

workflow-support javadoc
困ったときは javadoc 見る。
リンク先は workflow-support のものなので、知りたいオブジェクトを println でもして、クラス名でぐぐったらだどりつけると思う。

Groovy でプロパティ一覧とメソッド一覧を取得する - blog.scheakur.com
javadoc 見なくても、プロパティやメソッドを println しちゃえば何があるか直ぐわかる。

Jenkins2のPipelineを使うときのいくつかのポイント(2016/12/10現在) - Qiita
フリースタイルジョブを build job で呼び出したときに、そのジョブの結果を知りたい場合は build job: 'hoge' , propagate: false

Jenkinsfile を書く前に知っておくべきこと (セキュリティ制約編) - あらしおブログ
Sandbox とかの話。




なんとかなりませんかね?



Jenkinsfile を書く前に知っておくべきこと (機能制約編) - あらしおブログ
"CPS 変換" というものがあるらしく、対応していないコードを書くと UnsupportedOperatinException 例外が送出される。
また、Serializable 非対応なクラスも使えないらしく、以下のように例外になる。
java.io.NotSerializableException: java.util.regex.Matcher

リンク先に書いてあるとおり、@NonCPS なメソッドに括り出すことで対応可能。

Jenkins2.0のPipeline活用法(4月現在) | enish engineering blog
NonCPS についての知見が書いてあります。

Jenkins 2.0 (5): Jenkinsfileをコマンドラインからlintする

jflint 最高です!ありがとうございます!!


リンク
2017/11/08 追加

pipeline スクリプトのサンプル
https://github.com/jenkinsci/pipeline-examples
pipeline 自体のユニットテストフレームワーク(まだ使ったことない。個人的備忘録)
https://github.com/jenkinsci/JenkinsPipelineUnit

最後に
1ヶ月以上ブログ更新が滞ってしまいましたが、次もまだ未定でございますm(__)m
もう少し落ち着いたら、平常運転に戻していきたいなーと思ってます。


2017年8月8日火曜日

[CI] Scrutinizer 始めました



今回紹介する CI サービスは Scrutinizer です。
Pricing をみるとフリープランはないように見えますが、OSS であればフリーで使えるようです

今回、使い始めてから紹介できるようになるまでにかなーりの年月を費やしてしまいましたので、Sign up まわりは省略させていただきます。
(C++非サポート&Python のテスト周りで手間取った)

Scruntinizer の魅力
Scruntinizer の魅力は登録するだけですぐに静的解析の結果が得られるところです。
Scruntinizer は静的解析などの検証に特化した CI サービスで、めんどうな設定や YAML を書かずにすぐに始められます。テストもリポジトリを探索して自動で実行してくれます。

あと、レポートもグラフィカルでいい感じです。


使用例
いつもであれば、iutest の使用例で紹介するのですが、C++ は非サポートなので、
今回は「ブログズミ: ソースコード中の単語からの略語/スペルミス検出に挑戦」で作成した
taggertool リポジトリで紹介します。

リポジトリ登録
まずは、リポジトリの登録から始めます。
「Add Repository」ボタンを押すと、以下のような画面になるので、CI したいリポジトリを入力、言語を選択して、登録します。


リポジトリは、Github/Bitbucket/GitLab/PlainGit から選択できます。
Plain Git が可能なので、独自リポジトリが使えるのは良いところだと思います。

登録は以上です。
完了すると最初のテストが実行されます。

taggertool の結果
taggertool の結果はこんな感じです。

サマリー


Issues に、各静的解析で出た結果が出ます。


Code にはクラスおよび関数のサイズと複雑度がリストアップされます。


Inspections はキックされたジョブが並びます。


Reports には最後に実行されたジョブの結果が表示されます。


最後に、Statistics には Quality Rating や issue などの推移がグラフで確認できます。
Quality Rating は上の図で 9 となっているやつで、コードの複雑度、結合度など複数の要素から1つのスコアにしたもので、10点満点で評価されます。


チェック項目を増やす
さて、Scrutinizer には様々なツールで様々な解析ができる準備がされていますが、デフォルトでは多くのチェックは無効になっています。
チェックを有効にするには、Settings の Configuration に Checks ボタンがあるので、そこを開きます。


開くと Not Enabled なチェック項目がリストアップされているので、
必要なものにチェックを入れてください。


チェックの有効化は Congiguration の Repogitry Config や yml に直接書くこともできます。
チェックしたい項目が多い場合は、(UI でチェックするのが面倒なので)こちらの方がよいでしょう。

また、グローバルな設定も作成できるので、
複数プロジェクトで同じチェックをさせたい場合は、そちらを使うと良さそうです。
checks:
    python:
        code_rating: true
        duplicate_code: true
        variables_used_before_assignment: true
        variables_unused_wildcard_import: true
        variables_unused_variable: true
        variables_unused_import: true
        variables_unused_argument: true
        variables_unpacking_non_sequence: true
        variables_undefined_variable: true
        variables_undefined_loop_variable: true
        variables_undefined_all_variable: true
        variables_unbalanced_tuple_unpacking: true
        variables_redefined_outer_name: true
        variables_redefined_builtin: true
        variables_redefine_in_handler: true
        variables_no_name_in_module: true
        variables_invalid_all_object: true
        variables_global_variable_undefined: true
        variables_global_variable_not_assigned: true
        variables_global_statement: true
        variables_global_at_module_level: true
        typecheck_unexpected_keyword_arg: true
        typecheck_too_many_function_args: true
        typecheck_redundant_keyword_arg: true
        typecheck_not_callable: true
        typecheck_no_value_for_parameter: true
        typecheck_no_member: true
        typecheck_missing_kwoa: true
        typecheck_maybe_no_member: true
        typecheck_duplicate_keyword_arg: true
        typecheck_assignment_from_none: true
        typecheck_assignment_from_no_return: true
        string_truncated_format_string: true
        string_unused_format_string_key: true
        string_too_many_format_args: true
        string_too_few_format_args: true
        string_mixed_format_string: true
        string_missing_format_string_key: true
        string_format_needs_mapping: true
        string_constant_anomalous_unicode_escape_in_string: true
        string_bad_str_strip_call: true
        string_constant_anomalous_backslash_in_string: true
        string_bad_format_string_key: true
        string_bad_format_character: true
        open_mode_bad_open_mode: true
        miscellaneous_fixme: true
        newstyle_bad_super_call: true
        logging_unsupported_format: true
        logging_too_many_args: true
        logging_too_few_args: true
        logging_not_lazy: true
        logging_format_truncated: true
        imports_wildcard_import: true
        imports_relative_import: true
        imports_reimported: true
        imports_import_self: true
        imports_import_error: true
        imports_deprecated_module: true
        imports_cyclic_import: true
        format_unnecessary_semicolon: true
        format_trailing_whitespace: true
        format_superfluous_parens: true
        format_old_ne_operator: true
        format_multiple_statements: true
        format_mixed_indentation: true
        format_missing_final_newline: true
        format_lowercase_l_suffix: true
        format_line_too_long:
            max_length: '100'
        format_bad_whitespace: true
        format_bad_indentation:
            indentation: '4 spaces'
        format_backtick: true
        exceptions_raising_non_exception: true
        exceptions_raising_string: true
        exceptions_raising_bad_type: true
        exceptions_pointless_except: true
        exceptions_notimplemented_raised: true
        exceptions_catching_non_exception: true
        exceptions_broad_except: true
        exceptions_binary_op_exception: true
        exceptions_bare_except: true
        exceptions_bad_except_order: true
        design_interface_not_implemented: true
        design_abstract_class_not_used: true
        design_abstract_class_little_used: true
        classes_valid_slots: true
        classes_super_init_not_called: true
        classes_signature_differs: true
        classes_protected_access: true
        classes_non_parent_init_called: true
        classes_non_iterator_returned: true
        classes_no_self_use: true
        classes_no_self_argument: true
        classes_no_method_argument: true
        classes_no_init: true
        classes_missing_interface_method: true
        classes_method_hidden: true
        classes_interface_is_not_class: true
        classes_bad_staticmethod_argument: true
        classes_bad_mcs_method_argument: true
        classes_bad_mcs_classmethod_argument: true
        classes_bad_context_manager: true
        classes_bad_classmethod_argument: true
        classes_attribute_defined_outside_init: true
        classes_arguments_differ: true
        classes_access_member_before_definition: true
        classes_abstract_method: true
        basic_yield_outside_function: true
        basic_useless_else_on_loop: true
        basic_unreachable: true
        basic_unnecessary_pass: true
        basic_unnecessary_lambda: true
        basic_star_args: true
        basic_return_outside_function: true
        basic_return_in_init: true
        basic_return_arg_in_generator: true
        basic_pointless_string_statement: true
        basic_pointless_statement: true
        basic_old_raise_syntax: true
        basic_not_in_loop: true
        basic_nonexistent_operator: true
        basic_missing_reversed_argument: true
        basic_missing_module_attribute: true
        basic_missing_docstring: true
        basic_lost_exception: true
        basic_init_is_generator: true
        basic_function_redefined: true
        basic_expression_not_assigned: true
        basic_exec_used: true
        basic_eval_used: true
        basic_empty_docstring: true
        basic_duplicate_key: true
        basic_duplicate_argument_name: true
        basic_dangerous_default_value: true
        basic_bad_reversed_sequence: true
        basic_assert_on_tuple: true
        basic_abstract_class_instantiated: true

最後に
Scruntinizer は、最初から静的解析ツールが用意されており、それを目的にするのであれば、
通常の CI サービスよりも、とても簡単に恩恵が得られるのでオススメです。
(C++ がサポートされるともっとステキですが…あ、あと Scruntinizer のスペルが全然覚えられない…

今回は Python で利用しましたが、他の言語で何か作るときは、また利用したいなと思います。

以上。