2019年9月17日火曜日

[Codefresh] Free Plan の内容がよくわからない・・

トップページの Pricing には Unlimited build / 1 small resource となっているが、
自分の今の Plan を見ると Free Plan ではあるが、120 build/month でマシンリソースはおそらく Medium resource になっている。

Doc:


My Plan:



120 build/month の制限は正直きついが、Samll resource になるのもきつい・・・

どっちがいいかってのはないのだが、正しい状態なのかよくわからないので正解が欲しい。
それに合わせて、パイプライン調整するので・・・

2019年9月13日金曜日

[CEDEC2019][感想] LUMINOUS ENGINE のログ分析と自動テストで提案されたリプレイ的自動プレイ手法について

一応仕事で行っているので、個人のブログにこういったことを書くのはほとんどしないのだが、
個人的に手詰まりを感じていた分野に対して、非常に興味深い手法が提示されたことと、どこかが実現してくれないかなーという気持ちを込めて、ブログに書き起こすことにした。


セッションについて
まずは、当該セッションについて簡単に説明をしておくが、
大規模開発のためのLUMINOUS ENGINE のログ分析と自動テスト
こちらのセッションではいくつかのトピックが出ていて、AI の詳しいことはさっぱりわからんので、このブログで書きたいことと関係のある部分だけ、かいつまんで書きます。
(詳細は資料(CEDiL)または今ならタイムシフトを見て下さいmm)

ズレを許容するリプレイ的自動プレイ
自動リプレイの実現方法としては、大きく分けて2つに分類できる。

* パッド入力を記録
* スクリプトで制御

パッド入力を記録する方式は、ゲーム非依存で録画したものを再生するだけで実現が可能。ただし、ゲームに依存しないのでゲーム特有の状態変化に弱い(乱数・FPS・演算誤差とか)
スクリプトで制御する方式は、ゲームに特化した制御ができるのでなんとでもなる。ただし、パッド入力方式ほどの手軽さがない。

セッションでは、パッド入力方式を軸に
リプレイがずれないように、がんばるのではなく、
一度ずれても、復帰できるように
がんばった方が、よさそう。
という考えから、マシンラーニングによるラーニングリプレイを実装されていました。(スゴイ)



個人的に、ゲームに依存してはいけない(できない)絶対条件でリプレイ方法を考えていたので、
この方式はすごく参考になった。

ゲームの情報に依存しない
個人的に素晴らしいなと思ったのは、ゲームにおける意味のある情報を要求しないでも実現できているところ。
入力に使われる値は、ゲーム内の意味のある情報ではありますが、AI はそれを認識しておらず、単なるデータ配列として扱っています。
出力は「キーパッドの入力」であるため、こちらもゲームの内容には一切関わらないものです。

セッションでは、リプレイの撮り直しもマシンラーニングで行っていました。(スゴイ)
ただ、こちらはゲームおける特定の状態が認識できた方が、よい結果が得られるようで、セッションでは壁との衝突を認識させていました。
ここで、ゲームから壁に当たったよーという情報をもらうことなく、入力はあくまでデータ配列のまま解決していたのが素晴らしいと思いました。


これをそのまんま使いたい
たぶん、このセッションを聞いた方の多くがこう感じたのではないか?と思うのですが、私もその一人です。
システムとしてはゲームに依存しないので、このシステムは切り売りできるのでは?
(ゲームジャンルには依存するかもしれないが、考え方としては流用できるのでは?)

と、思ったところで1つの案を思いつきました。
ハードウェアでできるんじゃない?

開発ツールがリプレイ的自動プレイをできるようになる?
単純に時間とパッド入力の録画を再生する機能(パッドリプレイ)は実は存在しますが・・
これは当該セッションや他の自動プレイ関係のセッションでも語られてますが、しょーじき全然再現できないです。
(乱数シードの固定はもちろんしてても、どうしてもずれちゃう)

なんらかの同期信号も録画して、ゲーム内のループと同期しながら再生したらいいんじゃない?とか考えたりもしてましたが、
バグの再現方法としてのパッドリプレイをゴールにしてたので完全再現という呪縛から逃れられず、考えが凝り固まってましたね。。
なので、(開発ツールでやるなら、ここどうするの?ってところはありますが)ラーニングリプレイはなんか良さそうだなと思いました。





LUMINOUS ENGINE のリプレイ手法は、メモリ上の任意の値を入力に、パッド入力を出力するものでした。
開発ツールであれば、メモリ上の値はいくらでも見ることができますし、パッド入力などデバイス入力の状態も取得できます。
ログとして値の変化をためていく部分もハードウェアで処理させるほうが有利ですし、GAME への影響もありません。

メモリ上の任意のアドレスをどう示すかは、デバッグシンボルとなんらかのマーカーをおけばなんとかなりそう。
ゲーム機の Vsync は取れるが、ゲームループは単純には取れないので、これも上の方法で取得。
「取り扱い注意な値」は、デバッグ情報あればなんとかなるんじゃないかな。

出力として得られたパッド入力は、当然開発ツールから流し込めますし、わりと現実的なのでは?と思ってしまいました。。。
(テキトーに殴り書いてます・・)
(あ、リプレイの撮り直しは構想から除外してます)


ここでポイントになってくるのが、「ズレの許容」と「ゲームの情報に非依存」であるところです。
「ズレの許容」は単純なパッドリプレイの弱点を克服し、「ゲームの情報に非依存」であることで汎用的なツールやゲーム開発者が誰しも使う開発ツールにも適用できる。はず。

ぜひ、将来の開発機材には標準で搭載されていて欲しい。


最後に
勢いでここまで書いたが、まぁだからなんだという内容だ・・
他力本願です。って言ってるだけなんだが、まぁなんだ気持ち伝われ。
(そういうのまたやってみたいという気持ちはあるよ)

では。

2019年9月4日水曜日

[CEDEC 2019] 行ってくる

今日から CEDEC 2019 ですね。
私はいつもの CI love T シャツで参加します!



では。会場で!!

2019年8月28日水曜日

[Travis CI] Addons apt のリトライ設定

travis-ciにtravis_retryという失敗しても何度かリトライする機能があるらしい件 - xuwei-k's blog
Common Build Problems - Travis CI

Travis CI には 'travis_retry' コマンドが用意されているので、script でのリトライ対応はできるのですが、Addon の場合でもできないのか調べました。




答え:できる
For a more resilient apt operations, add retries by BanzaiMan · Pull Request #1343 · travis-ci/travis-build

addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
      - llvm-toolchain-xenial-8
      - llvm-toolchain-xenial
    packages:
      - clang-8
      - g++-9
      - gcc-9
    config:
      retries: true
https://github.com/srz-zumix/iutest/pull/279

2019年8月23日金曜日

[GitHub Actions] 公式 Badge を付ける

旧 GitHub Actions ではバッジがなくて、以下を利用させて頂いていたのですが、
CultureHQ/github-actions-badge: A GitHub Actions README badge

最近バッジ表示できないなーと思っていて、リポジトリを覗きに行ったら
公式のバッジが取得できることを知りました!

(ドキュメントはまだないっぽい)

Markdown だとこうなります。
[![Actions Status](https://github.com/{owner}/{repo}/workflows/{workflow_name}/badge.svg)](https://github.com/{owner}/{repo}/actions)

ブログズミ: 新しい GitHub Actions に移行しました
先日の記事でバッジ早くくれ!と言ってましたが、もうありました!!
お詫びして訂正いたしますm(__)m

やったぜ!


※ブランチ指定はまだできない?検証中

2019年8月21日水曜日

新しい GitHub Actions に移行しました


GitHub Actions now supports CI/CD, free for public repositories


新しい GitHub Actions が使えるようになっていたので、
iutest のワークフローを 旧 GitHub Actions から移行しました。
migrate github actions by srz-zumix · Pull Request #274 · srz-zumix/iutest

HCL な main.workflow から YAML への変換
以前の GitHub Actions は HCL というフォーマットを採用していましたが、新しい GitHub Actions は他の CI サービスと同様に YAML での configuration になりました。
HCL だとどう書くんだろ?といちいち調べる手間が減るので地味に嬉しい変更です。
ただここで、HCL で書かれた workflow を YAML に直す手間が必要になるのですが・・・



さすが GitHub 、ちゃんと Migration tool を用意してくれていました!
Migrating GitHub Actions from HCL syntax to YAML syntax - GitHub Help

手順は至って簡単で、
ツールをダウンロード・展開したら、目的のリポジトリ下でツールを実行するだけです。
(ブランチ切り替えとかも含めて丁寧に説明されていますので、手順は上のリンクから確認してください)

手順どおりに行えば一瞬で移行が完了します。



自動変換後に調整したこと
ジョブを分けた


以前の GitHub Actions ではアクションごとにステータスがついていたのですが、新しい GitHub Actions でジョブごとにステータスがつくようでした。
変換した YAML ではアクションがすべて 1つのジョブにまとめられていたので、前と同じステータス通知になるようにジョブを分けました。
https://github.com/srz-zumix/iutest/pull/274/commits/b9cbdc04b6620c210e03c10085ec949092e94e9d


チェックアウト
ジョブを分けたら、それぞれにチェックアウトステップが必要でした。
各ジョブの steps に 「uses: actions/checkout@master」を追加しましょう。

steps:
    - uses: actions/checkout@master


通知設定の変更
新しい GitHub Actions になったからなのか、いつぞやからかメールで通知が来るようになっていたので無効化しました。
https://github.com/settings/notifications を開くと「GitHub Actions」の項目があるのでそちらで設定します。


「Web」にすると、GitHub の右上のベルマークのところに通知が飛ぶようになります。



変わったこと
新しい GitHub Actions に変わって大きく変わったのは
* YAML になったこと
* Windows / Mac OS が使えるようになったこと
でしょうか。

Windows や Mac OS でのテストは現在は他の CI サービスを使っているので、近々で試すことはないかもしれませんが、これらをサポートする CI サービスもだいぶ増えた印象です。
各 CI サービスがどの OS を使えるか、以下のリポジトリで個人的にまとめているので興味がある方はどうぞ。(PR お待ちしてます)
https://github.com/srz-zumix/ci-specs/blob/master/README.md#build-environment

最後に
2019/8/23 追記
ドキュメントにはまだ書かれてないようですが、すでにバッジをつけることはできてましたmm
ブログズミ: [GitHub Actions] 公式 Badge を付ける

早くバッジください

2019年8月13日火曜日

「PVをツイートするサービス」から「Integromat」に引っ越ししました


長らく「PVをツイートするサービス」を利用させて頂いて来ましたが、IntegromatBasic プラン($9/mon) を使っていることもあり、なるべくそっちを使おうということで引っ越ししました。



特に難しいことはなくて、Google Analytics の APP を使って欲しいメトリクスを選択して取得したら、あとはいつものとおりにツイッターに流すだけです。


詳細
PV 以外にも色んな情報が取れますが、最終的に以下のようにツイートさせるようにしました。

それぞれ以下の Metrics を取得しています。
Pageviewsga:pageviews
1 Day Active Usersga:1dayUsers
Sessionsga:sessions
Avg. Time on Pagega:avgTimeOnPage

Avg. Time on Page は秒数が入ってるので、Tool の Set Variable オペレータで、「分:秒」テキストに変換しています。


{{toString(floor(round(2.`ga:avgTimeOnPage`) / 60))}}:{{toString(round(2.`ga:avgTimeOnPage`) % 60)}}

ハマったこと
Error 400 (badRequest): Selected dimensions and metrics cannot be queried together.

Metrics によっては、Dimensions と一緒に取得しなければいけないものがあるそうです。
なので、「metrics and dimensions」を選択して、「Dimensions」には適当に Date を指定するといいと思います。

どこにあるのかわかりづらい
ハマったというか、使いづらいなぁ・・・と思ったところです。

Metrics からはいろいろな情報が取得できるのですが、Integromat の UI から目的の要素を見つけるのがクソ面倒でした。



月間PVの対応
PVをツイートするサービス」は、月初に先月の PV もツイートしていたのでそちらにも対応しました。



できたシナリオはこちら。


Google Atalytics の設定
まずは一月分のメトリクスを取得する必要があります。
期間の設定を「先月の1日0時」から「今月の1日0時」までにします。
以下のように計算しました。

先月の1日0時:
{{addMonths(parseDate(formatDate(now; "YYYY/MM"); "YYYY/MM"); -1)}}

今月の1日0時:
{{parseDate(formatDate(now; "YYYY/MM"); "YYYY/MM")}}

そして、取得するデータの数がデフォルトだと 10 になっているので、
一ヶ月分取得できるように 31 にしておきます。


月間PV数を計算
Google Analytics オペレータからは日毎の結果が入ってくるので、各日の PV 数を Aggregate で配列にして Iterator で Sum して、月間PVを算出しています。
(これもう少し簡単にかけると嬉しいな)


Notification
最後にツイートです。
PV数を桁区切りするようにフォーマットしてるくらいで、あとは普通にテキストを指定しています。

先月のブログズミのPVは {{formatNumber(12.result; 0; "."; ",")}} でした。
https://srz-zumix.blogspot.com/

最後に
Basic プラン使ってることもあって、オペレータ数とかあまり気にせず作りましたが、工夫すれば少し減らせると思います。(変数セットをツイートオペレータにベタ書きとか)
daily/monthly で実行するものなので、起動回数的にも消費リソースは少なくて済むはずなので、無料プランでも運用できるかな?と思います。

最後に、ながらくお世話になった「PVをツイートするサービス」に感謝 m(_ _)m

2019年8月6日火曜日

[Azure Pipelines] 頻繁にトリガーされるジョブの実行回数を削減する

Build pipeline triggers - Azure Pipelines | Microsoft Docs

If you have a lot of team members uploading changes often, then you might want to reduce the number of builds you're running. If you set batch to true, when a build is running, the system waits until the build is completed, then queues another build of all changes that have not yet been built.

trigger:
  batch: true

trigger に batch: true をつけると、キューイングされたジョブは1つにマージされるようです。
Azure Pipelines の場合は、実行中のジョブは完了を待ちます。
Travis CI のように実行中のジョブをキャンセルして、キューの最後を実行する auto-cancel とは挙動が異なりますので注意が必要です。

2019年7月31日水曜日

[Codefresh] Parallel 実行してみた

Codefresh で並列実行が使えるようになっていたので試してみました。
Use parallel steps in your Codefresh pipelines - Codefresh
無料プランでももちろん並列実行できます。
試してみた結果
iutest で試してみた結果がこちら。
もともとしていた、「benchmark test」に加えて、gcc の複数バージョンの docker コンテナでテストを実行しています。


YAML はこちらです。
version: '1.0'
stages:
  - checkout
  - build
  - test

steps:
  main_clone:
    title: Cloning main repository...
    type: git-clone
    stage: checkout
    repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}'
    revision: '${{CF_REVISION}}'
  BuildingDockerImage:
    title: Building Docker Image
    stage: build
    type: build
    image_name: srz-zumix/iutest
    working_directory: ./
    tag: '${{CF_BRANCH_TAG_NORMALIZED}}'
    dockerfile: ./tools/docker/Dockerfile
  RunningUnitTests:
    type: parallel
    stage: test
    steps:
      BasicTest-gcc9: &basic_test
        title: Running Basic Tests - gcc9
        image: gcc:9
        environment:
          - OUTDIR=gcc9
        commands:
          - mkdir test/${OUTDIR} || true
          - make -C test clean
          - make -C test test
      BasicTest-gcc8:
        <<: *basic_test
        title: Running Basic Tests - gcc8
        image: gcc:8
        environment:
          - OUTDIR=gcc8
      BasicTest-gcc7:
        <<: *basic_test
        title: Running Basic Tests - gcc7
        image: gcc:7
        environment:
          - OUTDIR=gcc7
      BenchmarkTest:
        title: Running Benchmark Tests
        image: '${{BuildingDockerImage}}'
        working_directory: IMAGE_WORK_DIR
        entry_point:
          - /bin/sh
          - /codefresh/volume/cf-generated/unit_test_script
        create_file:
          path: /codefresh/volume/cf-generated
          name: unit_test_script
          content: |-
            cd /codefresh/volume/iutest
            cd test
            make -C benchmark
            make bench
    on_success:
      metadata:
        set:
          - '${{BuildingDockerImage.imageId}}':
              - CF_QUALITY: true
    on_fail:
      metadata:
        set:
          - '${{BuildingDockerImage.imageId}}':
              - CF_QUALITY: false

※執筆時現在は構成が異なってます。
※さらに使ってみてどうだったのかは別途書きたいと思ってます。

やり方
上記の YAML を例に説明していきます。
詳細は公式のヘルプを見てもらったほうが良いと思います。
といっても基本的には type を parallel にするだけなんですけどね。

下記のように、type: parallel にしたら steps: 以下に並列実行するステップを書くだけです。
RunningUnitTests:
    type: parallel
    stage: test
    steps:
      BasicTest-gcc9: &basic_test


ハマったこと・感想など
以下は、導入してみて躓いたところと感想を書いていきます。
git-clone したパスは共有
並列コンテナで同じ場所を使います。
なので、作業が競合するような場合は注意が必要です。

iutest でも、ビルド結果の出力先が同じだったため問題になりました。
各並列コンテナごとにワークスペースを用意するなどしたほうが良さそうです。

キャッシュ
キャッシュがあるので、クリーンビルドを想定しているとハマるかもしれません。
https://codefresh.io/codefresh-news/parallel-pipelines/
Codefresh runs a git reset and a git clean in your project repository everytime a pipeline starts. This means that all artifacts that you wish to be cached should be in your .gitignore file. A common example would be the node_modules folder. If you don’t place it in .gitignore, it will be deleted at the start of each build making it much slower.
git reset; git clean を行うので、.gitignore で無視指定されているものは残ったままになります。

iutest ではたまたまテストのビルド結果が .gitignore にかかれていたため、キャッシュされていました。
これのおかげで爆速でテストできてました。
ただ、今は clean ビルドするようにしてます。
(※現在はどの程度のテストが並列でできるか検証しているので、ゆくゆくはキャッシュ使っていきたい)


明示的にクリーンビルドをしてあげる、またはキャッシュを利用してビルド速度を上げるなど、使いみちに合わせた運用が必要です。

Join ができる

まだ使ってないんですが、Join ができるのはかなり嬉しい
wercker で join ができないのがつらくてな・・・


最後に
(なぜか)、フリートライアル中なので今のうちにいろいろ試してみたいと思います。
また、Free Plan になったときのことも考えて検証していく予定。
(すでに、SMALL RESOURCE キツイ・・・となってるので頑張る予定・・・)

2019年7月24日水曜日

[Wandbox] 処理速度比較したいときのテンプレ

C++ 書いてる(じゃないな見てる)と、これはこう書いたほうが速いんじゃないか、こう書いたほうが簡潔になるけどパフォーマンス落ちないかな、と思うことが多々あります。
そんなときは、サクッと Wandbox で試してみるのですが毎回計測コードをどう書くんだっけ?となっていたのでテンプレを用意しました。





2019年7月16日火曜日

[Visual Studio] ステップフィルターのカスタマイズでデバッグを楽にする

かなり前に Visualizer を紹介しましたが、今回はステップフィルターの紹介をします。
ブログズミ: [Visual Studio] デバッガー変数表示のカスタマイズ

Visual Studio ではステップインする際に、
特定の関数には入っていかないようにする設定がユーザー定義でできるようになっています。
Customize C++ stepping behavior independent of Just My Code settings

それを設定して何が便利なのか?
よくある事例で見てみましょう。

まずは設定なし。

そして、設定あり。


どちらも UnitTestSource::GetInstance().Initialize(); の Initialize にステップインしようとしている様子です。
いかがでしょう?
前者のように GetInstance にいちいちステップインしちゃうのが煩わしく感じてる人は多いのではないでしょうか?

ステップフィルターを設定した後者は GetInstance() の中に入っていかなかったですね。
このように、1行に複数の関数呼び出しがある場合に、興味がない関数へのステップインをしないようにするとデバッグがしやすくなると思います。

今回紹介する .natstepfilter を使って、この煩わしさから開放されましょう!


設定の仕方
.natstepfilter 拡張子のファイルを作成し、
「%VsInstallDirectory%\Common7\Packages\Debugger\Visualizers」もしくは「%USERPROFILE%\My Documents\\Visualizers」に保存するだけです。

ファイルのフォーマットは xml になっています。
この xml で関数の指定とその関数に対して、ステップインするか、しないかの設定を行います。
以下は GetInstance にステップインしないようにする .natstepfilter の例です。

<Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>

.natstepfilter は複数のファイルに分けて書くことができますので、stl.natstepfiler と iutest.natstepfilter のように namespace や用途に合わせて分けておくと便利だと思います。



iutest の例
さて、上記で iutest での GetInstance の事例を紹介しましたが、
iutest では、テスティングフレームワークの利用者はフレームワークの内部実装には興味がなく、テストコードにのみ興味があるはずという考えのもと、テストコードから内部実装にステップインしないようにした natstepfilter を提供しています。

<?xml version="1.0" encoding="utf-8"?>  
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">  
    <Function>
        <Name>iutest::TestEnv::environments</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestSource::Run</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionSuccess</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionFailure</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionResult.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertionHelper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::AssertPred.*Helper.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::PrintToString.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::WithParamInterface.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::.*GetInstance.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::Test::RecordProperty.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::UnitTestImpl::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::detail::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iuutil::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::matchers.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>iutest::internal::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
    <Function>
        <Name>std::.*</Name>
        <Action>NoStepInto</Action>
    </Function>
</StepFilter>

ユーザーが集中したいコードにのみ、ステップインするのでテストコードのデバッグがしやすくなったのではないか、と思ってます。

Resharper C++ をインストールしていると利用できない
https://pleiades.io/help/resharper/Reference_Options_Tools_Debugger_CPP.html
Resharper C++ にステップフィルターの機能があるため、すべてそちらの管理になります。
そのため、.natstepfilter の設定は引き継がれません。(継承かインポートできると嬉しいですが・・・)

Resharper 使っている方はご注意くださいmm


最後に
Visual Studio は "知っていれば" 便利な機能が結構あります。
ツールは使ってなんぼ。ただ使ってるだけじゃもったいないです。

これまでもいくつか機能を紹介してきましたが、今後も Visual Studio にはお世話になると思うので、また便利な機能を知ったら紹介したいと思います。

では。

2019年7月11日木曜日

[GitHub] Squash and merge したブランチを自動でまとめて消す



PR を普通にマージしたときは、merged なブランチを列挙して branch -d すればよかったのですが、
(こんな感じ: git branch --merged | grep -v \\* | grep / | xargs -I % git branch -d %)
「Squash and merge」すると、実際にブランチをマージしているわけではないので、branch --merged に列挙されず、上記方法でお掃除できずに困ってました。

結構、ローカルブランチが溜まってきたのでお掃除したいなーと思い、調べてみたらドンピシャな記事がありました。
GitHub で Squash merge されたブランチを削除する · ryym.log

詳しいことは、こちらの記事を読んでいただければと思います。


で、これで終わると、この記事自体の内容がないよう、となってしまうので、自分好みにカスタムした alias をおいておきます。

del-squashed-branch = "!f(){ base_branch=${1:-master} && echo ${base_branch} && git checkout -q ${base_branch} && git for-each-ref refs/heads/ "--format=%(refname:short)" | while read branch; do mergeBase=$(git merge-base origin/${base_branch} $branch) && [[ $(git cherry origin/${base_branch} $(git commit-tree $(git rev-parse $branch^{tree}) -p $mergeBase -m _)) == "-"* ]] && git branch -D $branch; done; git checkout -q -;};f"
  del-sq = !git del-squashed-branch `git def-branch`
  def-branch = !git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-

もとの shell command だと master との比較になってましたが、他のブランチを指定できるようにしました。
iutest の開発中は develop に PR 出して、ある程度安定したら master にマージするようにしているので、
develop ブランチを指定して、お掃除したかったのでこうしました。

また、短いエイリアスの方はデフォルトブランチを指定するようにしました。
(これは仕事のときに使うことを想定してこうした)

今回は以上です。


追記
git symbolic-ref --short refs/remotes/origin/HEAD | cut -d "/" -f 2
では正しく GitHub のデフォルトブランチを取得できてませんでした。
git ls-remote --symref origin HEAD | head -n 1 | cut -f 1 | cut -d "/" -f 3-
に修正しました。


2019年7月5日金曜日

[Blogger][AdSense] 「ads.txt ファイルが含まれていないサイトがあります」 に対応した

このブログでは Google AdSense で広告掲載をしています。
たまーにレポートを眺めに AdSense を見に行くのですが、いつの間にか以下のような警告文が出るようになってました。
「要注意 - ads.txt ファイルが含まれていないサイトがあります。収益に重大な影響が出ないよう、この問題を今すぐ修正してください。」



収益にこだわりはないのですが、警告は無視できない体質なので対応しました。

ads.txt とは?
警告文のヘルプを開くと以下のようなことが書かれています。


Blogger に ads.txt を設定する
Blogger の場合のヘルプもちゃんとあります。


ヘルプに従えば問題なく設定できると思います。





ここに書く内容は、AdSense のヘルプを参考に以下のように入力します。

google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0

「pub-0000000000000000」の部分は、サイト運営者ID に置き換えてください。
サイト運営者 ID を確認する - AdSense ヘルプ

入力ができたら、「変更を保存」で設定完了です。
再び、AdSense にログインしてみたところ、警告が消えました!

よかったよかった。




2019年6月27日木曜日

Cygwin インストール後に SourceTree で「SSH 認証に失敗」ダイアログが出て接続に失敗してたので対応した備忘録

SSH認証に失敗

OpenSSH は起動していますが、接続に失敗しました。メニューのツール > SSH キーの追加 から、適切なキーを追加する必要があります。

OpenSSH では手動でユーザー名とパスワードによってログインすることはできませんのでご注意ください。その場合、HTTPS 形式の URL を使うか、SSH クライアントを PuTTY/Plink に切り替えてください。これはメニューの ツール > オプション から設定できます。


最近、Windows PC を新調したので、セットアップしていてこんな感じのダイアログが大量に出てきて、ビックリしました。
原因は cygwin をインストールしてパスを通したタイミングで cygwin の ssh agent を見るようになったのと、cygwin の HOME から設定した ssh のキーが見えていなかったためでした。


というわけで、HOME 環境変数を %USERPROFILE% として設定して対応しました。
HOME を Windows の環境変数に設定するのは非推奨というのを見かけますが、今までだいたい HOME を設定してたんですよね。
これなんでなんでしょうね?(疑問で終わる・・・)

ダイアログが大量に出てビックリして、検索したけど、ドンピシャなページにヒットしなかったので備忘録として残しておきます。
今回は以上です。では。



2019年6月19日水曜日

git config コマンドで [mergetool "sourcetree"] のようなセクションを設定する

[mergetool "sourcetree"]
 cmd = 'C:/Program Files/TortoiseGit/bin/TortoiseGitMerge.exe'  -base:\"$BASE\" -mine:\"$LOCAL\" -theirs:\"$REMOTE\" -merged:\"$MERGED\"
 trustExitCode = true

こういうような、セクションにタグ?がついてるような config をコマンドから設定したいなと思いつつも、
いつもファイルを直接編集していました。


それでもなんとかなってたのですが…
自分も dotfiles を git 管理するようにして、いつでもどこでも簡単セットアップ!…
にしてたときに問題になったので、ちゃんと調べました。





まぁ、調べたらすぐ出てくるもんです。
Git on Windows: How do you set up a mergetool? - Stack Overflow

最初の mergetool sourcetree の場合は、こうなります。
git config --global mergetool.sourcetree.cmd 'C:/Program Files/TortoiseGit/bin/TortoiseGitMerge.exe' -base:"$BASE" -mine:"$LOCAL" -theirs:"$REMOTE" -merged:"$MERGED

[XXX YYY] ZZZ とあったら、XXX.YYY.ZZZ のように単純に . で繋げばいいだけでした。
めでたしめでたし。

2019年6月10日月曜日

[備忘録][Gem] github master の最新のパッケージをインストールする

はじめに
あるタイミングから Travis CI から Coveralls にカバレッジレポートを送る処理が失敗してることに気づきました。
https://github.com/srz-zumix/iutest/issues/234

Coveralls へのレポート送信は lcoveralls を使っていて、全く同じ issue がすでに修正されマージされていました。
ただ、まだ gem にはこの修正を含んだパッケージはアップされてなかったため、github の master からパッケージインストールすることにしました。

方法
specific_install を使うだけ!
参考にしたところ:gem installでGitHubリポジトリにある最新版をインストールする - Qiita

gem install specific_install && gem specific_install -l 'git://github.com/pcolby/lcoveralls.git'

2019年6月3日月曜日

lcov で "geninfo: ERROR: ***.gcno: reached unexpected end of file" が出たときにやったこと

Coveralls へのカバレッジレポートアップロードを Travis CI でやっていて、
今までは gcc + gcov でやっていたのだが、Codecov の方が clang から gcc に変更になったので、Coveralls は clang に。
と、思ったらぶつかったのでメモ。
https://github.com/srz-zumix/iutest/issues/234



まず、clang が生成する gcno のフォーマットが gcc 4.2 で、Travis CI の xenial 環境に入ってる gcc が 5.5 だったため clang + gcov でもエラーが出て集計できなかった、というのが根本的な原因と思われます。
gcov -r *.gcda;
also_run_disabled_tests.gcno:version '402*', prefer '505*'
Segmentation fault (core dumped)

この状態で lcov を使うと、表題のエラーになっていました。
geninfo: ERROR: /home/travis/build/srz-zumix/iutest/test/assertion_return_tests.gcno: reached unexpected end of file
lcov は gcov をバックエンドとして使っているので、おそらく内部的に gcov のエラーが置きているのではないかと予想。(ホントのところは知らんけど)

解決方法
Check Code Coverage with Clang and LCOV | Logan's Note

↑の記事にあるように、llvm-gcov.sh ファイルを作成する。中身は以下の通り


あとは、lcov のオプションに --gcov-tool path/to/dir/llvm-gcov.sh とするだけです。

iutest で実際にやってますので、そちらも参考にしてみてください。
ではでは。

2019年5月27日月曜日

[Travis CI] after_success ステップ中の失敗はジョブの失敗にならない

Travis CI でなにか他のサービスと連携したり、デプロイしたりするときに、after_success で処理を書いているサンプルがちょくちょくあります。
after_success 自体は、ジョブが成功したときにだけ実行されるので、成果物に対してなにかするときに便利ではあるのですが、
実はこのステップ中の失敗は、ジョブの失敗にならず握りつぶされていることに気づきました


そんなの知らないよーってことで、
なんと!一年以上 Codecov にカバレッジレポートがアップロードされてませんでした!!
Codecov にカバレッジがアップロードされていない · Issue #233 · srz-zumix/iutest

・失敗してるのに成功してるジョブ
https://travis-ci.com/srz-zumix/iutest/jobs/193873334




after_success に書く処理は失敗しても問題のないものにした方がいいな。と思いました。。。
解決策としては、(ベタに)ビルドステップに引っ越ししました。
travis-ci の issues でも似たようなやりとりがあったみたいです。
after_success failure doesn't fail build · Issue #758 · travis-ci/travis-ci

では。

2019年5月20日月曜日

Walterbot の「View log」 がすごく便利!

ブログズミ: [Wercker] Walterbot + Slack を試してみた

この記事を書いた時点では「View log」はなかったので紹介してませんでしたが、
これがすごく便利なので改めて紹介します。
(Walterbot については↑を参考にしてください)

View Log ボタンでエラーの周辺ログが見れる!!


「View Log」ボタンを押すと以下のようにログが見れます。


iutest の Wercker でのテストは
fused したコード(1ファイル化したもの)をさらに圧縮して(js の min.js みたいな) Wandbox に投げつけてコンパイル&実行しているので、エラーがすごく見づらいのですが・・・

ともあれ、すごく便利なので Wercker 使いの方は、ぜひ Walterbot を使いましょう!!

2019年5月13日月曜日

[C++] g++ 9.1.0 で variant が valueless_by_exception にならないケースに遭遇した

iutest の開発をしていたら、variant が valueless になったときのテストが失敗するようになった。


テストコードはこれ。
valueless_by_exception と出力されるのを期待しているが、実際には 0.2 という空になる前の値を出力している。

{
    PrintToLogChecker ck("valueless_by_exception");
    ::std::variant<int, ::std::string, float> v = 0.2f;
    try
    {
        struct S { operator int() { throw 42; } };
        v.emplace<0>(S());
    }
    catch(...)
    {
    }
    IUTEST_SUCCEED() << ::iutest::PrintToString(v);
}

この valueless にするコードは、
https://ja.cppreference.com/w/cpp/utility/variant/valueless_by_exception からとってきたもので、今までは valueless になっていたのを確認している。

関連するコードをいじってはいないので、環境周りの違いだと思い確認したところ、g++ 9.1.0 では valueless にならないことを確認しました。
また、valueless な状態を作る方法を探していたら、
https://cpprefjp.github.io/reference/variant/variant/valueless_by_exception.html に AlwaysThrow でのサンプルがあったので、そちらを使って確認したところ g++ 9.1.0 でも valueless になりました。

(typo がひでぇ)



よって、テストコードとりあえず以下のように修正しました。
{
    PrintToLogChecker ck("valueless_by_exception");
    ::std::variant<int, float, AlwaysThrow> v = 0.2f;
    try
    {
        struct S { operator int() { throw 42; } };
        v.emplace<0>(S());
    }
    catch(...)
    {
        IUTEST_INFORM_TRUE(v.valueless_by_exception());
    }
    if( !v.valueless_by_exception() )
    {
        try
        {
            v = AlwaysThrow();
        }
        catch(...)
        {
           IUTEST_INFORM_TRUE(v.valueless_by_exception());
        }
    }
    IUTEST_SUCCEED() << ::iutest::PrintToString(v);
}

これはバグ?
cpprefjpcppreference.com も、サンプルのコメントを読むと、確実に valueless な状態にはなるとは限らないように読み取れるのだが、(規格的に)これはそういうもんなのだろうか?それとも g++ 9.1.0 のバグなのだろうか?

一旦ここまでで記事公開させていただきます。
続報あれば、追記していきますmm



2019年5月7日火曜日

[Git] マージするときのリネーム上限とリネーム判定の抑制

最近、テスト結果を蓄積する試みをしていたら、git の挙動でハマったので備忘録として残しておきます。

git は意図的なリネームが可能ですが、意図しないリネームが発生したりすることがあります。
これは、リネームは削除と追加がまとまったもので(ほぼ)同じ内容のファイルが削除と追加(別名で)されたときに、git はリネームとして処理することがあります。
なので、こちらとしては望んでいない場合でもリネームとして扱われてしまうことがあります。
(ほとんどの人はこんなケースには遭遇しない気がするけど・・・)

で、なにが起きたかというと、
リネームが大量に検出されて、マージするときのリネーム上限に引っかかってしまいました。



というか、上限なんてあったんだ!という感じでしたが、git config merge.renameLimit で上限解放できるらしいです。
git config merge.renameLimit 9999


そもそもリネームじゃねぇっ!という場合は、merge.renames でリネーム処理を行わないようにもできます。
git config merge.renames false


たぶん、こういうケースにあたる人は少ない気がするけど、
merge.renameLimit と merge.renames config の紹介でした。
では。

2019年4月23日火曜日

[Cirrus CI] OSX VM 数制限対策としてマトリックスを直列にしてみた




OSX VM は1つしか使えない制限があり、その制限により CI が FAIL することがあったので対策しました。
もともとの YAML はこんな感じでした(一部抜粋)
cirrus_osx_test_task:
  only_if: *default-condition
  auto_cancellation: true
  osx_instance:
    image: mojave-xcode-10.1
  env:
    matrix:
      STDFLAG: -std=c++14
      STDFLAG: -std=c++17
  test_script: cd test && make -j4 showcxxversion default && make test


c++14 と c++17 コンパイルを並列していました。
単純にどちらかだけにしたら制限に引っかかることはなくなりますが、できれば減らしたくない条件です。
そこで、並列に実行するのではなく、直列で実行するようにしました。
修正した YAML はこんな感じです。
cirrus_osx_14_test_task: &osx_task
  only_if: *default-condition
  auto_cancellation: true
  osx_instance:
    image: mojave-xcode-10.1
  env:
    STDFLAG: -std=c++14
  test_script: cd test && make -j4 showcxxversion default && make test

cirrus_osx_17_test_task:
  <<: *osx_task
  env:
    STDFLAG: -std=c++17
  depends_on:
    - cirrus_osx_14_test
depends_on で依存を貼って、直列にしています。 YAML エイリアスが使えるため直列にしても記述量はさほど増えませんでした。メンテナンス性が問題になることはないでしょう。 ただし、実行時間が長くなるデメリットはあります。が、iutest の現状の開発ペースでは特に問題にならないのでこのようにしました。

今回は、これで以上です。
では。

2019年4月9日火曜日

Slack のステータス(障害情報)を通知する

ついこの間 Slack の障害が発生し、メッセージが正しく届かなかったり、スタンプが押せなかったりなどの影響がありましたね。
Slack の状態はステータスページで確認できます。また、Twitter アカウントもあります。


あとは、Atom feed と RSS も用意されているので、お好きな方法で状況を確認できます。


ただ、ステータスページを都度都度見るのはめんどくさいですし、twitter もタイムラインをずっと見てるわけじゃないので気づかなそう。RSS や Atom feed はリーダーを使ってない。。。

RPA で任意のツールに通知する
というわけで、RPA 組みました。
今回使ったのは Integromat です。最近のお気に入りです。

出来上がったシナリオは3オペレーションになりました。(こだわらなければ2ステップでできます)


Trigger は RSS で、Slack Status の RSS url をセットします。


間にある Text Parser はステータスからアイコンのファイル名を摘出するためのステップです。
アイコン画像にこだわらなければ、このステップは不要です。


最後は通知するステップです。Slack で通知してますが、ここはなんでも良いです。お好きなもので通知してください。
接続設定(slack ならスペースとチャンネル)をしたら、本文をセットしましょう。
RSS で取得した内容が使えるので、その内容を流しています。(特に決まりはないので、ここもお好きに編集してください。)


Slack ではアイコンを指定できるので、Text Parser で取得したステータスからアイコンの url をセットしました。



最後に、Slack Status は 30 分更新のようなので、Trigger の Interval も 30 分にします。


これで完成です。
シナリオを有効にしたら、以下のように通知が飛んできます。


最後に
Integromat はシナリオの Export/Import が可能です。
今回紹介したシナリオの blueprint を Gist で公開しているので、こちらを Import して始めることもできます。
Integromat 便利なので是非使ってみてください。では~