oss な開発は chatgpt が猛威を振るう予感

2時に寝て6時半に起きた。開発の追い込みが佳境に入ってきて集中力が増してきた。

chatgpt と一緒にデバッグ

openldap サーバーの拡張の仕組みに Overlays がある。c 言語でカスタム overlay を実装することで openldap サーバーに任意のフック処理を実装できる。いまやっていることはパスワードの追加や更新をフックしてそのパスワードを id 連携するためのモジュールを開発している。というか、開発済みだと聞いていたモジュールが意図したように動かないのでデバッグしている。例えば ppolicy という overlay を使って次のように設定すると、平文で送ったパスワードをディレクトリサービスの db へ格納する前に平文からパスワードをハッシュ化してくれる。この変換はパスワード変更を overlay でフックして実装されている。

overlay ppolicy
ppolicy_hash_cleartext on

overlay は slapd.conf に設定した順番に実行されるようで、それぞれの overlay に依存関係がある場合は実際の処理にも影響がある。そんな openldap サーバーの拡張モジュールの開発を引き継ぐことになったが、私がまったく openldap サーバーのことをわかっていないので chatgpt を使って理解しながらデバッグしている。これがそれなりにうまくいっていて調査が捗った。但し、chatgpt が教えてくれたことなので完全に正しいかどうかの保証がない。振る舞いで検証できるものはともかく、そうじゃないものは最後に有識者に正しいかどうかを確認する必要がある。

例えば、次のような ldif エントリーをサンプルとして、パスワードは userPassword という属性で扱う。ここで userPassword だけコロンが2重 (::) になっていることがわかる。これは属性の値が base64 でエンコーディングされていることを意味している。こういった2重コロンのような短いキーワードを検索で調べるのは難しい。chatgpt ならピンポイントに答えてくれる。

dn: uid=jdoe,ou=users,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
uid: jdoe
cn: John Doe
givenName: John
sn: Doe
mail: jdoe@example.com
userPassword:: e1NTSEF9bm9ZMU5kdzN3WUdSbFhpdDJUaTY5UW9SeXpXaklEeXc=

openldap は oss だし、ドキュメントもインターネット上にあるので構造体の定義や c 言語のサンプルコードも書いてくれる。それらが完全に正しいか、私には判断できないが、openldap のソースコードで調査するところの当たりをつけるには十分な情報を返してくれる。カスタム overlay を開発するときの主要なエントリーポイントと ldap 操作のタグ名は次になる。

  • bi_op_bind: バインド(認証)操作に対応するエントリーポイント、LDAP_REQ_BIND
  • bi_op_search: 検索操作に対応するエントリーポイント、LDAP_REQ_SEARCH
  • bi_op_compare: 比較操作に対応するエントリーポイント、LDAP_REQ_COMPARE
  • bi_op_modify: 修正(属性の追加、削除、変更)操作に対応するエントリーポイント、LDAP_REQ_MODIFY
  • bi_op_modrdn: エントリ名の変更 (MODIFY RDN) 操作に対応するエントリーポイント、LDAP_REQ_MODRDN
  • bi_op_add: エントリの追加操作に対応するエントリーポイント、LDAP_REQ_ADD
  • bi_op_delete: エントリの削除操作に対応するエントリーポイント、LDAP_REQ_DELETE
  • bi_op_abandon: 中止操作に対応するエントリーポイント、LDAP_REQ_ABANDON
  • bi_op_extended: 拡張操作に対応するエントリーポイント、LDAP_REQ_EXTENDED

例えば、LDAP_REQ_ADD は ldap.h で次のように定義されている。

#define LDAP_REQ_ADD        ((ber_tag_t) 0x68U) /* application + constructed */

これを gdb でデバッグしてタグを確認するときは次のように Operation 構造体内の o_tag をチェックすればよい。gdb で16進数表示するときは /x を指定する。

(gdb) print /x op->o_tag
$8 = 0x68

ppolicy よりも前にカスタム overlay を設定すれば平文のパスワードにアクセスできそうにみえるのだけど、gdb でデバッグしているとハッシュ化済みのパスワードになっていた。

あと稼働している openldap サーバーに gdb で attach してデバッグする方法も chatgpt に聞きながら行った。やりたい操作に対して gdb のコマンドを教えてもらってすぐに検証してフィードバックからさらに質問できるのでインタラクティブな repl のような環境と chatgpt は相性がよいように思えた。gdb のコマンドを覚えておく必要も、ググる必要もないことに気付いた。

近況報告

元同僚と 約1年ぶりの近況報告 の雑談会をしてきた。これで3回目かな。毎年の恒例行事のようになってきた。兵庫県の住みたい街ランキングでいつも上位にある 西宮市 でカレーを食べて、バーで飲んできた。三ノ宮から西宮は快速で15分程度の距離。すぐ行ける場所なんだが、とくに行く機会がなかったので神戸に引っ越してきて5年以上経つのに電車で行ったのは今回が初めてになる。いつも通り近況を聞きながら、みんな私と同じぐらいの世代なので今後のキャリアの方向性などを話していた。

私は起業して税金やその仕組みに関心をもつようになり、起業する前より少し詳しくなった。知人から節税相談を受けることもある。税金の基本的な考え方として、1つの大きな収入に対して節税することはできない。自由に使えるお金がほしかったら基本的に節税できない。税金をたくさん払って貯金するしかない。一方で個人と会社に資産を分割したり、共済や基金を活用することで手取りの収入は減るが、支払う税金は少なくなって中長期でみると資産が増える。例えば、共済や基金に積み立てたお金は原則としては退職所得で戻ってくるので、ずっと優遇された 退職所得の所得税 により、最終的に支払う税金が少なくなるからである。これが税金を支払う基本的な考え方。自分の手元にお金を残した上で税金を払いたくないが、どうすればよいか?とよく聞かれるが、そんなことはできないというのが模範回答になる。元同僚も私もそうなのだが、もはや自分の生活にお金をあまり必要としていない。私が節税の仕組みを調べたり実践したりするのは、税金の仕組みを学ぶために過ぎない。ただ知識として学ぶよりも、実際に実践して運用してみる方が学びになる。

以前の 出張もくもく会 の後で懇親会のときにそのうち資本主義は新しい制度にとって変わられるのではないかという話題があった。それは行き過ぎた資本主義の弊害と、資本主義である限り40時間/週の労働時間から抜け出すには資本家になるしかなくて、人類はすでにこれだけ技術があるのだからもっと多くの人が今よりも働かずに食べていけるのではないかと多くの人が考えている。私の場合も、実質は自分のやりたいことしかやってなくて、自分のために働きながらも、老後のために一応はお金をもらっておくみたいな働き方になっている。この考え方は資本主義の次の制度へ移行するときに活きてくればいいなと思う。

rpm のパッケージングを作り直す

1時に寝て何度か起きてあまり眠れなかった。昨日は遅くに帰ってきて晩ご飯を遅くに食べたので寝ていて吐き気がしてうまく眠れなかった。寝る前に食べることはできないみたい。

rpm パッケージング再び

ビルドができるようになったモジュール を rpm でパッケージングする。rpm でのビルドもできる状態で渡してもらえたので私が開発したモジュールを追加してパッケージングを修正する。rpm のパッケージングを行うのも5年ぶりといったところ。コンテナに慣れてしまって rpm を使うことはもうないと思っていたけれど、まだまだ現役であることを実感する。spec ファイルは普通に読めるので既存の設定や、他の rpm パッケージの spec ファイルの記述などもみながら、自分のモジュールで必要な設定を追加していく。久しぶりだったわりには順調に作業が進捗して2-3時間もやっていて追加の修正をして、実際にインストールして動作確認もできた。

rpm のマクロを確認する。

$ rpm --eval "%{_libdir}"
/usr/lib64

あるサーバーサービスを systemd 経由で実行させる。内部的に環境変数を使っている。systemd の EnvironmentFile で環境変数を設定したファイルへのパスを指定できる。例えば、次のように EnvironmentFile にパスを設定する。

[Service]
Type=simple
EnvironmentFile=/opt/path/to/my.env
ExecStart=/opt/path/to/bin/my-service
KillMode=process
StartLimitBurst=2
Restart=on-abnormal
User=ldap
Group=ldap

この環境変数にはパスワードのような機密情報も含むので rpm の %files で root 権限でのみ読めるようにアクセス制限を設定する。systemd 自体は root 権限で動くので環境変数の設定は root が行って my-service は ldap のユーザー/グループ権限で動く。

%attr(600,root,root) %config(noreplace) %{_sysconfdir}/path/to/my.env

ローカルのゲスト os に開発環境を作る

0時に寝て7時に起きた。いろいろうまくいってない。

vagrant 再び

rpm でパッケージングされた openldap サーバーの動作検証をするために vagrant で rockylinux/8 Vagrant box の環境を構築する。 rockylinux 8 だと次のようなエラーが発生した。

VBoxManage: error: Failed to open OVF file 'path/to/.vagrant.d/boxes/rockylinux-VAGRANTSLASH-8/7.0.0/virtualbox/box.ovf' (VERR_FILE_NOT_FOUND)

既知のバグとして次の forum にワークアラウンドが書かれている。

uefi なマシンのせいなのかな?詳細を理解していないけど Vagrantfile を次のようにする。

Vagrant.configure("2") do |config|
  config.vm.box = "rockylinux/8"
  config.vm.provider "virtualbox" do |domain|
    domain.customize ["modifyvm", :id, "--firmware", "efi"]
  end
end

修正済みのイメージをダウンロードするようにメタデータを作成する。

$ vi box-metadata.json
{
  "name" : "rockylinux/8",
  "description" : "Rocky Linux 8 7.0.0 Bugfix",
  "versions" : [
    {
      "version" : "7.0.1-20221213.0",
      "providers" : [
        {
          "name" : "virtualbox",
          "url" : "http://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-Vagrant-Vbox-8.7-20221213.0.x86_64.box"
        }
      ]
    }
  ]
}

再度 vagrant の環境を作り直す。

$ vagrant box add box-metadata.json
$ rm -rf .vagrant/  # 古い設定を削除
$ vagrant up

vagrant を使うのも4年ぶりになるかな。コンテナに慣れてしまうと久しぶり感がある。使い方を忘れていて調べながらやってた。

vagrant にポートフォワーディングの設定を追加

$ vi Vagrantfile
...
  config.vm.network "forwarded_port", guest: 389, host: 1389   # ldap
  config.vm.network "forwarded_port", guest: 636, host: 1636   # ldaps
...

これでホスト os からゲスト os へ接続できる。

==> default: Forwarding ports...
    default: 389 (guest) => 1389 (host) (adapter 1)
    default: 636 (guest) => 1636 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)

ここでは ldap サーバーに対して Apache Directory Studio で接続できるように ssh のポートフォワーディングを設定している。

scp でファイルを転送

config を出力する。ssh の秘密鍵へのパス設定をしてくれるので scp のオプションに指定しなくて済む。

$ vagrant ssh-config > ssh.config

ポート番号も config に記載されているけれど、それは指定しないと scp できなかった。

$ scp -P 2200 -F ssh.config path/to/myfile vagrant@localhost:

vagrant ユーザーのパスワードも聞かれて vagrant を指定すればコピーできた。config を作ってもあまり便利ではなかった。

vagrant-scp というプラグインがあるのでインストールしてみる。

$ vagrant plugin install vagrant-scp

次のようにして使う。この方が簡単。

$ vagrant scp path/to/myfile ./  # 仮想マシンのホームディレクトリにコピーされる

リリースまで残り2週間

0時に寝て4時に起きて6時半に起きた。最近は以前より眠れるようになりつつある。今日は定例会議とバグ調査とコードレビューと検証をしていたらすぐに1日終わってしまった。

ビルド問題の解決

2月の上旬 から問題を認識していて、ある c 言語のモジュールが正常にビルドできない問題がようやく解決されてビルドできるようになった。libtool を使ってライブラリをビルドしていて、歴史的経緯からシンボル名の書き換えが必要だったみたい。2週間後にリリースされるモジュールの開発前の状態でビルドが通ったのがいまという状況。ここから私がそのモジュールに対して追加の開発を行う。本来の私のお仕事ではないけど、このモジュール開発の私が負う方がチームとしての成果が大きいと判断した。

ビルドができるようになるまで2ヶ月程待ったことになる。普通に考えたらリリース延期だが、担当者の割り当ての課題もあって、もうこれは不可抗力としてそのままリリースしようと思う。おそらく誰もこの件に関して本来の開発の在り方についての言及しないと私は考えている。おそらく品質も信頼できないものだと推測する。残りの2週間で追加の開発を一目散に駆けて成るように成るのを私も受け入れることにしようと思う。

サーバーサイド開発とセマフォ

0時に寝て7時に起きた。

web api サーバーへの負荷テスト

web api サーバーへ数百から数千件の同時リクエストを送ってエラーが発生しないことを確認する。チームのメンバーがテストを実施していたら producer がメッセージを送信するときに rabbitmq との接続エラーがいくつか発生した。いくつか対応方法を考えられるが、既存のコードを大きく変更せず解決するものとしてセマフォを導入してみた。自分で作っても難しいものではないが、golang.org/x/sync/semaphore で準標準パッケージとして提供されている。次のように簡単に使える。

sem := semaphore.NewWeighted(maxConcurrentSessions)
...
ctx := context.Background()
if err := sem.Acquire(ctx, 1); err != nil {
    return err
}
defer sem.Release(1)

これで rabbitmq との同時接続数を制御する。rabbitmq 側もどのぐらいの接続を受け付けるかは Networking and RabbitMQ を参照して設定で制御できる。デフォルトは 128 となっているので 1024 ぐらいまで増やしてみた。

サーバーサイド開発のおもしろさの1つとしてボトルネックは移動するという概念がある。必ずどこかにニーポイント (ボトルネック) は現れるので意図したパフォーマンスや負荷を耐えるようにリソース制限をしてサーバーが堅牢になるよう調整する。この手の作業はサーバーサイドエンジニアをやってきた私の得意とするところ。

ubuntu の環境構築

0時に寝て8時に起きた。昨日は出張から遅くに帰ってきたのでバテた。

ストレッチ

昨日はもくもく会で遅くに帰ってきたので毎週のストレッチを土曜日から日曜日に変更していた。ここ1-2ヶ月ほどでは最も調子がよかった。今週は出張していて普段より健康的な生活をしていた。というのは、お手伝い先のオフィスでは原則として私は9-18時でしか働けないため、業務の都合でずっと座りっぱなしにならない。例えば、自社のオフィスだとだいたい8時から始業して遅いと23時ぐらいまでずっと座りっぱなしになってしまう。たまたまホテルもいつもよりも離れた場所にとり、10分ほど歩く距離だったのでちょうどよかった。帰ってからホテルで2-3時間作業していたりもするのだが、それでも同じ姿勢でずっと座り続けている方が体にとってはよくないことがわかる。今日の開脚幅は開始前152cmで、ストレッチ後156cmだった。座っている時間が短かったために腰の張りはほとんどなかった。

ubuntu 22.04 lts の環境構築

先日 マシンに ubuntu をインストールした 続きの話し。東京出張があったり、開発の終盤でいろいろやっている中で開発環境を作り直すインセンティブが低かったので環境構築が遅くなった。過去の環境構築の issue が残っているのでそれをみながらやれば5-6時間もあれば作り直せた。結論から言って、マシンスペックが上がって、os も新しいものに変わったので開発環境としてはめちゃくちゃ快適になった。好みだが、私はリソースの潤沢なデスクトップマシンに linux をインストールして開発するのが一番しっくりくる。主観的に感情的にその構成が好きだというもの。

realforce の bluetooth キーボードの設定をするのにもう1つキーボードが必要なことに気付いた。私は bluez というツールを使って bluetooth キーボードのペアリングをしている。ペアリングするためには bluez の bluetoothctl という cli から操作してペアリングを行う。realforce のキーボードは有線/bluetooth 接続を両方同時につなぐことはできないため、bluetooth 接続するためには別のキーボードを接続して cli 操作しないといけない。

$ bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# scan on

bluetooth キーボードから接続要求を送る。

...
[NEW] Device F6:9D:A5:41:B7:1F REALFORCE_2
...
[bluetooth]# info F6:9D:A5:41:B7:1F
Device F6:9D:A5:41:B7:1F (random)
	Name: REALFORCE_2
	Alias: REALFORCE_2
	Appearance: 0x03c1
	Icon: input-keyboard
	Paired: no
	Trusted: no
	Blocked: no
	Connected: no
	LegacyPairing: no
	UUID: Human Interface Device    (00001812-0000-1000-8000-00805f9b34fb)
	RSSI: -51

マシンからデバイスを検出したらデバイス情報を確認してペアリングを実行する。

[bluetooth]# pair F6:9D:A5:41:B7:1F
Attempting to pair with F6:9D:A5:41:B7:1F
[CHG] Device F6:9D:A5:41:B7:1F Connected: yes
[agent] Passkey: ***

これでペアリングが実行されて bluetooth 接続できるようになる。ubuntu 20.04 lts の頃より進化しているのは接続/切断時に電池の残量も表示されるようになった。キーボードには充電池を使っているので地味に嬉しい。残量が少なくなってきたら帰るときに充電を仕掛けて帰れる。

今回の環境構築で1つはまったものがある。vagrant の仮想環境として virtualbox を使う。secure boot のために virtualbox をインストールするときにパスワードを mok (Machine-Owner Key) に登録しないといけない。この作業手順が分からなくて右往左往していた。インストール時に mok のダイアログが表示されてパスワードを登録するが、この後に os を再起動して bios 起動時に特別なダイアログが表示されて mok に登録したいパスワードを入力する。アプリケーションのインストール時に bios の設定が必要という概念が私の頭の中になくて分からなかった。これをやらないと virtualbox サービスが正常に起動しない。調べていると ubuntu 標準の virtualbox は壊れていて 3rd party の contrib なパッケージを使えという古い記事も出てくる。22.04 なら ubuntu 標準の virtualbox でも問題なく、mok の登録後に systemd から virtualbox サービスが起動することを確認した。再起動後の mok のダイアログは1度しか出てこないのでうっかり見逃してしまったら再設定しないといけない。次の cli で再設定できる。

sudo dpkg-reconfigure virtualbox-dkms

気分転換のもくもく会

0時に寝て4時に起きて6時に起きてだらだらして7時半から広いお風呂入ってきた。

the b 水道橋

昨日は the b 水道橋 に宿泊した。the b というホテルブランドらしい。初めて宿泊した。あまり新しい施設ではないし、部屋も狭かったけれど、受付でアイスクリームが無料というサービスをしていたり、大浴場があったりと限られたリソースでがんばろうとしている雰囲気がみえておもしろいホテルだと思う。値段も他のビジネスホテルより少し割安だった。水道橋駅から10分ほどだとは思うが、微妙に歩く立地が割安にしているのではないかと思う。水道橋はどこに行くにもアクセスがよいのでよい場所だと思う。晩ご飯に近くの つどい酒場えすと。 という居酒屋にふらっと入ったらよいお店だった。お店もほぼ満席だった。部屋は普通もしくは手狭なのだけど、全体としてはよい宿泊体験だったと思う。また機会があったら泊まるかもしれない。

もくもく会

出張もくもく会 を開催した。3月は週末にお仕事していなければバテて家で寝ているといった、あまりよくない状態だったので気分転換も兼ねてのもくもく会だった。いつもと違う場所、違う人たちとやり取りすることそのものがマンネリを解消する上でもよかったように思う。12人が参加してくれた。20人ぐらいが入れる広い場所を借りてみたものの、思ったより集まらなかった。前回来てくれた方たちも何人かいた。レンタルスペースなので参加費いらないですか?と問い合わせしてくれた方もいた。もくもく会イベントはうちの会社の交際費を使う手段の1つでもある。

会場は VILLENT 秋葉原 というレンタルスペースを借りた。10時00分から17時30分まで7.5時間を借りて税込20,988円。前回の会場 は定員が10人なものの、窮屈で狭かったため、今度は広い場所を借りることにした。定員は24人なものの参加者は私を含めて13人だった。だいたい4人座れる机に2人ずつ、たすきに座ってスペース的には余裕があってちょうどよかった。次回またもくもく会をやるときは20人ぐらいのスペースに対して10人程度の募集にしようと思う。

会場はサイトの写真をみて想像したよりも汚い (古い) 施設だった。あとで参加者と話していて借りるときに google map でビルの外観をみればいいと教えてもらった。電源タップはないと書いてあったが棚を探すと3つほど見つけた。インターネット接続にちょっとしたトラブルがあった。wifi ルーターには接続できるけど、インターネットにアクセスできない。あれー?と思って問い合わせしたら自動音声でルーターの電源の on/off を試せと流れて、wifi ルーターを探してみたら、その後ろに置いてあった onu (光回線終端装置) の電源が入ってなかった。wifi ルーターだけ電源が入っていて onu だけ電源を切ることはないと思うので前に使った人たちのいたずらかもしれない。くそーって気分だった。wifi 速度は7人接続している状態で240Mbpsほどあったので十分に速かった。

あとで施設のレビューをみてみると「清潔感」が 4.0 と低くはないけれど、他の項目に比べて明らかに低い点数となっている。私ならこの項目に 3.0 をつけるかなと思う。価格が割安なのでそんなものと言えるが、特定の項目だけ統計の値が低いのならなにか理由があると考えてよいということを学んだ。ちなみにそれでも 4.0 と点数が高いのはすべての項目を 5.0 に付けているレビューアがいるためだと考えられる。ちゃんと点数を付けているレビューアは 2.0-4.0 を付けていたようにみえる。

午前中に10人ほど参加して、午後から2人参加して、参加者の大半は web 系の人たちにみえた。午後から来た2人組は期待したものと違ったのか1-2時間作業してすぐに帰られた。窓を開けておくと周りの工事の音が少し騒々しい。途中で少し寒いということで窓を閉めたら騒音はそれほど気にならなくなった。私は日記を書いたり、お仕事のドキュメントを書いたりしていた。図書館で勉強するような雰囲気になっていて作業に集中できてよかった。

一日中リファクタリング

0時に寝て7時に起きた。昨日は夜にホテルで作業しようと思いながらテレビをみているうちに寝落ちしてた。朝から夜までずっとリファクタリングのためにコードを書いたり、コンテナ環境の設定を変更したりしていた。

mongodb のコネクションプール

MongoDB Drivers の Connection Example に次のようなことが書いてある。

Reuse Your Client

We recommend that you reuse your client across sessions and operations. You can use the same Client instance to perform multiple tasks, instead of creating a new one each time. The Client type is safe for concurrent use by multiple goroutines. To learn more about how connection pools work in the driver, see the FAQ page.

mongodb drivers の client は goroutine safe なので再利用することを推奨している。内部的にはコネクションプールをもっていて mongodb とのコネクションを再利用できる。具体的にはライブラリ内部に次のようなコードがみつかる。context にセッション情報があればそれを使い、なければクライアントの sessionPool (コネクションプール) を使ってセッションを取得して mongodb にアクセスする関数の終わりで終了処理を行う。

sess := sessionFromContext(ctx)
if sess == nil && coll.client.sessionPool != nil {
	sess = session.NewImplicitClientSession(coll.client.sessionPool, coll.client.id)
	defer sess.EndSession()
}

既存のコードはコネクションプールのことを考慮していないコードになっていたので大きくリファクタリングして効率化した。

docker hub の pull 制限

午前中はリファクタリング、午後は docker compose 環境の変更と再構築、午後はバグ修正と一日中 docker image を取得する作業をしていた。gitlab ci/cd が動くとテストと docker image 生成の処理が動くのでその過程で関連する docker image を pull する。夕方になって gitlab ci/cd で初めて次のエラーが発生することに気付いた。前にお手伝いしていた職場でもそういう現象が起こると聞いて、docker login するコードを github actions のスクリプトに追加していたので、rate limit がかかることは知っていた。

You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limits.

Understanding Your Docker Hub Rate Limit によると、6時間あたり匿名アクセスは100、 free ユーザーは200を上限としているらしい。匿名アクセスは ip アドレスでカウントしているのだろうから場合によっては会社内からのアクセスをすべてカウントされたりするかもしれない。課金するとこの上限が24時間あたり5000になる。docker hub のプライベートリポジトリを利用する意図で team プランの課金を検討していたが、docker hub のアクセス制限を緩和するために課金する必要があるかもしれない。

リリース後の展望

0時に寝て7時半に起きた。そろそろ出張バテしてきた。

プロジェクトの進捗報告

出張したときの月例報告の5回目。前回の進捗報告はこちら 。私のマネジメントの不手際で1ヶ月延期 (元の計画通り) して、未だに開発は完了していないものの、今月末にリリースできる見通しでプロジェクトを進めている。おそらくあと1-2回は私が休出するのだろう。これからメンバーにはできる限りの QA テストを3週間に渡って行ってもらう。

チームが fix した3月の issue 数は47、そのうちの34を、enhance ラベルが付いたものは12でそのうちの9を私が担当した。クリティカルパスになりそうなものは、一旦はメンバーにアサインするものの、進捗をみて遅れていれば私が issue を引き取って対応している。先月から引き続き、やばそうな芽が出てきたら私が本気出して対応する。見た目上のスケジュールには影響を与えないようにしている。先月の反省で早めに引き取ることにしたのでずるずる後ろへ延びることはない。このやり方をすると、私がボトルネックになりかねないが、私の工数は調整次第でメンバーよりも大きくできるのでいまのところ問題ない。リリースまで1ヶ月を切った中で取り得る手段は限られてくる。

2月から ハドルと雑談 の試験運用をしていた。ほぼ毎日午前中は私が slack のハドルに在籍 (オフィスアワーに近い取り組み) するようにして、メンバーから雑談する機会は増えるかどうかを試していた。約2ヶ月やって結果は次の通りとなった。

  • 対象日数: 34日
  • 雑談人数: 10人
  • 雑談時間: 5.75時間

3日に1日ぐらい軽く雑談するといった結果になった。おそらく私がハドルにいなかったら話す機会はなかったのでこの価値をどう見積もるかは人によって分かれると思う。うちのチームはリモートワークが中心なので雑談する機会があるほど望ましい。それほど強く提案するわけではないが、slack のハドル活用をもっと展開してもよいのではないかと経営者に推奨した。

聞いた話では着任前にこのプロダクト開発は2年近く迷走していたらしい。それによって要件は整理されていたと言える。私がこの半年でリリース (予定) できる状態にしたのを評価してもらえているようにはみえる。余談だが、自分のスキルを社会の役に立てられるのがいまは嬉しい。前職では、誰でもできる簡単なお仕事しかできず、開発もあまりつまらなかった。いまは自分がよいと思うものを一定の裁量で判断し、さらにマネージャー経験も積めて、今回のお仕事は私の中でも達成感は高い方でもある。

あとは今後の開発の話し、販売戦略の話しなどもしていた。4月末で初期開発の区切りもつく。今後は毎月1週間も出張しなくてよいのではないかという話しもして、5月は会議を2-3日に集中してやったらいいんじゃないかということになった。出張はそろそろ疲れてきたのと、私がオフィスにいてもメンバーは半分以上リモートワークなのでオフィスに来る意義があまりない。うちのチームはリモートワークで開発に支障が出ない仕組みを構築できているとは思う。

rsync に daemon モードがあるらしい

23時に寝て2時半に起きて4時や5時に起きて7時に起きた。泊まっているホテルの低反発枕の寝心地がよい。

rsync daemon over ssh

外部向けのドキュメントを公開するための gitlab ci/cd を構築した。web サーバにドキュメントをアップロードする手段として rsync を使っている。rsync over ssh でデータを転送するときにさらに daemon モード (rsyncd) という仕組みがあって、権限や書き込み先の acl なども細かく制御できる。手順や設定は古の古臭い雰囲気はするけれど、実用的には ssh の秘密鍵を使ってちょっと高機能なアップロードを実現できる。ssh agent で鍵登録できていれば次のような cli でセキュアに rsync できる。全然知らない方法だったので学びの1つになった。

$ rsync \
    --verbose \
    --rsh ssh \
    --stats \
    --compress-choice=zstd \
    --compress-level=10 \
    --itemize-changes \
    --recursive \
    --checksum \
    --delete \
    local/ ${USER}@${HOST}::${RSYNC_DIR}

LLMを使ってみる会

LLMを使ってみる会 に参加した。私も chatgpt に調べものやちょっとしたことを聞くようになったりしているが、他の人たちがどんな用途に使っているのかも知りたくて参加してみた。fin-py のイベントだったのでみんな金融系のドキュメントの要約に使っているのが多そうにみえた。あとは研究テーマとして gpt/llm を取り上げている人たちも何人かいた。

考えているとストリームが発生する

18時から20時半ぐらいまで寝て、それから晩ご飯を食べに出掛けて、23時頃に戻ってきてまた寝て、4時に起きて、6時に起きた。出張の初日は不規則な寝方になる。

定例会議とふりかえり

リリースまであと3週間。一部の開発がまだ完了していないことに大きなストレスと懸念を感じつつ、進捗はしているそうなのでその対応が完了するのを待つ。いまは日々の進捗や発生する事象に注意を配りつつ、メンバーは QA レベルのテストを、私は淡々とリリースの準備をしている。外部からアクセスできるプライベートなコンテナレジストリを docker hub でお金を払うか、自社で運用するかの決めの問題や外部向けにドキュメントを公開するための決めごとなどを確認したりしていた。

毎月のマイルストーン終了後にふりかえりをしている。今月は対応した issue のうち、70%超を私が fix しているのであまり話題がないかなぁとか思っていたけど、全然そんなことはなく、活発にふりかえりのコメント (付箋に書く) が出てよかった。当初は付箋に書いた内容に対して関心のあるものをメンバーに投票してもらっていた。そして、メンバーの関心の高いマークがたくさん付いたものから掘り下げて聞くようにしていた。最近は3人でふりかえりをやっているため、すべての付箋をみていっても10個未満程度、すべてヒアリングしても時間がちょうどよいので投票をやめた。そうすると、メンバーが自分のやったことや思ったことを他者へ話す機会になっていて、これは内省を促す意図でとてもよいことじゃないかと思うようになってきた。

ふりかえりをしない人やチームは成長しない

これは私の持論だ。うまくいかなかったときにふりかえりすると、当事者が嫌な気持ちになったりしんどかったり、責任を感じたりとネガティブなイメージから、私の経験則ではふりかえりを行わないチームの方がずっと多かった。こういう小さい積み重ねを継続的にやるのは後になってその人の価値観や成長に影響を与えるのではないかと最近は思う。うちのチームでは厳しく責任追及はしないのでメンバーが率直的にこれができなかったとふりかえることはできるようになっているとは思う。

ふとふりかえりをしていてこんな言葉が私の口から出た。

作業の進捗をストリームとして確認できると嬉しい、ストリームを眺めているとメンバーが考えているのかどうかが分かる

エンジニアリング組織論への招待 に次のような節がある。

「悩む」と「考える」の違い

「考える」は行動であり、「悩む」は状態なのです。考えているのであれば、それはメンターがその行動を見ることができます。しかし、「悩む」であれば、メンターは心の状態を観察することはできません。

悩んでいる状態は手が止まっていて、頭の中で思考がぐるぐる巡っていて、もやもやしている状態。考えているとは、課題を書き出したり、分解したり、調査したりと忙しく行動していると言える。当然、考えないと優れた品質のアウトプットは出せない。正に私がやっている課題管理も、そのための課題管理システムも考えていることを確認・監視するために有効な手法とシステムであることが伺える。チームのふりかえりをしながら、そういった話しをメンバーに共有したりしていた。