2020年12月29日火曜日

【技術書典10】「詳解 Integromat iPaaS 完全入門」の販売を開始しました

 こんにちは。
表題の通り、技術書典10 で「詳解 Integromat iPaaS 完全入門」の販売を開始しました。


Integromat は IFTTT や Zapier などと同じ iPaaS で様々なサービスと連携して自動化ロボットを作れるサービスです。
本書では Integromat の基本機能の解説と連携サービスから一部をリストアップしています。

Integromat は私自身お気に入りのサービスなのでユーザーが増えると嬉しいなと思っております。
RPA/iPaaS の入門の一冊として検討していただけたら幸いです。

本書は GitHub にてコンテンツ以外を公開しております。
本書へのフィードバックはこちらへお願い致します。

https://github.com/srz-zumix/book-integromat


2020年12月22日火曜日

[C++] Clang ではオーバーロードされた private 関数に明示的な実体化時のアクセスができない?

※この記事は C++ Advent Calendar 2020 22日目の記事です。

はじめに

過去に本ブログでも紹介した template の明示的実体化時に private メンバーアクセス可能な仕様を利用した private メンバー変数・関数へのアクセスですが、最近それを使っていて clang だけとある条件でアクセスできないことに気づきました。

この挙動が仕様として正しいのか正しくないのかは筆者ではわからないので、実挙動ベースの話になってしまいますことをご了承ください。

過去の記事

ブログズミ: [C++] Private な関数のテスト
ブログズミ: [C++] 本当に private なところ

サンプルコード

こちらは iutest の private メンバーのテストのための機能を使ったサンプルです。
Wandbox 用に圧縮したソースコードを使ってますので、実装を確認したい場合はこちらを御覧ください。
https://github.com/srz-zumix/iutest/blob/master/include/iutest_prod.hpp#L62

#define IUTEST_USE_MAIN
#include "iutest.hpp"

class A
{
public:
    int GetX(void) { return m_x; }
private:
    int m_x;
};

IUTEST_MAKE_PEEP(int A::*, A, m_x);

IUTEST(Peep, Test1)
{
    A a;
    IUTEST_PEEP_GET(a, A, m_x) = 42;
    IUTEST_EXPECT_EQ(42, a.GetX());
    IUTEST_EXPECT_EQ(42, IUTEST_PEEP_GET(a, A, m_x));
}

IUTEST(Peep, Test2)
{
    A a;
    IUTEST_PEEP(A, m_x) x(&a);
    x = 54;
    IUTEST_EXPECT_EQ(54, a.GetX());
    x += x;
    IUTEST_EXPECT_EQ(108, a.GetX());
    IUTEST_EXPECT_EQ(108, x);
}

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ
https://wandbox.org/permlink/2ZPvpUz1zDe1KHHs

ポイントは IUTEST_MAKE_PEEP と IUTEST_PEEP_GET です。
IUTEST_MAKE_PEEP で private メンバーアクセスするための情報をセットアップし、IUTEST_PEEP_GET で実インスタンスの private メンバーへの R/W を実現しています。

問題のコード
class Hoge
{
    int x;
public:
    Hoge() : x(42) {}
private:
    int GetX() { return x; }
    
private:
    int gX() { return x; }
    int gX() const { return x; }
    int gX(int) { return x; }
};


IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, GetX);
IUTEST_MAKE_PEEP(int (Hoge::*)(), Hoge, gX);

int main()
{
    Hoge hoge;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, GetX)() << std::endl;
    std::cout << IUTEST_PEEP_GET(hoge, Hoge, gX)() << std::endl;
}

Clang の場合はエラー
https://wandbox.org/permlink/roGkNKKwsnaLX7og 
GCC の場合は OK
https://wandbox.org/permlink/AWd5A19WWDznccfq

エラーとなるのは gX 関数の PEEP で、オーバーロードされた関数があるとダメなようです。
Visual Studio はバージョンによって static メンバー関数がダメだったりするのは認識してましたが、 clang でもうまくいかないケースがあることがわかりました。

この挙動に関してなにか進展があったら、追記したいと思います。

では。


2020年12月14日月曜日

[DockerHub] AutomatedBuild でバージョンタグを自動でつける

DockerHub のイメージを見てるとタグがいっぱいついてるリポジトリがありますよね。
あとは latest が最新バージョンのタグと同じになってたり、Ubuntu の xeinal -> 16.04 みたいに名前付けされてたり、バージョンがメジャー、マイナーまでになっていてそのバージョンの最新を指していたり(例: v1 -> v1.3 -> v1.3.2)、とか。



こういうのを AutomatedBuild 管理するのは面倒くさそうだなと思ってましたが、そんなことはありませんでした。

hooks で AutomatedBuild をカスタマイズできる
DockerHub AutomatedBuild では Dockerfile と同じディレクトリに hooks ディレクトリを作成し、post_build や post_push ファイルを配置することでビルドをカスタマイズできます。カスタマイズできるポイントは↑の公式ドキュメントを参照してください。

post_build や post_push では bash スクリプトを書くことができ、docker コマンドも使用できます。ビルドしたイメージを実行したり、AutomatedBuild で設定したタグ以外をつけたりできます。

バージョンタグを自動でつける
post_build のタイミングでビルド済みのイメージを実行し、バージョンを取得すればタグ付けが自動化できます。
 
#!/bin/bash
# post_build
VERSION=$(docker run --rm ${IMAGE_NAME} --version)
docker tag ${IMAGE_NAME} ${DOCKER_REPO}:${VERSION}
docker push ${DOCKER_REPO}:${VERSION}
最後に
とあるツールをインストールした Docker イメージを作ることがちょくちょくありますが、ここれからは hooks 使って管理楽ちんにしたいと思います。

ではでは。

2020年12月8日火曜日

Zapcc を使った複数プログラムの並列ビルドでハマった話

※この記事は C++ Advent Calendar 2020 8日目の記事です。

Zapcc とは

zapcc は clang ベースのキャッシュを利用した高速な C++ コンパイラーです。
zapcc はサーバープロセスのメモリ上にキャッシュを構築して高速化します。
ヘッダーファイルの解析結果や template のインスタンス化などがキャッシュされます。

プリコンパイルヘッダーを使うよりも生成されたコードもキャッシュされるので高速です。
類似のツールで ccache というキャッシュツールがありますが、こちらは翻訳単位ごとにキャッシュする仕組みなのでフルビルドのときはキャッシュ生成するだけでキャッシュの恩恵を受けられませんが、 zapcc の場合は同じヘッダーファイルを include してるファイルで、template インスタンス化などのキャッシュが利用されるためフルビルドでも高速になります。

また、zapcc サーバープロセスがいる間は別のプログラムのコンパイル時でもキャッシュ利用可能なので複数のプログラムをビルドする際も高速になります。

導入は簡単でビルド・インストール後、 CXX=zapcc++ とするだけで使えます。
自作の C++ テスティングフレームワーク iutest のテスト環境として zapcc インストール済みの Docker を用意してるので、よろしければそちらからでも試せます。
https://hub.docker.com/r/srzzumix/zapcc

ハマったこと

zapcc はビルドを高速に行うためにキャッシュをサーバーに蓄えます。
キャッシュはサーバープロセスが生きてるうちは有効です。
つまり、1つの実行ファイルをビルドするときだけでなく、その後に別プログラムをビルドする場合にもキャッシュが有効になります。
ライブラリの大量にあるテストプログラムをビルドするときには、このキャッシュがとても有効に働くと思います。

筆者が開発している iutest でも、複数のテストプログラムがあるのでビルド時間が短縮されるのを期待しましたが、結果は「テストの失敗」でした。

何が起きたか。

ビルドは特に問題なくできているように見えました、しかしながらテストは失敗している。
どうやらテストが失敗するのは、デフォルト設定ではなくテスト用に機能の有効化・無効化をしているテストでした。
iutest はコンフィグマクロを定義することで任意の機能を有効にしたり、無効にしたりするのですが、これが zapcc と相性最悪でした。。

どうやら、以下のようにとあるテストでコンフィグを変えても、キャッシュされたヘッダーファイルを利用してしまうため、#define が伝わっていないことがわかりました。

#define IUTEST_HAS_VARIADIC_TEMPLATES   0
#include "iutest.hpp"
  
対策

並列ビルドしているとキャッシュされたヘッダーを利用してしまうため、直列にしました。 -j4 とかせず -j1 を指定。
はい。もこの時点で Zapcc の恩恵を捨てています。いやむしろビルド時間的には悪化する場合も考えられます。。。

次に、キャッシュサーバーのプロセスが生きたままになっているので、1プログラム作る度に kill するようにしました。。。

Makefile はこんな感じになりました。

ifeq ($(CXX_NAME),zapcc++)
BUILD4ZAPCC=pkill zapcc++; sleep 1
endif

$(TARGETS1) : $(OUTDIR)/% : %.cpp $(IUTEST_HEADERS) $(MAKEFILE)
	$(BUILD4ZAPCC)
	$(CXX) $(IUTEST_INCLUDE) $(CXXFLAGS) -o $@ $< $(LDFLAGS)

なんか無理くりですが、 iutest はビルド速度改善を目的に zapcc を使っているわけじゃなく、zapcc コンパイラで不具合がないか検証するために使っているので、これでもまぁいいのです。。

最後に

zapcc はすごいけど万能ではなかった。



2020年12月1日火曜日

[C++] Concepts で外部ライブラリの template よりも優先されるオーバーロード関数を書く

※この記事は C++ Advent Calendar 2020 一日目の記事です。

はじめに

 C++20 で Concepts が導入されました。
コンセプト - cpprefjp C++日本語リファレンス

コンセプトはテンプレートパラメータを制約する機能で、「コンセプトによって関数オーバーロードやテンプレート特殊化」ができます。
今までテンプレート関数のオーバーロードを書く場合は SFINAE などのテクニックを使って書いていたと思いますが、コンセプトで書きやすくなりました。
これも大きな変化の1つですが、コンセプト関数が通常の関数よりも優先して lookup されるのも便利になった点の1つです。
コンセプトによるオーバーロードの場合、コンセプト関数が通常の関数よりも優先して lookup され、要件を満たすコンセプト関数がなかったら他の候補を探しに行きます。SFINAE では優先順位がつけられないケースでもコンセプトなら可能になりました。

どういうこと?
SFINAE では解決できなかった優先順位問題とコンセプトを使った実装の例

↑こちらは、std::cout << できない型の場合は "unknown" を出力するようにしようとしている様子です。

donot-change.h には std::cout するだけの template 関数 print があります。
こちらは変更ができない想定です。(外部ライブラリとか)

SFINAE.cpp では頑張って、 std::cout ができない場合で特殊化しオーバーロードしようとしてます。他の書き方を書いたりもしましたが、どうしても ambiguous になってしまって条件を満たすことができませんでした。

一方 Concepts.cpp は printable ではないコンセプト制約でオーバーロードするだけで実現できています。
すごく簡単ですね。

ちなみに
ちなみに donot-change.h を変更可能とした場合は、以下のように書くことができます。
namespace printer_internal
{
template<typename Elem, typename Traits, typename T>
::std::basic_ostream<Elem, Traits>& operator << (::std::basic_ostream<Elem, Traits>& os, const T&)
{
    return os << "unknown";
}
}

// 解決順序
// foo::operator <<
// ::operator <<
// ::printer_internal::operator <<
template<typename T>
void print(const T& val)
{
    using namespace ::printer_internal;
    ::std::cout << val << ::std::endl;
}
これは ADL の解決順序を利用して実現しています。
[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ https://wandbox.org/permlink/rlQoH37cvYTI23qo 
使い所は?
例でも示したとおり、オーバーロードしたい対象の関数を変更できるのであれば、そちらで解決する方法を模索するのが良いと思います。
ただ、外部ライブラリなど変更することができない場合、非侵入的に解決する方法として覚えておくと役に立つ日が来るかもしれません。

実例
そもそも私がなんで外部ライブラリの挙動をオーバーロードで変更したいと思ったのかというと、以下の理由でした。

* Google Test はアサーションが失敗すると、そのときの値を出力します
* std::cout できない場合はバイト列を出力します
* できない場合の対応は「ちなみに」の ADL を利用した方法で実現されています
* 古い Google Test ではこの機能がない
* 自作テスティングフレームワーク iutest は Google Test と互換性がある
* iutest は Google Test の拡張機能としての一面もある
* 古い Google Test と iutest の組み合わせでも不明な型を printable にしたい
* Google Test 側のコードは書き換えられない
* どうしよう

実際にコンセプトで対応してる部分はこちらになります。
最後に
教えていただいた いなむのみたま(@mitama_rs) 先生ありがとうございました。
ちなみにそのツイートにもぶら下がってますが、C++20 未満のコンパイラでこの問題を解決する方法も募集しておりますmm


2020年11月26日木曜日

[C++] -Weverything で得たもの


こちらで紹介した C++ 警告のまとめプロジェクトの作成にあたって、自作テスティングフレームワークの iutest で clang のすべての警告を有効にするオプション「-Weverything」を使って得た知見をまとめます。

-Wdouble-promotion

double 型テストしてたつもりが float になってたのに気づきました。

-Wextra-semi

なぜか二重についてた ; セミコロンに気づきました。

-Wnonportable-system-include-path

Windows 系のヘッダーが全部小文字だったのを修正しました。

-Wshadow-all

マクロ内で使っていた変数名が b とか info とかかぶりやすい名前だったのを修正しました。

-Wdocumentation-unknown-command

こちらはワークアラウンドの紹介になりますが、 Clang は Doxygen のコメントに対しての警告がありますが、対応していない Doxygen コマンドが存在します。

Diagnostic flags in Clang — Clang 12 documentation

その場合、コンパイルオプションに -fcomment-block-commands=private,internal,retval のようにコマンドを教えてあげることができます。
ただし、引数のない private や internal コマンドは別の -Wdocumentation 警告がでるようになってしまいます。

../include/internal/iutest_time.hpp:47:13: error: empty paragraph passed to '@internal' command [-Werror,-Wdocumentation]
 * @internal
   ~~~~~~~~~^

こちらの回避方法はまだ見つけてないので、見つけたら追記します。

以上。


2020年11月16日月曜日

[CI] TeamCity Cloud OpenBeta を使ってみた

 TeamCity のクラウドサービスが始まるようでそのオープンβがやっていたので使ってみました。
TeamCity Cloud



一般リリースは年内を予定しているようです。
登録
まずは TemaCity Cloud にアカウント登録しましょう
トップページからインスタンス名と登録するメールアドレスを記入して「Sign Up」を押し、インスタンスの招待状が届くのを待ちます。



招待状が届いたら、アカウント登録に進みます。
今回は GitHub アカウントで登録します。特に気をつけることなく進めて OK です。

利用規約に同意したら登録完了です。





プロジェクト作成
アカウント登録できたら、最初に決めた「インスタンス名.beta.teamcity.com」が開きます。
ダッシュボードが出るのでプロジェクトを作成しましょう。




GitHub のリポジトリ一覧が出るので CI したいリポジトリを選択します。
今回は C++ 自作テスティングフレームワークの 「iutest」を選択します。
選択すると verify が始まるので少し待ちましょう。



verify 完了すると以下の画面になるので、名前を決めて Proceed します。

ビルドステップの設定では、リポジトリを解析してビルドコンフィグらしきものを自動で収集してくれます。
ビルドスクリプトなどがあればリストアップされるので、ビルドしたいコンフィグを選択しましょう。



iutest は複数プロジェクトファイルがリポジトリに入ってるのでたくさん出てきました。
ビルドコンフィルを選択すると自動でビルドステップが作成されます。
この時点でテスト実行可能になります。

特にない場合は手動でビルドステップを設定します。

iutest では最初 VS2019 のプロジェクトを選択したのですが、 "Microsoft.Cpp.Default.props" がなくてビルド失敗してたので、別のテストをするようにしました。
次の項目で設定した手順をまとめます。

Google Test 互換性テストを構築する
今回ちょうど Wercker でやっていた Google Test 互換性を引っ越したいと思っていたので、そちらを移植したいと思います。

Google Test 互換性テストでは Google Test セットアップ済みの Docker image を使って、ビルドとテストを行います。任意の Docker コンテナ上で処理をする方法が複数あるので紹介します。

Docker runner を使う方法
Docker runner でビルドステップを作成します。
「Runner type」 に「Docker」を選択し、 「Docker command」は「other」を選択します。「Command name」は「run」です。

あとは「Additiona arguments for the command」に docker run コマンドの引数を設定します。 チェックアウトディレクトリが「%system.teamcity.build.checkoutDir%」なのでそこをマウントしましょう。
また Docker run コマンドは実際にはラッパーを経由するようで、「--rm」オプションをそのラッパーが必ずつけるので不要なようです。

Command Line runner を使う方法
Command Line runner でビルドステップを作成します。
「Runner type」 に「Command Line」を選択し「Run step within Docker container」にイメージを設定します。
あとはやりたい処理を「Custom script」に書くだけです。
(「Additonal docker run arguments」に docker run のオプションを設定できるので、Docker runner と同等に使えると思います)

複数の処理を行う場合は Command Line runner を使ったほうが良さそうです。

設定は以上です。
これで Docker イメージを使ってビルド・テストの準備ができました。
プルリクエストでトリガーする
TeamCity Cloud では他の CI サービスと違ってデフォルトでは PR をトリガーにジョブがキックされません。「Build Features」で設定を追加する必要があります。

プロジェクト設定の「Build Features」を開いたら Add します。
Features に「Pull Requests」があるので選択し、必要な項目を設定しましょう。
「VCS Root」に GitHub のリポジトリを選択
「VCS hosting type」を「GitHub」にすると追加の設定項目が出てきます。

「Token」は GitHub で Personal Access Token を作って設定します。
権限は「public_repo」もしくは「repo」が必要になります。
iutest は public なので「public_repo」権限のトークンを設定しました。
「public_repo」の場合はコミットステータスにレポートするためには「repo:status」も必要になるので注意してください。

「By authors」で対象とする PR の範囲を設定します。
iutest では特に制限必要ないので「Everybody」を設定。


以上で設定完了です。「Test connection」で接続確認したら Save しましょう。 
これで PR が来るとビルドが実行されるようになりました。
また、GitHub のコミットステータスに結果を表示するには「Build Features」に「Commit status publisher」を追加してください。こちらも Personal Access Token が必要です(同じトークンで問題ないです)。


設定の仕方は公式ブログでも紹介されています。そちらも参考にしてみてください。

DockerHub login
DockerHub の pull 制限に対応するためにログインしておきます。
まずは、プロジェクト設定の「Connections」で「Docker registry」を選択して「https://docker.io」のアカウントを登録します。(パスワードはアクセストークンで ok)
接続確認して保存しましょう。


続いて、「Build Features」で「Docker Support」を追加します。
レジストリに先程接続した設定を追加しましょう。

設定は以上です。
バッジ
では、パイプラインが完成したのでバッジをつけましょう。
Markdown の場合は以下のようになります。
[![TeamCity Cloud Build Status](https://iutest.beta.teamcity.com/app/rest/builds/buildType:Iutest_GoogleTestCompatibleTest/statusIcon?guest=1)](https://iutest.beta.teamcity.com/viewType.html?buildTypeId=Iutest_GoogleTestCompatibleTest&guest=1)
このままだと自分以外はステータスが見られないので、ゲストアカウントにログイン権限をつけます。「Administration」の「Authentication」に「Guest user login」の項目があるのでチェックを入れましょう。


このように表示されます。

※ブランチごとに表示をしたかったのですがサーバーの設定が必要なようなのでクラウド版では現状できなそうでした。

改善したいところ
TeamCity Cloud で現状可能かわかりませんが以下の対応ができると嬉しいなと思ってます。

* Matrix Build
現状バージョン違いのビルドステップをコピーしているが、マトリックスにしたい。

* as Code

最後に
TeamCity は他の CI as a Service と比較すると設定することが多い印象でした。
その分拡張性も高い感じがするので、Jenkins おじさんを少し思い出しました。
ただ、オンプレではなくクラウド版でどこまで拡張して使えるのかはわからないのと、まだオープンベータであり、料金体系や制限がどうなってくるかが気になるところです。

とはいえ、一般リリースまでまだ少し期間があるのでそれまで使わせていただこうと思います。
一般リリースされたら、パイプラインをより精査していきたいと思います。
では。

2020年11月10日火曜日

Travis CI の新プランについて

 The Travis CI Blog: The new pricing model for travis-ci.com

Travis CI の新しい料金プランが 2020/11/02 より始まり、あっという間にクレジットを使い切りました。


新しいプランでは 10,000 クレジットが毎月与えられ、それを消費するスタイルですが、圧倒的に足りない・・

こちら↑はブログからの抜粋ですが、マイニングとかに悪用されたのが理由のようです。
制限かかっても仕方がないな…とは思います。
が、今まで CI サービスの中でも制限ゆるい方だったのが、一気にキツめの部類になったので辛いですねぇ…
まぁ、今まで無料だからと気にせずマトリックス組んでましたが、このままではキツイので体制を見直すことにしました。(自作 C++ テスティングフレームワークの iutest で主に使ってて、複数パターンでテストしてました↑)
ただ、それでも 10,000 クレジットはあっという間になくなってしまうと予測されるので、サポートに OSS クレジットを申請してみました。

結果が来たら追記したいと思います。

Travis CI のかわりにオススメの CI サービスは?
さて、これを機に Travis CI から引っ越しする方も多いと思います。
GitHub Actions に移る方が多そうですが、別のサービスもオススメしておきます。

  • CircleCI
    まぁこれは知ってる人も使ってる人も多いと思うので、こっちに移る人も多いかも。
    OSS プランであれば 400,000 クレジット使えます。
    iutest の 2020/10 月の利用結果はこちら。まだ余裕あり
  • Drone.io
    Drone (Cloud)は OSS であれば完全フリーで使えます。
    並列数とか制限ありません(ただし、リソースは限られてる)
    iutest では gcc/clang の各バージョンでのテストをしています。
  • Azure Pipelines
    GitHub Actions よりは少ない 10 並列ですが、それでも強力な CI サービスです。
    GitHub Actions は(まだ)YAML のアンカー・エイリアスに対応していないので、独自のテンプレート構文が使える Azure Pipelines のほうが、マトリックスは組みやすいと思います。
    Travis CI でマトリックス組んでた人にはオススメです。
  • その他
    iutest では他にもたくさんの CI サービスを利用しているのでよければ参考にしてください。
最後に
DockerHub の pull rate limit の対応をしてたんですが、これまたインパクトのデカイ変更でした。。。このような CI サービスの悪用は他のサービスでも起こりそうな気がしてますが。。。今後の CI as a Service はどうなっていくんでしょうね。。。

2020年11月2日月曜日

Docker login しているか確かめる方法

前置き

 ダウンロードレート制限 | Docker ドキュメント

いよいよ DockerHub の Download Rate Limit が始まりましたね。
この制限は徐々に導入していくとありますが、さてどんな状況でしょうか?
(この記事は 11/1 に書いています)

特に懸念されていたのは CI サービスでの制限です。
DockerHub にログインしていない場合は IP に対して制限がかかるため、利用者の多いサービスではあっという間に上限越えて、制限がかかってしまうことが予想されました。
これに対し、すでに(期限付きではありますが)制限を受けないようにする交渉が完了しているサービスもあります。

DockerHub による2020/11からのコンテナイメージ Pull 回数制限のCircleCIへの影響 - Build Environment - CircleCI Discuss

ある程度猶予があるかもしれないですが…
何れにせよ、今後 DockerHub からイメージを pull して CI を回す場合は、事前に DockerHub へのログインをするようにパイプラインを更新しておくのが良さそうです。

それらへの対応方法についても、記事冒頭のドキュメントからリンクが貼られていたり、各 CI サービスから案内が出ていると思います。

筆者が開発している C++ テスティングフレームワークの iutest はめちゃくちゃたくさん CI サービスを使っているので(Docker 関係ないものもあるので全部ではないが)絶賛対応中です。

対応方法はログインするだけなんですが、各サービスやり方が異なるのでここでは対応方法は省略します。
一応、状況はこちらの issue で確認できます。
https://github.com/srz-zumix/iutest/issues/519

Docker login しているか確かめる方法

で、ようやく本題。
このログイン対応をしていて思ったのは、「設定したけど本当にログインした状態で pull できているのかをどう確認したらわからなくて不安」でした。

docker のコマンドに「それ」を確認するものがあればよかったのですが、なさそうだったので以下の方法で確認しました。

echo a | docker login

ログイン済みなら以下のように成功となります。

$ echo a | docker login
 Authenticating with existing credentials...
 Login Succeeded
$ echo $?
 0
ログインしてない場合は以下のように失敗になります。
$ echo a | docker login
 Error: Cannot perform an interactive login from a non TTY device
$ echo $?
 1
最後に
この方法をパイプラインに組み込んでみてないので、うまく CI 上で確認できるか未確認ですが、もっと簡単に確認できると嬉しいなと思います。もっと良い方アレば教えて下さい。
てか、直球なコマンドが欲しい。。

2020年10月26日月曜日

[C++][IWYU] Include What You Use CL を VS2019 対応しました

include-what-you-use-cl を VS2017/VS2019 に対応しました。
include-what-you-use-ci (以下 IWYU-CL) は include-what-you-use (以下 IWYU) を Visual Studio のプラットフォームツールセットとして選択できるようにするツールです。
プラットフォームツールセットとすることでプロジェクトの設定(インクルードパスなど)をそのまま利用して IWYU をかけることを目的に作りました。
VS2017 から VS{version}COMNTOOLS 環境変数がなくなったりと、インクルード関連の構成が一新されてから更新が滞ってましたが、最近 vswhere の存在を知り更新することにしました。

あと同僚に突っ込まれたので README も更新して、使い方を書きました。

Include-What-You-Use-CL

Include-What-You-Use-CL is Visual Studio toolset for Include-What-You-Use

Dependency

Include-What-You-Use

Install

git clone https://github.com/srz-zumix/include-what-you-use-cl.git
cd include-what-you-use-cl
install.bat

Usage

  1. Project Settings > Platform toolset
    Select "Include-What-You-Use" toolset
  2. Compile
  3. Get Include-What-You-Use result
    output

Uninstall

uninstall.bat

IWYU は cpplint にも組み込まれてたりするようなので、わざわざ cl から呼ぶ必要性はない気もしますが。。
お手軽に試せるので IWYU-CL も試してみてくださいmm

今回は以上です。
では。

2020年10月21日水曜日

lizard で C++ コードメトリクス

今の会社に来てから OS が Windows とは限らない。むしろ macOS が多くなったので CCCC の代わりに lizard を使ってみました。

インストール
pip install lizard
で終わりです。
使い方
ヘルプ見たらだいたい分かると思いますが、パス指定したら解析してくれます。
-l で言語指定ができます。(e.g. -l cpp)

--xml で cppncss xml 形式で print されるのでファイルに出力したら Jenkins でも簡単に可視化できます。

--html で HTML レポート出力もできるのでさっと確認したい人はこれで見ると良いでしょう。
iutest の結果
lizard 入りの Docker image 作って GitHub Actions でレポートを取ってみました。
作成したイメージはこちらです。 https://hub.docker.com/r/srzzumix/lizard

GitHub Actions の YAML は以下のようになります。
lizard で出力した HTML レポートを成果物として保存しています。
  lizard:
    runs-on: ubuntu-18.04
    needs: prepare
    steps:
    - uses: actions/checkout@master
    - name: Lizard
      uses: docker://srzzumix/lizard
      with:
        args: -o lizard.html --html ./include
    - name: Archive code metrics results
      uses: actions/upload-artifact@v1
      with:
        name: lizard.html
        path: lizard.html

実行結果はこのようになります。

成果物から HTML レポートをダウンロード可能です。



最後に
今回はメトリクスを集計するところまでをやりました。
xml を取得して閾値チェックなどできると良いかもしれません。
取得したメトリクスを利用する事例ができたら、また記事にしたいと思います。

今回は以上。では。

2020年10月12日月曜日

OpenSTF を Windows の Docker 上で動かす

CEDEC での講演もあって OpenSTF を使い始めた人も多いようなのでメモ。



講演でもお話ありましたが、 OpenSTF は DeviceFarmer に変わったそうですね。 (DeviceFarm と似てて検索とかしづらそう) 

OpenSTF のセットアップについては以下の記事が参考になります。

筆者もネットの情報を参考に立ち上げました。

OpenSTF 便利
OpenSTF はリモート操作のためのツールの印象が強いですが、開発者がローカルで実機確認するときにも便利です。
なぜなら、わざわざ端末を操作して社内システムにログインするためのユーザーID/パスワードの入力が必要なかったり、スクリーンショットも簡単に PC 側で取れちゃうからです。

Docker の勉強がてらローカル環境に立ててみることをオススメします。

docker-compose.yml と起動手順
使っている docker-compose.yml がこちら。コメントに手順も書いてます。


メモ
Windows でボリュームマウント
Windows だとホストマシンでマウントできる場所が限られてたりして面倒くさかったので、ホストマシンに DB の永続化をするのではなく、docker volume create したボリュームに永続化するようにしてます。(今はなんか Docker Desktop がいい感じにマウントできるようにする?って聞いてくれるので面倒くささ減ったみたいだけど)
端末が認識しない場合
adb サーバーが起動してないかも。
adb start-server をしてみてください。

端末を返却した際にインストールしたアプリをアンイストールしないようにする
デフォルト設定だと、OpenSTF で端末操作して返却するとその間の変更がクリーンナップされます。これはこれで便利なのですが、個人環境で利用する場合は不便にもなります。
クリーンナップしなくない場合は stf の起動オプションに  --no-cleanup を追加しましょう。
使ってみて困っていること・知りたいこと
たまに操作できない状態になる
USBの抜き差しで復旧したりするが、リモートワークな昨今、物理的な挿抜は難しい。
adb kill-server / start-server で復旧したりもする。
リモートで電源の通電操作が可能な機材(リブーター)が存在するので、それを使って AC 給電な USB-HUB の電源切断で、USB 挿抜をエミュレートできないかと思っている。(未検証)

ポートフォワーディング機能の使い方
端末上で実行しているアプリと特定ポートでお話できるかな?と思っているのだが、うまくいってない。機能を勘違いしているのかもしれないし、使い方・設定の問題かもしれない。

最後に
利用者が増えて知見が増えていくと嬉しいですね。
Airtest も便利なんでそっちも情報増えると嬉しい。(Android 10 になって minitouch 使えなくてツラミ)
以上。

2020年10月5日月曜日

GitHub Actions のコンテナに setup-python したときの error while loading shared libraries 対応


python: error while loading shared libraries: libpython3.8.so.1.0: cannot open shared object file: No such file or directory

GitHub Actions で setup-python 使って python のテストをしていたのですが、とあるときから上記エラーが出るようになっていたので、以下の修正で対応しました。

修正前
 
zapcc-basic-test:
    runs-on: ubuntu-18.04
    container: docker://srzzumix/zapcc
    needs: prepare
    steps:
    - uses: actions/checkout@master
    - uses: actions/setup-python@v2
      with:
        python-version: 3.8
    - name: zapcc test
      run: |
        make -C test clean
        make -C test showcxxversion
        make -C test check_stdlib
        make -C test -j1 IUTEST_REQUIRE_PYTHON=1
        make -C test test
修正後
zapcc-basic-test:
    runs-on: ubuntu-18.04
    container: docker://srzzumix/zapcc
    needs: prepare
    steps:
    - uses: actions/checkout@master
    - uses: actions/setup-python@v2
      with:
        python-version: 3.8
   #### ここを追加 ####
    - name: Set Python environment variable
      run: echo "LD_LIBRARY_PATH=${{ env.pythonLocation }}/lib" >> $GITHUB_ENV
   ################
    - name: zapcc test
      run: |
        make -C test clean
        make -C test showcxxversion
        make -C test check_stdlib
        make -C test -j1 IUTEST_REQUIRE_PYTHON=1
        make -C test test

setup-python が pythonLocation 環境変数をセットしてくれるのでそれを使って LD_LIBRARY_PATH を設定します。

以上。

2020/10/6 追記

set-env コマンドは Deprecated だったので修正しました。
GitHub Actions: Deprecating set-env and add-path commands - GitHub Changelog

修正前: echo '::set-env name=LD_LIBRARY_PATH::${{ env.pythonLocation }}/lib'
修正後: echo "LD_LIBRARY_PATH=${{ env.pythonLocation }}/lib" >> $GITHUB_ENV

2020年9月28日月曜日

Zenn とブログズミ

 Zenn が話題になっていたので自分も記事を書くことにしました。
本も書きたいなと思っています。

現時点で何個か記事を書きました。


今後について
さて、Zenn で記事を書いていくことにしましたが、このブログはどうするの?となるのでルールを決めました。

  • ブログズミ
    • 扱う分野の縛りなどなく、今まで通り特に変わらず投稿します。
  • Zenn

今後も本ブログともどもよろしくお願いします。

2020年9月25日金曜日

[C++] 警告のコンパイラー対応表を作り始めました

 srz-zumix/awesome-cpp-warning: c++ warning correspondence table (Clang/GCC and Visual Studio)

マルチプラットフォームやってると、Visual Studio (VC++) と clang で警告の制御方法が異なるので面倒くさいなーって思っていたので対応表を作りました。
(全部 clang にしたら楽なんですけどね・・・)



特に vc++ は C4096 とかの ID でコントロールするのでわかりにくいんですよね。
あとは当然、clang では警告になるけど、vc++ は警告ないとか。逆パターンとか、clang だとエラーとか、あるあるだと思います。
そんなマルチプラットフォーム開発のビルドエンジニア向けにまとめた(まとめている)ものが↑↑です。

とりあえず、VC++ の警告を一通りみてサンプルコードがあるものや、すぐに再現できたものに対してはこちらの表に記載してます。
https://github.com/srz-zumix/awesome-cpp-warning/blob/master/VCLIST.md



そして、おそらくみんなが欲しいのは clang/gcc の -Whogehoge 警告が vc++ だと ID いくつなのかって点だと思うので top にまとめてます。
(すべての警告を無視(よくないけど)したり、すべての警告を as error として直さなければならない環境ならあまり必要ないかも?)


今後も対応表を増やしていこうと思ってます。
もちろん PR 大歓迎です!!

今回は以上。では。

2020年9月22日火曜日

GitHub Sponsor のバッジを付ける方法

GitHub でプロフィールリポジトリを作ることで自由にカスタマイズできるようになったので、GitHub Sponsor のバッジを付けてみました。
https://github.com/srz-zumix




バッジは Shileds.io を使って生成してます。
やり方は↑こちらにありました。

https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=ff69b4&link=https://github.com/sponsors/srz-zumix

Markdown の場合は以下のようになります。
ユーザー名を自身の名前に変えて使ってください。
[![GitHub Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=ff69b4)](https://github.com/sponsors/srz-zumix)

2020年9月14日月曜日

[Re:VIEW Starter][Re:VIEW] 訳あって Starter から素の Re:VIEW に戻すツールをリリースしました

 技術書典9 が始まりましたね。
私は今回サークル参加しておりませんが、前回初めて参加しました。
来年また参加できたらいいなと思っております。

さて、そんな中今回は執筆環境周りのことを書きたいと思います。
技術書典9が始まったばかりですが、こちらはイベント後に役に立つ内容かと思うので、このタイミングでの公開としました。

紹介するのは表題のとおり、「Re:VIEW Starter」で作成された書籍をただの「Re:VIEW」で扱える状態にコンバートするツールです。
このツールがなぜ必要になったのか?はここでは省略しますが、この変換が必要になる人は今後も少なからず出てくるのではないかな?と思っております。
(私自身も今後の執筆にただの「Re:VIEW」を使うつもりはなく、「Re:VIEW Starter」や他の便利な環境を使いたいと思っているので、またお世話になることもあるかもしれません。)

Re:VIEW Retrovert

ツールは「Re:VIEW Retrovert」といいます。ruby で書かれていて gem install review-retrovert ですぐに使えます。
また、コードは GitHub にて公開中です。
https://rubygems.org/gems/review-retrovert
https://github.com/srz-zumix/review-retrovert

何ができるのか?

review-retrovert convert /path/to/dir/review-starter/config.yml <output directory>

Re:VIEW Starter のプロジェクトの config.yml から Re:VIEW のプロジェクトを生成して出力ディレクトリに書き出します。(Re:VEIW のバージョンは 3.2 です)
テストとして Re:VIEW Starter のテンプレプロジェクトを変換したものが GitHub Actions の成果物として残してあるので、どんな結果になるのかすぐ見てみたい人はダウンロードしてみてください。
https://github.com/srz-zumix/review-retrovert/actions/runs/201132608

制限事項

Re:VIEW Starter は Re:VIEW という名がついていますが、単なる Re:VIEW とはもう別物といっていいくらい便利な機能が拡張されています。
その分、Re:VIEW Retrovert ではこれらの拡張機能を Re:VIEW でも取り扱えるようになるべく、もとの状態を保つように頑張ってます。
ただ、どうしても全く同じ出力にすることはできません。
コンバート後は一通り目を通していただき、不自然な箇所や欠落した場所を調整していただく必要がありますのでご了承ください。

いくつか事例をあげておきます。

出力される Re:VIEW プロジェクトは version 3.2 を想定しています。
4 系が使いたい場合は issue 投げてください。(3.2 から 4.X へアップグレードできるかもしれないので、もしかしたら使えるかもしれません。)

まず Re:VIEW で表現できない命令は削除されます。
文字サイズや修飾はなくなるものと考えてください。(一部は類似の命令に置換します)


次に、ネストされたインライン命令は Re:VIEW では対応してないので、それぞれネストにならないように分解して出力しています。
また、テーブル中のインライン命令も安定しないため、テーブル中の @<br> は削除されます。
空のセルとして . を使用している場合に Re:VIEW の出力がなぜか2行になってしまっていたので、空のセルは . ではなくスペースに置換しています。

また、ブロック命令もネストできないので内側の命令は無視されるので注意してください。


他にもいろいろ無理やり対応しているところがあるので、もし使ってみておかしなところがあれば issue 出してください。
https://github.com/srz-zumix/review-retrovert/issues

最後に

もともとは自分用に書いたツールですが誰かの役に立てば幸いです。
執筆環境の制約はどうしても発生することがありますが、私としてはこのツールのおかげで安心して Re:VIEW Starter を使っていけるようになったかなと思います。

では。


2020/10/3 追記

ミスって gems に publish できてませんでしたmm
v0.9.1 から新しい Re:VIEW Starter に対応してます。
https://rubygems.org/gems/review-retrovert


2020年9月8日火曜日

[AppVeyor] fatal: reference is not a tree が出る場合の対応

AppVeyor に限らず git を使っていると遭遇するエラーかもしれませんが、AppVeyor でよく遭遇していて困ってたのでメモ。

原因としては「clone_depth: 1」としていることで、CI で実行されようとしているコミットハッシュが既に古く参照できないからのようなんですが、master の HEAD でも起きてる気がするんですよね。 


「New Build」をしても同じエラーになるので疑問が残るのですが、とりあえず 「clone_depth」をコメントアウトして対処しました。
ビルド時間を短縮する狙いで clone_depth を設定していたのですが残念です。

「それ以降はこのエラーに遭遇していません。」
と下書きに書いていたのですが、この記事を数ヶ月ストックしている間に再発しました。
おそらく、パスフィルターを導入して特定のファイルのみの変更はスキップするようにしたことが影響しているような気がしています。。

こちら、また進展があったら追記したいと思います。

今回は以上です。では。


2020年8月31日月曜日

wandbox-api の CLI に C/CPP/Go/JavaScript/Nim/OpenSSL/Perl/Python/Ruby/TypeScript を追加しました

 表題のとおりですが以前公開した wandbox-api
C/CPP/Go/JavaScript/Nim/OpenSSL/Perl/Python/Ruby/TypeScript のラッパーコマンドを追加しました。(以前の記事はこちら「ブログズミ: Wandbox の CLI ツールを作ってみた」)
それぞれ言語ごと特有のオプションやコンパイラオプション・ランタイムオプションが使用可能かどうかに対応しています。

また、C/CPP/C++ であれば #include してるファイル(システムヘッダー除く)を自動的にファイルリストに追加する機能がありますが、Python の import や Ruby の require なども対応をしています。

OpenSLL は少し特殊でローカルで openssl を使うのと同じように使えるように工夫してます。
(あんまりデバッグしてないので対応してないサブコマンドありそうですが・・)
例えば、以下のように鍵の作成が可能です。

> wandbox-ssl genrsa -out test.key 2048
> wandbox-ssl rsa -in test.key -pubout -out test.key.pub

需要があるのかわからないけど、openssl がインストールされてなくても python があれば openssl 相当のことができるようになりました。 

最後に

筆者が明るくない言語はファイルリストの自動登録機能が正しく動作してなかったり、対応してない構文があったりするかもしれません。
(実際、JavaScript/TypeScript の require は対応してないです)
ぜひ、PR いただけると嬉しいです。

ではでは。

2020年8月26日水曜日

[技術書典] Re:VIEW Starter でクローバー「♣」を別の文字に変更する

Re:VIEW Stater では節の装飾に「♣」(クローバー)が使用可能です。

技術系同人誌を書く人の味方「Re:VIEW Starter」の紹介 - Qiita

なんとなく個人的に「♣」がしっくりこなかったので、「技術書典8(技術書典 応援祭)」で書いた本では、別の文字に変更しました。
config-starter.yml では変更できないので、変更方法を備忘録として残しておきます。


方法
公開されている「Re:VIEW Starter ユーザーズガイド」に書いてあるとおりにするだけです。

sty/starter-section.sty に \clubsuit があると思いますが、ここの部分が「♣」表示している部分にあたります。
文字を変更する場合は、ここを直接変更することでも可能ですが以下のように対応します。
(技術書典8 のときは知らずに直接編集してた)

sty/mystyle.sty に下記を追加

\renewcommand{\starter@subsection@symbol}{$▶$}

diff を見ていただいたほうが早い気もするので、対応したコミットを載せておきます。

https://github.com/srz-zumix/ci-dex-book/commit/a38b35d279660778a6e8780346f7d2f8c4389e1e

フォントさえあれば LaTex の特殊文字・記号じゃなくても問題なさげ?
(電子書籍用 PDF では問題なさそうだったので "▶" を採用した)

今回は以上。
では。

2020年8月17日月曜日

[Doxygen] @page の名前には小文字を使おう

Doxygen の page コマンドの説明によると 「ページへの参照となる <名前> には、 すべて小文字 (mypage1 など) を使用するべきです」とあります。

iutest のドキュメントは GitHub Pages で公開しているのですが、この注意点を知らず 
/**
 * @page    CMDLINE     コマンドラインオプション
 * @par     Command Line Options
のように大文字を使っていました。

ただ、大文字でも特に問題なくドキュメントの生成はできますし、特に問題なく使えていると思っていました。
しかし、実は問題があったのでこの記事を書いているわけです。

名前を大文字にした場合のファイル名が問題だった
@page の名前を大文字にすると、アンダーバー(_) + 小文字に変換されて html ファイルが出力されます。
そして GitHub Pages ではデフォルトで jekyll が有効になっており、アンダーバー(_) で始まるファイルが URL 指定で直接開けず 404 になってしまっていました。。。

対処方法
アンダーバー(_)始まりのファイル名を修正する
Doxyfile の設定で CASE_SENSE_NAMES を YES にすると、文字の変換をせずそのままの名前で出力されるようです。
ただし、大文字小文字を区別しないファイルシステムでは問題になる場合があるので、ドキュメントが推奨するように全部小文字にするのが良さそうです。

GitHub Pages の jekyll を Disable にする
jekyll を無効にすればアンダーバー(_)始まりのファイルでも開けるようになります。
方法はこちらを参考にしてください。 GitHub ioでjekyllをdisableにする - adragoonaの日記
「.nojekyll」ファイルをルートに commit すれば ok です。
結果
今回は前者の方法で対応しました。

ちゃんとアクセスできるようになりましたね。