Github で PR の APPROVED 数に応じてラベル(releasable) をつけたり外したりする

f:id:kyagi:20220131212856p:plain
Dismiss stale pull request approvals when new commits are pushed

Github の Pull Request のレビュー後、APPROVED の数に応じてラベルをつける運用を自動化します。APPROVED 後にコミットがあった場合、自動的に APPROVED が取り消される運用(画像) での運用を想定しています。*1

f:id:kyagi:20220131220133p:plain
shamshir

任意の数の APPROVED を取得した PR の集合を A とし、releasable ラベルが付与されている PR の集合を B とした場合、動作は以下になります。

  • 差集合 A - B に対して releasable ラベルを付ける
  • 差集合 B - A に対して releasable ラベルを剥がす

差集合 B -A は主に APPROVED 後にコミットすることで発生します ((Github のブランチ設定で Dismiss stale pull request approvals when new commits are pushed 設定をしている場合)))

レポジトリ

https://github.com/kyagi/shamshir

実行

$ node shamshir.js --owner kyagi --repo awesome-project --label releasable --quorum 2

ログ

$ cat combined.log
{"level":"info","message":"Shamshir started.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:22"}
{"level":"info","message":"Shamshir got pulls: 2602,2598,2596,2575,2573,2557,2553,2551,2540,2539,2481,2478,2295,2281,1981,1951,1685","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:22"}
{"level":"info","message":"Shamshir added releasable label to pull/2598.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:24"}
{"level":"info","message":"Shamshir added releasable label to pull/2596.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:24"}
{"level":"info","message":"Shamshir added releasable label to pull/2575.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:25"}
{"level":"info","message":"Shamshir removed releasable label from pull/2573.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:26"}
{"level":"info","message":"Shamshir added releasable label to pull/2551.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:28"}
{"level":"info","message":"Shamshir added releasable label to pull/2540.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:29"}
{"level":"info","message":"Shamshir added releasable label to pull/2539.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:30"}
{"level":"info","message":"Shamshir added releasable label to pull/2478.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:31"}
{"level":"info","message":"Shamshir added releasable label to pull/2295.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:32"}
{"level":"info","message":"Shamshir added releasable label to pull/1951.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:34"}
{"level":"info","message":"Shamshir finished.","mode":"live","owner":"kyagi","repo":"awesome-project","service":"shamshir","timestamp":"2022-01-31 00:54:34"}

Github API (REST API) について

Github API では Issue と Pull Request でエンドポイントを共有しています("shared" actions for both features)。API Reference の Issue ページにはラベル処理がありますが Pulls ページにはラベル処理がありません。だからといって Pull Request にラベルをつけられないというわけではなく、Issue API のエンドポイントを使い key として pull_request を使用することで(shared) Pull Request に対してもラベル処理が可能です。

Note: GitHub's REST API v3 considers every pull request an issue, but not every issue is a pull request. For this reason, "Issues" endpoints may return both issues and pull requests in the response. You can identify pull requests by the pull_request key. Be aware that the id of a pull request returned from "Issues" endpoints will be an issue id. To find out the pull request id, use the "List pull requests" endpoint.

https://docs.github.com/en/rest/reference/issues

Every pull request is an issue, but not every issue is a pull request. For this reason, "shared" actions for both features, like manipulating assignees, labels and milestones, are provided within the Issues API. https://docs.github.com/en/rest/reference/pulls

トップの画像では集合の図を載せていますが、実装で集合演算は使用していません。JavaScript に組み込みの集合演算がないのと、1 ページ 30 個 程度の Pull Request が処理対象の場合、集合演算よりループで処理した方が簡単だからです。

運用方法について

EC2 や ECS で動かすスタンドアローン的な運用と Github Actions で動かす運用の 2 つを考えています(Github Actions は将来サポート予定)。それぞれの長所/短所を以下に挙げます。

スタンドアローン Github Actions
設計/実装 制約がなく自由度が高い Github Actions の方法に則る必要があり workflow/action 内でできることに制約がある
コスト 走らせるためのリソース(EC2 or ECS) にコストがかかる 条件内の実行時間とストレージ容量であればコストは無料
認証/認可 Personal Access Token が必要 入力として GITHUB_TOKEN が使える

参考情報

*1 Dismiss stale pull request approvals when new commits are pushed 設定をしている場合

Web の QMK Configurator でキーマップを作成してからローカルの QMK Firmware でビルド/書き込みを行う

Corne Cherry で自分専用のキーマップを作成してファームウェアをビルド、書き込みする手順です。ビルドガイドの補足情報としてお役に立てば幸いです。

f:id:kyagi:20190717172535j:plain

Corne Cherry のファームウェア書き込みについて

ビルドガイドにもある通り、QMK Firmware を使用してファームウェアを書き込む必要がありますが、ビルドガイドではキーマップの編集手順が掲載されていないため、自分が行った手順を補足情報として載せておきます。

ここではキーマップの作成と編集を Web の QMK Configurator で行ってからローカルの QMK Firmware でビルド/書き込みを行っています。自分で keymap.c を書き換えるよりもコピー&ペーストで実施できるため、簡単です。*1

1. 自分専用のビルド環境を構築

qmk_firmware の crkbd/keymaps 配下で default をコピーして自分専用のビルド環境を構築します。

$ cd ~/git/qmk_firmware
$ pushd keyboards/crkbd/keymaps
$ cp -rp default kyagi

2. QMK Configurator でキーマップを作成してダウンロード

QMK Firmware/Building Your First Firmware の説明通り、キーマップの変更は keymap.c の keymaps 配列を編集することで行います。エディタで編集してもいいのですが、QMK Configurator を使用して自分好みのキーマップを作成し、COMPILE を実施した後、KEYMAP ONLY のリンクから keymap.c をダウンロードして keymaps 配列を入れ替えるとお手軽です。

$ vi kyagi/keymap.c # 自分で書き換えてもいいが...
$ cp ~/Downloads/crkbd_rev1_kyagi/keymap.c kyagi/keymap.c # QMK Configurator でコンパイル済みの keymap.c を KEYMAP ONLY からダウンロードしたほうが簡単

上記ではコピーしていますが、実際は keymaps 配列だけ書き換えればいいはずです。差分は以下のようになります。

$ diff -Nurp keymaps/default/keymap.c keymaps/kyagi/keymap.c
--- keymaps/default/keymap.c    2019-07-15 19:36:36.000000000 +0900
+++ keymaps/kyagi/keymap.c  2019-07-17 20:12:01.000000000 +0900
@@ -58,30 +58,8 @@ enum macro_keycodes {
 #define KC_ALTKN ALT_T(KC_LANG1)

 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-  [_QWERTY] = LAYOUT_kc( \
-  //,-----------------------------------------.                ,-----------------------------------------.
-        ESC,     Q,     W,     E,     R,     T,                      Y,     U,     I,     O,     P,  BSPC,\
-  //|------+------+------+------+------+------|                |------+------+------+------+------+------|
-      CTLTB,     A,     S,     D,     F,     G,                      H,     J,     K,     L,  SCLN,  QUOT,\
-  //|------+------+------+------+------+------|                |------+------+------+------+------+------|
-       LSFT,     Z,     X,     C,     V,     B,                      N,     M,  COMM,   DOT,  SLSH,  RSFT,\
-  //|------+------+------+------+------+------+------|  |------+------+------+------+------+------+------|
-                                  GUIEI, LOWER,   SPC,      ENT, RAISE, ALTKN \
-                              //`--------------------'  `--------------------'
-  ),
-
-  [_LOWER] = LAYOUT_kc( \
-  //,-----------------------------------------.                ,-----------------------------------------.
-        ESC,     1,     2,     3,     4,     5,                      6,     7,     8,     9,     0,  BSPC,\
-  //|------+------+------+------+------+------|                |------+------+------+------+------+------|
-      CTLTB,    F1,    F2,    F3,    F4,    F5,                     F6,    F7,    F8,    F9,   F10, XXXXX,\
-  //|------+------+------+------+------+------|                |------+------+------+------+------+------|
-       LSFT,   F11,   F12,   F13,   F14,   F15,                    F16,   F17,   F18,   F19,   F20, XXXXX,\
-  //|------+------+------+------+------+------+------|  |------+------+------+------+------+------+------|
-                                  GUIEI, LOWER,   SPC,      ENT, RAISE, ALTKN \
-                              //`--------------------'  `--------------------'
-  ),
-
+  [_QWERTY] = LAYOUT(KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_MINS, KC_ENT, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_GRV, MO(1), KC_LALT, KC_SPC, KC_ENT, KC_RCTL, KC_RGUI),
+  [_LOWER] = LAYOUT(KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, RSFT(KC_BSLS), KC_LCTL, LSFT(KC_1), LSFT(KC_2), LSFT(KC_3), KC_F11, LSFT(KC_4), KC_QUOT, RCTL(KC_1), RSFT_T(KC_9), RSFT_T(KC_0), KC_SCLN, KC_F4, KC_LSFT, LSFT(KC_5), LSFT(KC_6), LSFT(KC_7), KC_F12, LSFT(KC_8), KC_BSLS, RCTL(KC_2), KC_LBRC, KC_RBRC, RSFT(KC_SCLN), KC_EQL, KC_NO, KC_LALT, KC_SPC, KC_ENT, KC_RCTL, KC_RGUI),
   [_RAISE] = LAYOUT_kc( \
   //,-----------------------------------------.                ,-----------------------------------------.
         ESC,  EXLM,    AT,  HASH,   DLR,  PERC,                   CIRC,  AMPR,  ASTR,  LPRN,  RPRN,  BSPC,\

3. ローカルでのビルドと書き込み

USB ケーブルで Corne Cherry と Mac を接続し、ビルドと書き込みを行います。

$ popd
$ pwd
/Users/kyagi/git/qmk_firmware
$ make crkbd:kyagi
$ make crkbd:kyagi:avrdude

QMK Configurator でコンパイルしてダウンロードした .hex ファイルのみを差し替えてファームウェアに書き込む(OLED不使用)

コンパイルまでは QMK Configurator で可能なので FIRMWARE からダウンロードした .hex ファイルのみを差し替えて書き込みも可能です。ただし QMK Configurator で作成する keymap.c はレイアウトのみの簡易的なもので OLED 機能がコードに入っていないため、OLED は光りません。ただ、OLED 機能を使うと一部のキーに遅延が起こっているように感じるのと、パスワードなどの表示問題があるためオフのほうがいいかもしれません。機能的には問題ないようです。

$ pwd
/Users/kyagi/git/qmk_firmware
$ cp  ~/Downloads/crkbd_rev1_kyagi.hex .build/
$ ls -l .build
total 3168
-rwxr-xr-x   1 kyagi  staff  414300 Jul 15 19:41 crkbd_rev1_default.elf
-rw-r--r--@  1 kyagi  staff   53429 Jul 16 20:25 crkbd_rev1_default.hex
-rw-r--r--   1 kyagi  staff  325408 Jul 15 19:41 crkbd_rev1_default.map
-rwxr-xr-x   1 kyagi  staff  414292 Jul 17 20:12 crkbd_rev1_kyagi.elf
-rw-r--r--   1 kyagi  staff   70799 Jul 17 20:12 crkbd_rev1_kyagi.hex
-rw-r--r--   1 kyagi  staff  320940 Jul 17 20:12 crkbd_rev1_kyagi.map
drwxr-xr-x   2 kyagi  staff      64 Jul 15 20:41 obj_crkbd_rev1
drwxr-xr-x  33 kyagi  staff    1056 Jul 15 20:41 obj_crkbd_rev1_default
drwxr-xr-x  33 kyagi  staff    1056 Jul 17 20:59 obj_crkbd_rev1_kyagi
$ make crkbd:kyagi:avrdude

QMK Toolbox は使用不可

QMK Toolbox は使えないようです。書き込みしようとすると間違ったポート(Bluetooth)を見てしまうため失敗します。

*** Caterina device connected
    Found port: /dev/cu.Bluetooth-Incoming-Port
*** Attempting to flash, please don't remove device
>>> dfu-programmer atmega32u2 erase --force
    dfu-programmer: no device present.
>>> dfu-programmer atmega32u2 flash /Users/kyagi/Downloads/crkbd_rev1_kyagi.hex
    dfu-programmer: no device present.
>>> dfu-programmer atmega32u2 reset
    dfu-programmer: no device present.
>>> avrdude -p atmega32u2 -c avr109 -U flash:w:/Users/kyagi/Downloads/crkbd_rev1_kyagi.hex:i -P /dev/cu.Bluetooth-Incoming-Port -C avrdude.conf
    avrdude: warning at avrdude.conf:14976: part atmega32u4 overwrites previous definition avrdude.conf:11487.
    
    Connecting to programmer: .avrdude: butterfly_recv(): programmer is not responding
*** Caterina device disconnected

おまけ

私が作成したキーマップです。

  • もともと右親指で Ctrl、左親指で Alt、左小指で英数/かな切り替えの人生を送ってきました。英数/かな切り替えは LeftCtrl を Karabiner Elments でトグル設定にして対応しています。
  • タブキーがないですが、タブを利用するのは iTerm2 か JetBrains 製 IDE のみのためソフトウェアの設定で対応できます。iTerm2 は特定のキー(Ctl+t)からアスキーコード 0x09 を送るように設定しています(Preferences > Profiles > Keys > Send Hex Codes: 0x09)

f:id:kyagi:20190717194023p:plain f:id:kyagi:20190718024141p:plain

割れたキーボードを使うのははじめてなので長期使用するかどうかはまだ不明です... 一定期間試運転した後、決心がつけば、本格的に乗り換えるかもしれません。(^_^;

*1:はじめは quantum/quantum_keycodes.h を見ながら自前で keymap.c を編集していましたが、一部マクロの使い方が間違っている部分でコンパイルエラーになったので、だったら既にコンパイル済みの keymap.c からレイアウト部分だけ抜き出せばいいのでは、と思いつきました。実際は LAYOUT_kc マクロを使うか LAYOUT マクロを使うかの違いだったようです。

HAProxy 2.0.1 の Docker イメージは prometheus 機能がデフォルトでビルドされる

f:id:kyagi:20190616100100p:plain

Dockerhub の haproxy:2.0.1 では prometheus へ統計情報を export する機能がデフォルトで組み込まれる

HAProxy 2.0.1 の Docker イメージから拡張機能である prometheus.o がデフォルトのビルドオプションに含まれるようになった。これで前回の記事で紹介したPrometheus機能を使うためにDockefileの1行書き換えて独自ビルドする必要もなくなった。Dockerhub にある haproxy/2.0.1 のイメージをそのまま使うだけになるので、prometheus ユーザーとしてはありがたい限り。

github.com

prometheus.o をデフォルトでビルドに組み込むかどうかは Github で議論があり、prometheus の普及とパフォーマンスへの影響がないことから組み込むことが決定したようだ。

github.com

また 2.0.1 では 2.0.0 でバグレポートとしてあがっていた「数時間稼働させた後にクラッシュする」バグが修正されている。私も 2.0.0 を 2-3日使用した際に同様の問題が発生したため、一時2.0.0の使用を取りやめていたが、これで安心して 2.0 系を使用することができそうだ。(^_^)

BUG/MAJOR: mux-h1: Don't crush trash chunk area when outgoing message… · haproxy/haproxy@c2518a5 · GitHub

HAProxy 2.0 (-dev7) の prometheus サポート拡張機能を利用してマルチスレッドの統計情報を exporter なしで正しく取得する

f:id:kyagi:20190616100100p:plain

HAProxy 1.7 から 2.0 へ移行

前回 試した通り、HAProxy 1.7 + haproxy-exporter の組み合わせではマルチプロセス時に統計情報が正しく取得できない。代替案として prometheus サポートが提供される HAProxy 2.0 (dev7) を試してみた結果、こちらでうまくいきそうなので置き換えることにした。2.0 は 2019 年夏リリースの予定の LTS(Long Term Support) 版となっており、この記事を書いている時点でも開発は終盤に差し掛かっているようだ。

バージョン 並行処理 統計情報 prometheus対応 その他
1.7 マルチプロセス それぞれのプロセスで統計情報を持つ 別途 exporter が必要 マルチプロセス時、特定のプロセスに統計情報を固定する手段はない。haproxy-exporter は counter を gauge として扱ってしまう
2.0 マルチスレッド それぞれのスレッドの統計情報は統合 内部機能で prometheus サポートを提供 追加コンポーネントとして EXTRA_OBJS に prometheus.o を指定して独自ビルドする必要がある

www.haproxy.com

kubernetes 環境で 1.7 を動かしていた場合 2.0 に移行する場合の変更点

  • 1.7 から 2.0 へのアップグレード
    • haproxy 1.7 から 2.0-dev7(2019/06/11 release) にアップグレードした。
    • 起動オプションとして -Ds (Start in systemd daemon mode, keeping a process in foreground.) がなくなっていたので、YAML から削除した。また global parameter の daemon を削除して foreground で起動させるようにした。
  • prometheus サポートに伴う変更
  • マルチスレッドモデルへの切り替え
    • マルチプロセスからマルチスレッドになるため nbthread=4 を追加した。

haproxy1.7.yaml (-Ds オプションを使用して foreground で起動)

        command:
          - /usr/local/sbin/haproxy           
          - -f
          - /conf/haproxy.cfg
          - -f
          - /conf/frontend.cfg
          - -f
          - /conf/backend.cfg
          - -f
          - -Ds   

haproxy2.0.yaml (-Ds オプションはすでに廃止されていたため、グローバルパラメータの daemon を外して foreground で起動。stats が frontend の設定として独立)

        command:
          - /usr/local/sbin/haproxy           
          - -f
          - /conf/haproxy.cfg
          - -f
          - /conf/frontend.cfg
          - -f
          - /conf/backend.cfg
          - -f
          - /conf/stats.cfg

-Ds オプションについては man ページから削除してもらう PR を出したところ 1 時間も経たずにマージされた。(^_^)/

github.com

$ rg -H -- '-D' {haproxy-1.7.0,haproxy-2.0-dev7}/src/haproxy.c
haproxy-2.0-dev7/src/haproxy.c
493:        "        -D goes daemon ; -C changes to <dir> before loading files.\n"

haproxy-1.7.0/src/haproxy.c
460:        "        -D goes daemon ; -C changes to <dir> before loading files.\n"
823:                if (flag[1] == 's')  /* -Ds */
2038:                /* it's OK because "-Ds -f x" is the shortest form going here */

HAProxy 1.7 ではマルチプロセス時の統計情報が正しく取得できない

f:id:kyagi:20190616100100p:plain

HAProxy 1.7 をマルチプロセスで動かした場合、統計情報がおかしくなる

Kubernetes 上で haproxy を HTTP/HTTPS のロードバランサとして使用したところ、動作的には問題ないが prometheus/grafana で出力する統計情報(stats)が正しくないことに気がついた。正確に言うとシングルプロセス(nbproc 1)の場合は正しいものの、マルチプロセス(nbproc 4)になるとおかしくなる。マルチプロセスでそれぞれのメモリに統計情報を保持しているため、それらをまとめて出力する手段を持ち合わせていないことに由来するようだ。

1.7 のマニュアルを参照すると stats bind-process 1 を指定することで最も PID が若いプロセスに限定して統計情報を取得する説明があったものの、実際に試してみたところ、期待していた動作とは違っていた。

  • マニュアル
By default the stats socket is bound to all processes, causing a warning to be emitted when nbproc is greater than 1 because there is no way to select the target process when connecting. However, by using this setting, it becomes possible to pin
the stats socket to a specific set of processes, typically the first one. 

https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#stats

  • 実際の動作

f:id:kyagi:20190616101815p:plain

上記のグラフは 1.7 を利用して 1. シングルプロセス、2. マルチプロセス(nbproc=4), 3. マルチプロセス(nbproc=4, stats bind-process 1) それぞれを設定して、http リクエストを一定時間流した結果である。負荷が一定であれば単純な Counter 値である haproxy_frontend_http_requests_total は rate() した場合、右肩上がりになってから水平になるのが正しいはず。この例では 1. シングルプロセス時は正しい動きになっているものの、2.マルチプロセス(nbproc=4) および 3.マルチプロセス(nbproc=4, stats-bid-process 1) の時は値がおかしくなっている。本来であればマルチプロセス時に統計情報を取得するプロセスを固定するのが stats bind-process 1 のはずだが、こちらを指定しても機能はせず取得するプロセスはランダムになるようだ(stats ページにブラウザでアクセスしリロードを繰り返すと都度 PID が移り変わることも確認)

Each process has its own memory area, which means:
  (... snip ...)
  Information is stored locally in each process memory area and can't be shared:
    - stick table + traced counters
    - statistics
  (... snip ...)

www.slideshare.net

また、haproxy の統計情報を prometheus が取得(pull)するためのエンドポイントを提供するために haproxy-exporter を利用したが、こちらもメトリクスタイプを Counter ではなく Gauge としてしまうバグが 2015 年から放置されているようだ(こちらも fluentd のエンドポイントを curl して出力されるメトリクスタイプのコメントが gauge になっていることを確認)

github.com

このままでは正しく統計情報を取得できないままになってしまうため、解決策として2019年夏にリリースが予定されている 2.0(-dev7) を利用して、再度動作を確認してみることにする(続く) (o)

www.haproxy.com

meishi キットからはじめる自作キーボード入門

f:id:kyagi:20190603014435p:plain

meishi キットとは

遊舎工房さんで販売している自作キーボードの入門セットです。「名刺」サイズの基盤に4つのキーを載せたミニキーボードの組み立てを通して、自作キーボードの作業の概要を把握できるようになっています。費用は meishi キット(1,000 円ほど)と工房利用代金(2 時間で 500 円程度)をあわせて 2,000 円用意しておけば十分です。良心的! (^_^)

最終的に4つのキーを何に使うかは個人が自由に決められますが、デフォルトだと Ctl+z, Ctl+x, Ctl+c, Ctl+y の 4 つが割り当てられています。これは Windows/Mac それぞれで文字列のカット&ペーストのショートカットになっています。私は今のところ、Home, Ctrl+n, Ctrl+P, Enter キーにしています。これはターミナル上でコマンドの検索履歴を辿って Enter をする利用を意図しています。ネットで他の meishi キット作成者の活用法を探してみると仮想デスクトップの切り替えとして使っている方もいるようです。

yushakobo.jp

作業の流れ

大きく分けてハード作業とソフト作業の 2 つがあります。

1. ハード作業キーボードの組み立て

遊舎工房さんでの作業です。はんだづけ作業がメインになります。個人的には「はんだづけ」や「ダイオード」という用語だけで「なんだか難しそう (´・ω・`)」という印象を持っていましたが、工房内で作業していた方やスタッフのかたがとても親切に教えてくださったおかげで、ど素人の私でも 2 時間程度で作業を完了させることができました。ただし、基本的にはハンズオンのようにチューターが逐一指導してくれるわけではなく、meishi キットに付属している QR コードから辿れる以下の URL を教科書として自分で組み立てていくことを想定しているようです。

biacco42.hatenablog.com

ただ、上記のサイトはわかる人には教科書として機能するものの、私のようなど素人は完成図からそこに至るまでの工程を想像できず、一緒にいった友人や工房内で作業していた方、スタッフの方にいろいろご指導いただき、ようやく「やること」がわかったいうのが実情です。同じようなバックグラウンドの方は経験者と一緒に行くか、スタッフの方が比較的空いていそうな時間帯を狙っていくのがよいかもしれません。(´・ω・`)

2. ソフト作業(Mac 用)

ソフト作業はふたつのソフトウェア、QMK Toolbox と QMK Configurator(Web 上で利用可能) を使用します。QMK Toolbox は meishi キーボードのファームウェアを更新(つまり内部のフラッシュメモリを書き換え)するソフトウェアで、QMK Configurator がキーマップを設計するソフトウェアです。

2-1. QMK Toolbox のライブラリのインストール

Installation -> Dependencies -> macOS を参考にして homebrew で必要なライブラリをインストールします。途中でそれぞれ make が走るので結構時間がかかります(2018年の mac mini で15分ぐらい。2013年の macbook で 40分ぐらい)。

GitHub - qmk/qmk_toolbox: A Toolbox companion for QMK Firmware

2-2. QMK Toolbox のインストール

QMK.Toolbox.app.zip をダウンロードして、zip を展開するとアプリを起動できます。

Releases · qmk/qmk_toolbox · GitHub

2-3. QMK Configurator を利用して .hex ファイルの作成とダウンロード

Web サービスとして提供されている QMK Configurator で meishi キーボードの 4 つのキーにそれぞれ割り当てるキーを自分でドラッグアンドドロップをして設計できます。割り当てるキーが決まったら右上の COMPILE からコンパイルを実行した後、右下の FIRMWARE から .hex ファイルをダウンロードします。この .hex ファイルがファームウェアの設計図で、次の QMK Toolbox で読み込み、ファームウェアを更新します。

QMK Configurator

f:id:kyagi:20190603011402p:plain

私の場合、前述した通り、ターミナルの履歴実行の目的で Home, Ctrl+n, Ctrl+P, Enter キーの 4 つを割り当てています。Ctrl + P を割り当てたい場合、いったん「Quantum」タブで RCtl をドラッグアンドドロップから「ANSI」タブで P をドラッグアンドドロップする必要があります。ちなみにデフォルトの LCtrl は私の環境だとことえりが起動してしまい意図通りに動かなかったので RCtl を選んだほうがいいかもしれません。

f:id:kyagi:20190603011320p:plain

2-4. QMK Toolbox を利用してファームウェアの更新(フラッシュメモリの書き換え)

ダウンロードしたファームウェアの設計図の .hex を開いたあと、meishi キット上のリセットボタンを押した後に QMK Toolbox の Flash ボタンを押してフラッシュメモリに書き込みます。成功した場合「Thank you」で終わるメッセージですが、場合によっては Connecting to programmer: .avrdude: butterfly_recv(): programmer is not responding でうまくいかない場合があります。その場合、何度かリセット + Flash を繰り返すか、QMK Toolbox の Auto-Flash にチェックを入れてリセットボタンを「カチカチカチッ」と2回3回連続で押すことで成功したりします。このへんは遊舎工房で一度実施した通りです。

f:id:kyagi:20190603011553p:plain

何を割り当てるか

meishi キットの 4 つのキーにそれぞれ何を割り当てるかを考えるのは一番悩ましい部分である反面、一番面白い部分です。特定のアプリケーションのスイッチャー、仮想デスクトップの切り替え、スリープやスクリーンセイバー、プレゼン時の戻る/進む、その他私のようにターミナル限定で使うなど、使い方次第で可能性は広がります。(^_^)

※私の場合、通常のキーボードの左側で縦置きで運用し、上から仮想デスクトップ1、仮装デスクトップ2、アプリケーションウィンドウ、ミッションコントロールの 4 つで落ち着きました。

f:id:kyagi:20190603211238p:plain

次の一手

meishi キットで自作キーボードの作業概要が把握できたので、次は本格的なキットに挑戦してみようと思います。以前から分割キーボードに興味があったので、Ergo42 Towel あたりを候補にしています。 yushakobo.jp

みなさまもよい自作キーボードライフを! (^_^)/

おまけ

ハード作業からソフト作業まで動画で解説してくださっている方がいらっしゃいます。こちらを参考にするとはんだづけ作業の具体的な手順もわかります。

www.youtube.com

Kubernetes The Hard Way を AWS で実施する

f:id:kyagi:20180216023000p:plain

Kubernetes The Hard Way とは

Kubernetes の公式ドキュメントで Setup の項目をたどると kubeadm を使う例が記載されている。いくつかの機能はまだ alpha/beta であるものの公式でも kubeadm をクラスタ構築に使う流れを後押ししたいように見える。確かに kubeadm (や各ベンダの構築ツール)を使ったクラスタ構築は楽なのだけれど、ツール内部でやっていることを理解しない限りただツールに使われるだけになってしまうのと、トラブル発生時に原因把握もできなくなってしまう。ここでは従来よりスクラッチからのクラスタ構築として定評のある Kubernetes The Hard Way を AWS で実施していく。なお本家は GCP での構築例であり、AWS のサポートには消極的な様子。ここでは少し古いものの AWS 版の Hard Way を公開している方がいるのでそちらをベースに進めながら、AWS 依存の構成やバージョンのアップデートなどでハマった点を備忘録がてらに残しておく。

実際に Kubernetes The Hardway on AWS を完走するまでにやったことと注意点

  • VPC, Subnet, RouteTable, Internet Gateway などは awscli ではなく CloudFormation で実施したほうが便利。何回かやり直すことになると思うので再実行しやすいのと振り返りにも役立つ。 f:id:kyagi:20190603024052p:plain
  • 各手順もそれぞれシェルスクリプトにまとめておくと再実行しやすいし、あとでプロビジョニングツール用に変換もできる。slawekzachcial さんの AWS 版では内部IP取得のために無駄にだらだら awscli を長く利用していたり、user-data に埋め込んでいるところがあるが、そこは固定で埋め込んでしまったほうが混乱がなくてよい。 f:id:kyagi:20190603024504p:plain
  • slawekzachcial さんの例では kubelet v1.9.0 だが kubelet v1.9.0 + ubuntu 18.04 だと couldn't propagate object cache: timed out waiting for the condition になるので controllers, workres ともに v1.12.7 にアップデートする。
  • pods "coredns-595db6f9cb-svfj5" is forbidden: User "system:node:ip-10-240-0-20" cannot patch pods/status in the namespace "kube-system" を解決するために clusterrole も更新する。
  • slawekzachcial さんの例では kubelet + cri-containerd で構築しているが kubelet + containerd に置き換える。cri-containerd はあくまで過渡期の一時用であり、containerd 1.1 から完全体となっているため。
  • 公式ドキュメントでも記載されているが、最低限のマシンスペックとして 2GB RAM, 2 CPUs が必要とされる。最初ケチって t3.nano で構築していたが、これだと workers の構築が完了し kubelet, kube-proxy を動作させると controllers 側が劇的に重くなるので t3.small にした。 https://kubernetes.io/docs/setup/independent/install-kubeadm/
  • EC2 の src/dst チェック外しておく。ENI(Elastic Network Interface) で作成した 10.200.0.0/16 のパケットが ENI に届けられず破棄されてしまう。
  • Route Table の「Main Table」を変更するのを忘れずに。
  • Securigy Group で DNS(udp:53) が塞がれていると、kube-dns service(10.32.0.10) から各 endpoint の coredns pod へ通信できない。いっそ Pod CIDR のネットワーク帯は All traffic を通すのも検証段階ではよいと思う(= All traffic from 10.200.0.0/24, 10.200.0.0/16)。これで node(ec2) からも dig が通るようになる。
  • coreDNS は以下が通れば OK。
ubuntu@ip-10-240-0-10:~/80-k8s-hardway$ dig +short @10.200.0.25 www.google.com kubernetes.default.svc.cluster.local kube-dns.kube-system.svc.cluster.local
172.217.164.164
10.32.0.1
10.32.0.10
  • 正しく完走できれば最終的には以下のようになるはず。 f:id:kyagi:20190603025052p:plain
  • Kubernetes のネットワークモデルについては以下のドキュメントがとてもわかりやすい。AWS を元にして書かれているのと、内部で amazon-vpc-cni-k8s という CNI プラグインを紹介しているがこれは Hard Way で ENI と Route Table を利用して POD CIDR への経路を用意したのと同じように思える。

sookocheff.com

GCP ではなく AWS で Kubernetes The Hard Way を実施するのは、AWS 依存の設定もあり、文字通り以上にハードだったけれど、そのぶん Controll-pane や worker 、そして CNI の概要が理解できたと思う。ただ完全には把握できず、やはり Kubernetes 難しいと改めて感じたのと、バージョンごとに機能や設定がどんどん変わっていくので追随していかないと構築例もあっというまに時代遅れになってしまうと感じた (_o_)

世界各都市の現地時刻を表示するコマンドを作った

仕事上、東京とロサンゼルスの時間を気にする必要があるので、時差を知りたい時は環境変数 TZ にそれぞれの都市を入れて date していたのを peco を使って拡張してみた。timedatectl list-timezones で抜き出したタイムゾーンのリストを peco でフィルタして TZ 変数に渡して date を叩くだけだが、なかなか便利。(^_^;

GitHub - kyagi/localtime: Select and show localtime in cities you pick

f:id:kyagi:20190308031720p:plain f:id:kyagi:20190308031726p:plain f:id:kyagi:20190308031734p:plain f:id:kyagi:20190308031747p:plain

使いかた

  • localtime と入力すると都市名を選ぶプロンプトが表示され、インクリメンタルサーチが走る(内部で peco を使用)
  • 複数の候補を選びたいときは peco の Ctrl+S を利用すればそのまま表示。
  • タイムゾーンを書いた設定ファイルを -c オプションで指定するとその都市の時刻を表示(ここでは東京とロサンゼルスを指定)

IntelliJ から Docker イメージの開発作業を行う

f:id:kyagi:20190303201557p:plain

IntelliJ の Docker Integration プラグインを使う

Dockerfile の修正、ビルド、イメージの動作確認を行うのに、今まではターミナルから docker build -> run -> attach をしていたけれど、全て IntelliJ のインターフェイスでサイクルを回した効率がよかった。

f:id:kyagi:20190303201311p:plain

f:id:kyagi:20190303201423p:plain

IntelliJ だとイメージやコンテナの一覧が見やすいし、右クリックから docker コマンドの操作は大体可能。

f:id:kyagi:20190303203144p:plain

ローカルの k8s クラスタで動かしている各 pod の内部情報は kubectl や k8s dashboard からも参照できるものの、IntelliJ からのほうが見やすい情報もある。

最近はすっかり IntelliJ (JetBrains IDE) の環境に染まってしまった。そういえば git も IntelliJ 経由でしか使用していない。どのツールもそうだけど、最初は使い方や基本概念を学ぶためにコマンドラインから入り、慣れてきた後はより効率的なインターフェイスで利用するのがベストだと思う。かつてはそれが Emacs だったけれど、数年前から完全に IntelliJ に置き換わってしまった感がある。年々 JetBrains 製プロダクトへの依存度があがっていることは自覚しているが、これほど完成された作業環境をお手軽に、柔軟に、素早く、しかも管理コストを少なく構築できるソフトウェアは他にないのではないだろうか。(^_^;

mac mini 2018 向けのディスプレイケーブルとマイク

年末に mac mini 2018 を購入した際に発生した問題がふたつ。

  • それまでのディスプレイケーブルが使えない。USB Type C to HDMI のものを書い直さないといけない。
  • マイクがない(マイクがないと日課のオンライン英会話が mac mini できない)。

しょうがないので以下のディスプレイケーブルとマイクを購入した。mac mini には USB 3.0 ポートは 2 つしかなく、HHKB とマウスで埋めてしまっていたのでマイク用に USB Type C から USB 3.0 へ変化するアダプタも一緒に購入。きちんと動作するのか若干不安だったが、どちらも問題なく動いたのでよかった。他のデバイスもそうだが USB Type C が普及するまではもう少し時間がかかりそうだ...。

ちょっとひっかかったのが外部マイクを接続した際に「システム環境設定」>「セキュリティとプライバシー」>「プライバシー」からマイクに接続するアクセス権をアプリケーションごとに設定する必要があった。

f:id:kyagi:20190226000044p:plain

以上、mac mini 2018 で同様にケーブル難民、マイク難民となっている方への情報提供になれば幸いです。(^_^;