GitLabでtagとtagの間に含まれるMRリストを取得する
GitLabであるタグに含まれるMRのリストをトレースする必要があったので、GitLabのAPIとjqを使ってtagとtagに間含まれるMRリストを出力して、Markdown形式のリリースノートを出力するシェルを組みました。
#!/bin/sh BASE_URL="GITLAB_HOSTNAME" API_TOKEN="GITLAB_APITOKEN" PROJECT_ID="xx" PROJECT_NAME="yyy" REPOSITOEY_NAME="zzz" TAG_FROM_AUTHORD_DATE=`curl -X GET -H "PRIVATE-TOKEN: ${API_TOKEN}" "${BASE_URL}/api/v4/projects/${PROJECT_ID}/repository/tags/${1}" | jq -r .commit.authored_date` TAG_TO_AUTHORD_DATE=`curl -X GET -H "PRIVATE-TOKEN: ${API_TOKEN}" "${BASE_URL}/api/v4/projects/${PROJECT_ID}/repository/tags/${2}" | jq -r .commit.authored_date` # tagを切ったコミットハッシュのMRが含まれない可能性があるため1分ずらす TAG_FROM_AUTHORD_DATE=`date -v+1M -j -f "%Y-%m-%dT%T.000Z" ${TAG_FROM_AUTHORD_DATE} +%Y-%m-%dT%T.000Z` TAG_TO_AUTHORD_DATE=`date -v+1M -j -f "%Y-%m-%dT%T.000Z" ${TAG_TO_AUTHORD_DATE} +%Y-%m-%dT%T.000Z` curl -X GET -H "PRIVATE-TOKEN: ${API_TOKEN}" "${BASE_URL}/api/v4/projects/${PROJECT_ID}/merge_requests?state=merged&updated_after=${TAG_FROM_AUTHORD_DATE}&updated_before=${TAG_TO_AUTHORD_DATE}&target_branch=master&view=simple&per_page=100" | jq -r 'sort_by(.iid)| .[] | "- [" + (.title|tostring) + "](" + (.web_url|tostring) + ")"'
使い方は引数に2つのタグを入れるだけです。
# 実行方法と出力サンプル $ ./generate-releasenote.sh tag1 tag2 - [MR Title1](${BASE_URL}/${PROJECT_NAME}/${REPOSITOEY_NAME}/merge_requests/mr_id1) - [MR Title2](${BASE_URL}/${PROJECT_NAME}/${REPOSITOEY_NAME}/merge_requests/mr_id2) - [MR Title3](${BASE_URL}/${PROJECT_NAME}/${REPOSITOEY_NAME}/merge_requests/mr_id3)
中でやってるのは以下の通りです。
- tag1、tag2が打たれたタイムスタンプを取得する
- 1で取得したタイムスタンプをdateコマンドで1分後ろにずらす
- 2を使ってMRリストを取得するAPIリクエストを投げてタイトルとIDのリストを取得する
- jqで加工してMarkdown形式で出力する
tag1、tag2のタイムスタンプをそのまま使ってしまうとtag1・tag2がマージコミットだった場合に出力されるMRリストに含まれない可能性があるのでdate
コマンドで1分後ろにずらしています。
またクエリにヒットするのはタイムスタンプの間に更新があったMRリストなので、もしマージされたあとにコメント書いたりして更新されたものがあるとヒットしてしまいます。このへんは運用で除外するように対処しました。
あとはMR一覧を取得するAPIは一度に取得できる数がデフォルトだと20件なので、per_pageで最大値である100
を指定しています。
これを日々行うことで、リリース前後でどのbugfixがどのタグに含まれているか追跡するのが楽になりました。
AtCoderの色が緑で停滞している
AtCoderを再開した話を以前書いた。
あれからもぼちぼち続けて晴れて緑になったのだけど、その後は800くらいで停滞している。
水色になりたいと↑では語っていたのだけど、水色になるには今のABCでE問題まで常に解けるくらいにならないといけなさそうだ。
実力的にはEよりもまずABCDを確実に早く解けるようになるのが先だと思い、とりあえず過去問を埋めることにした。
https://kenkoooo.com/atcoder/#/user/takamii228
8月中にA、B、Cは埋められそうな勢いだったけど仕事が忙しくなったので停滞気味。
A、B、Cを埋めるとsortとか簡単な全探索はパッと書けるようになったので、グラフ問題とかDPの式構築がサクッと解けるようになるのが次のステップかなと思った。
ゆるーく楽しみながら続けたいと思いましたまる。
flutter driverでassetsが原因で画像が表示されなくなった件 #flutter
flutter driverでE2Eテストをゴリゴリ書こうとした時にハマった内容と暫定的な対処方法を共有します。
※ 2020/10/21 追記あり
ある日突然flutter driverで画像が表示されなくなった
flutterではflutter driverというIntegration test用のFWが用意されています。
公式を参考にそれっぽいシナリオを実行していたのですが、ある日突然今まで成功していたシナリオが失敗するようになりました。
あれれと思ってエミュレータを見てみると、画像が一切表示されていませんでした。
flutter doctorはこんな感じ。
$ flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel unknown, v1.5.4-hotfix.2, on Mac OS X 10.14.6 18G87, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.0) [✓] iOS toolchain - develop for iOS devices (Xcode 10.2.1) [✓] Android Studio (version 3.4) [!] VS Code (version 1.37.1) ✗ Flutter extension not installed; install from https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter [✓] Connected device (2 available)
assetsの数が多すぎるのが原因っぽい
おかしいなと思ってコミットの差分を追ってみると、どうやら画像を大量に追加した前後で挙動がおかしくなっていた。
でも普通にflutter runすると正しく画像は表示されていた。おかしいなぁと思っていろいろググってみるとgithubのIssueを発見。
After days of investigation, I've found that it may have the same cause with #24703. When the AssetManifest.json file size larger than 10 * 1024, it will call compute, then Isolate.spawn will be called which won't work for flutter drive. So images can NOT be displayed. However when AssetManifest.json file size smaller than 10*1024, then It works well. That's why image assets can be displayed for some certain apps.
なんと、AssetManifest.jsonのファイルサイズが 10 * 1024を超えると新しくIsolate.spawnが呼ばれて、画像が読めなくなってflutter driverが動かなくなる模様。
AssetManifest.jsonはassetsのファイル名とパスをkey / valueでまとめたjsonファイルで、iosはApp.Frameworkの中に、androidはbuild配下にビルド時に自動生成されるファイルのようです。
assetsはpubspec.ymlでフォルダごと読み込むようにしていました。
... flutter: uses-material-design: true assets: - assets/ ...
ファイルのサイズを確認すると、確かに10 * 1024は超えていてflutterのObservatory URLを見に行ってみるとspawnのisolateが起動されていました。
$ ls -la AssetManifest.json -rw-r--r-- 1 takamii228 staff 10905 8 28 22:11 AssetManifest.json
対象方法
えーどうしよう...と思ってflutterのソースを眺めてたらそこの制御をしているコードを発見。
Future<String> loadString(String key, { bool cache = true }) async { final ByteData data = await load(key); if (data == null) throw FlutterError('Unable to load asset: $key'); if (data.lengthInBytes < 10 * 1024) { // 10KB takes about 3ms to parse on a Pixel 2 XL. // See: https://github.com/dart-lang/sdk/issues/31954 return utf8.decode(data.buffer.asUint8List()); } return compute(_utf8decode, data, debugLabel: 'UTF8 decode for "$key"'); }
Pixel 2XLだと、10 * 1024を超えるとparseに3msかかるらしい。3msくらいええやん...。
最新のmasterでもこのソースのままだったので、アドホックですがflutter driverの実行前後でこの上限を緩和するpatchを当てるようなシェルを組みました。
asset_bundle.patch
--- a/development/flutter/packages/flutter/lib/src/services/asset_bundle.dart +++ b/development/flutter/packages/flutter/lib/src/services/asset_bundle.dart @@ -67,7 +67,7 @@ abstract class AssetBundle { final ByteData data = await load(key); if (data == null) throw FlutterError('Unable to load asset: $key'); - if (data.lengthInBytes < 10 * 1024) { + if (data.lengthInBytes < 1000 * 1024) { // 10KB takes about 3ms to parse on a Pixel 2 XL. // See: https://github.com/dart-lang/sdk/issues/31954 return utf8.decode(data.buffer.asUint8List());
flutter-driver.sh
#!/bin/sh set -x # 実行前にパッチを当てる CURRENT_DIR=`pwd` cd $HOME patch -p1 -N < ${CURRENT_DIR}/asset_bundle.patch || true cd ${CURRENT_DIR} # flutter driverを実行 flutter driver --debug --flavor develop --target test_driver/app.dart -d xxxxxx # 実行後は元に戻す cd $HOME patch -p1 -N -R < ${CURRENT_DIR}/asset_bundle.patch || true cd ${CURRENT_DIR}
パッチを当ててから実行するようにしたら無事spawnのIsolateが消えてflutter driverでも画像が表示され、E2Eテストが再び通るようになりました🎉🎉🎉
flutter driverは公式の情報がまだまだ少なく、この後もいろいろ踏みそうですがなんとか食らいついて頑張っていこうと思います。
【追記 2020/10/21】パッチファイルの修正が必要
flutter 1.22.0よりasset_ bundle.dartに修正が入ったためパッチファイルも修正が必要になっています。画像が読み込まれなくなる事象はまだ発生するようなので引き続きご注意ください。
asset_bundle.patch
--- a/development/flutter/packages/flutter/lib/src/services/asset_bundle.dart +++ b/development/flutter/packages/flutter/lib/src/services/asset_bundle.dart @@ -71,7 +71,7 @@ abstract class AssetBundle { // that the null-handling logic is dead code). if (data == null) throw FlutterError('Unable to load asset: $key'); // ignore: dead_code - if (data.lengthInBytes < 10 * 1024) { + if (data.lengthInBytes < 1000 * 1024) { // 10KB takes about 3ms to parse on a Pixel 2 XL. // See: https://github.com/dart-lang/sdk/issues/31954 return utf8.decode(data.buffer.asUint8List());