ちなみに

火曜日の空は僕を押しつぶした。

ユニコーンはいかにしてモチベーションを生むか

あの アジャイルサムライ のジョナサン・ラスマセンの新作。角谷さんの翻訳で間違いないのが出ました。 社のブログ向けに今のチームとの対比を絡めて書こうともがいてますが、ひとまず感情だけを先に書き殴ります。 (こうやって読者の反応を見ずにブログマーケットフィットを想像して推敲に推敲を重ねているのがまさにエンタープライズ人間っぽいのでこっちは一切推敲していない)

この本はいまや音楽ストリーミングのデファクトとなったSpotifyがすさまじい勢いで成長していたころの著者の体験を元に書かれている。 インターネットには少し批判的なようすが出てきていたスクワッドやトライブなどの実際の様子や、全体の方向を統一しつつも速度を出すためにやってきたこと、そのための文化の話などが書かれている。

残炎ながら、これを読んで明日から真似しようと思って手に取って人には向いていません。 方法論の本ではなくて、俺たちにはこのやり方がうまくいったという例が書かれている本で、ちりばめられたヒントから自分達はどうなんだろうと考えるための本だと思います。 エンタープライズ企業でも当たり前にアジャイルな開発をするようになって久しくであったりとか、ユニコーン企業はスクラムなんてやっていないなどと強い言葉も書かれているが、方法論の本だと思って真に受けてスクラム止めますなんていうことは推奨されてないので注意が必要。

目につくのは「自立、信頼、権限」という言葉だけれど、僕はこの本はモチベーションの本だと思って読みました。

強いプレッシャーと不確実性の中で素早くプロダクトマーケットフィットを見いだすには、短いイテレーションで改善を続けるアジャイルな開発は前提条件であって、その速度と品質をさらに上げるのがモチベーションだと。 内発的なモチベーションをもってプロダクト開発に関わるチームは自立して前に進めるし、そんなチームを上層部は信頼して、権限を譲渡出来る。そうするとチームのモチベーションはより上がっていく。 本ではまずは信頼して権限を与える。と書いてあるけど鶏卵になっていて我々開発チームとしてはまずは内発的なモチベーションを得るところから始めるのが良いのではないかと思います。

そのために方法として、やはり「目的」というのが重要で、本ではカンパニーベッドというものを使って1つの目的にフォーカスする方法が書かれている。 会社やプロダクトの目的に心から賛同出来る場合は自然とモチベーションというのは沸いてくる。これはOSSと同じでプロダクトを作ることに関わること自体が目的に出来ている。 つまり自分からそのプロダクトを作りたくなるのだ。そりゃあアウトカムも出てくる。 アウトカムが出てきたらフィードバックを得られるので、さらに改善していける。次のカンパニーベッドをよりうまく決められるのだ。

プロダクトがよくなってくると次の段階が訪れる。 プロダクトを作っている自分達の環境をもっとよくしたいというモチベーションにつながる。 これが生産性の話につながってきて、さらに開発速度は上がっていく。 (これは逆のループもあって開発速度を上げるとフィードバックが早くなってチームの信頼も獲得して権限を得て、会社はフォーカスする方向を決められるようになる。これは明日から出来る!!!会社が変わるのを待っている暇があるなら手を動かそう。)

それも楽しくてやっているのだ!!!

こういった一連の流れを文化として定着させることで組織として強くなっていく。 ハードだけれど楽しい職場で、そして結果もついてくるような環境は最高だと思いませんか。 そこを目指すためにどうやったらいいのか考えるきっかけとしてこの本はとてもいい石を僕の中に投げ込んでくれたと思います。

こうやって本を読むことで内発的なモチベーションを得られるのだけれど、これは正直すぐに消える。 モチベーションが消えないようにどうすればいいのか。「近道はない。やるしかないんだ。」の精神で何かをやってみるしかないのだ。

フィーチャフラグを使いたい

今のチームでは GitHub ワークフローを使っていて、フィーチャブランチを育てている。 この方法はまあまあうまくいっていて、ふだんは何の問題もない。

しかし、ある機能の開発に時間がかかると問題が生じる。特に複数のブランチがそういう状態になると目も当てられない。 すばやいデリバリーのための施策が逆に速度を落とすための足かせになってしまう。

  • masterと乖離してしまいマージの難易度が上がる
  • どのブランチに入った機能なの分からなくなる
  • 頻繁なブランチ切り替えが発生してそのたびに環境を作り直す
  • リリースするときにマージするのでいわゆるビッグバンリリースになってしまう

こういった問題を回避するにはフィーチャフラグというテクニックがあって、コードはメインブランチにどんどんマージしてリリースするんだけれど機能としては伏せておくみたいなやりかた。 どんどんマージしてリリースしちゃうので上のような問題は起きない。

別の問題はあってフィーチャフラグの仕組み自体が技術的負債になってしまったり、うまく運用しないと開発中の機能が公開されてしまったり既存の機能に悪影響を起こしてしまったりする。 こういうのはチームの練度にもよりそうなのでやっていくしかないと思うのだけれどけっこう不安が大きい。

新規追加ならやりやすいのだけれど、既存機能に手を入れる場合はうまく新旧のコードを管理する必要があって難しそうだし、速度が落ちそうで心配。

しかし、よく考えるとブランチの運用コストや、リリースして失敗したときのやり直しなどを考えると、ただただ分岐を書くだけなので実は速度は上がるはず。 既存コードに手を入れるときもまあきっとうまくやれば良い感じで出来ると思う。

フィーチャフラグでうまくいくことはすでに多くのチームが成果を出していることで証明されているが自分でやるとなると勇気が必要ですね。

Dockerコンテナ内でプライベートリポジトリのGemをBundlerでインストールしたい

tl;dr

  • 認証情報をイメージに残さずにGitHubのプライベートリポジトリのGemをインストールしたい
  • ビルド時にインストールする場合は --mount=type=ssh がおすすめ
  • 実行時にインストールする場合には BUNDLE_GITHUB__COM を使うのがおすすめ

やりたいこと

Docker内で bundle install するときに社内で使っているプライベートなGitHubリポジトリのGemが含まれる場合、なんとかして認証情報を渡す必要があります。 イメージのビルド時にインストールするのか、それとも実行時にコンテナ内でインストールするのかでも方法が違うのでそれぞれ方法を探ってみました。

ビルド時にインストールする場合

何も考えずビルド時にSSH秘密鍵をマウントしてみたり、環境変数やビルド時変数としてGitHubの認証情報を渡したりすると、イメージ内に認証情報を残してしまうことになります。 ローカル開発だとまあいのではとも思うのですが、出来るだけリスクは軽減したいです。 この辺りのことが意識できてない人は去年のはてなインターンで出題された Docker Quiz を解いてみると良さそう。

ここで紹介したいのは BuildKitBuild Mounts を使う方法です。

--mount=type=secret

--mount=type=secret を使うとビルド時にだけ秘匿情報をマウントし、イメージレイヤには残さないということが出来ます。 これを使って秘密鍵をマウントすることでプライベートリポジトリにアクセスしようというのが今回の方法です。

# syntax=docker/dockerfile:experimental
FROM alpine
RUN apk add --no-cache openssh-client git
# GitHubの公開鍵を取得しておく必要がある
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=secret,id=ssh,dst=/root/.ssh/id_rsa bundle install

bundle install するときに秘密鍵をマウントするようにした Dockerfile を書いておいて、ビルド時にGitHubに登録している公開鍵の対となる秘密鍵を指定します。

$ docker build --secret id=ssh,src=/path/to/private_key .

2点注意があって、

--mount=type=ssh

--mount=type=secretでも目的は達成出来るのですが、パスフレーズを設定していない秘密鍵を扱いたくないという課題が残ります。 これを解決するには --mount=type=ssh を使って ssh-agent 経由でホストの秘密鍵を利用する方法が使えます。

# syntax=docker/dockerfile:experimental
FROM alpine
RUN apk add --no-cache openssh-client git
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh bundle install

先ほどとほとんど同じですが --mount=type=ssh のところが違います。これによってイメージのビルド時に ssh-agent を経由してホストの秘密鍵にアクセス出来ます。もちろんパスフレーズはホストで入力出来るので安心。

$ ssh-add /path/to/private_key
$ docker build --ssh default .

このようにして ssh-add しておいた秘密鍵を利用してプライベートリポジトリにアクセスすることが出来ます。

また、以下のように秘密鍵を指定することも可能です。

$ docker build --ssh default=/path/to/another_private_key .

ここでも注意点があります。何もしていないと uid=0gid=0 でマウントされるのでroot以外のユーザーを使っている場合は意図した動作にならないという点です。 これは以下のようにマウント時に適切なuidとgidを指定することで解決します。

RUN --mount=type=ssh,uid=1000,gui=1000 bundle install

詳しい使い方は リファレンスマニュアル を参照してください。

実行時にインストールする場合

ビルド時にインストール出来ることは確認出来たのですが、普段の開発フローを考えると Gemfile を更新したときに毎回イメージをビルドしなおすのは手間です。 実行時にインストールしなおせるといいのですが、ビルド時に渡した認証情報はどこにも残っていません。ということで実行時に認証情報を渡す方法を探しました。

ちなみに実行時は標準入力にアクセス出来るので1個1個認証情報を入力すればいいという話はありますが、複数のプライベートリポジトリがある場合に毎回入力するのは手間ですよね。

ssh-agent を利用する方法

--mount=type=ssh と同様に ssh-agent を使うのはどうでしょうか。

r7kamura.com

この方法は確立されていて ssh-agent が用意した通信用のソケットをボリュームとしてマウントしつつ、マウントしたパスを SSH_AUTH_SOCK 環境変数に設定してあげるだけです。

ただしこの方法には問題があって macOS 上では動作しません。

https://github.com/docker/for-mac/issues/410 によると /run/host-services/ssh-auth.sock を指定することで回避出来るようなので以下のようにすることでやりたいことは実現できます。

$ docker run -v /run/host-services/ssh-auth.sock:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent bundle install

詳しい仕組みについてはざっくりと読み飛ばしてしまったので理解出来てなくて、詳しい人いたら教えて欲しいです。 macOS 上で SSH_AUTH_SOCK に指定されているソケットが特殊なもの?みたいな雑な理解です。

BUNDLE_GITHUB__COM を使う方法

ssh-agent を利用しても実現出来ることは分かったのですが、これだと環境依存が発生してしまいます。 もう少しうまい方法はないでしょうか。

Bundler ではGitHubの認証情報渡すのに BUNDLE_GITHUB__COM 環境変数を使うことが出来ます。 これを使うのはどうでしょうか。

この環境変数には user:pass 形式の認証情報も渡せますが、Personal Access Token (PAT) を渡す方が管理しやすいでしょう。 プライベートリポジトリにアクセスしたいので repo 権限をもったPATを生成して以下のようにして渡すことで無事にプライベートリポジトリのGemもインストール出来ました。

$ docker run --rm -e BUNDLE_GITHUB__COM=<YOUR PAT> container bundle install

これまではソースとして SSH プロトコルの形式でURLを指定していましたが、今回はGitHubの認証を使うため HTTP(S) プロトコルで指定する必要がある点が注意です。

Slackのサイドバーを隠す

Cmd+Shilft+D でサイドバーが開閉出来るので、All unreads を表示しておくことでRSSリーダーかのように未読だけを好きなタイミングで読むことが出来る。 サイドバーが出ていると未読が残っているチャネルがハイライトされるので気が散ってしまっていたので快適が訪れました。

f:id:Sixeight:20210429154349p:plain

モザイクだらけで何も分からない様子です。

blog.nishimu.land

Discordをミュートにし忘れていることに気付くために

皆さんはちゃんとミュートにしてますか。

DiscordはKrispを使ったノイズキャンセリングが優秀でマイクをいちいちミュートにしていなくても相手に生活音が伝わらずに快適に会話が出来る。 作業しながら同僚とつないでいて、何か思いついたときにはすぐに発音出来るように常にマイクをオンにしているのが常態化している。

しかし、これがに慣れてくるとマイクが音になっていることを忘れてしまうことがある。 そうなるとBGMに聴いていた曲のサビで熱唱したのを聞かれてしまったり、家族と話している雑な会話がブロードキャストされてしまうという悲劇が起きてしまう。

Discordはよく出来ていてメニューバーにアイコンを出してくれて、マイクがオンになっているときはそれと分かるようになっている。 しかし、たくさん出ているメニューの中の1つの見た目が変わったところでノイズにしかならなくてなかなか気づけない。

先日 Bartender を導入したのだけれど、これを使うと不要なアイコンをメニューバーから消すことが出来る。 これで他のアイコンを削ることで気付きやすくなるかと思ったのだけれど、意外と気付かない。 常に存在するものの見た目がちょっと変わったところで認知外になってしまうらしい。

どうすればいいかと考えていたけど最高のソリューションを思いついた。

Bartender ではメニューバーのメニューを特定の条件でのみ表示することが出来る。 条件として最初に保存していて画像と見た目が変わったら表示というのがあるので、これを使ってマイクがオンになっているときだけアイコンを表示するようにする これで、ミュートにしているときは何も表示されていないが、マイクがオンになっているときだけアイコンが現れるので、あ、今は駄目そうとすぐに気づけるようになった。

f:id:Sixeight:20210428232617p:plain

これが普段の様子

f:id:Sixeight:20210428232701p:plain

これがマイクがオンの時の様子

大変快適なのでお試しください。

blog.nishimu.land

元気

さいきん仕事が終わるとぐったりしていることがあって夜に何も出来ないことが多い。 体力が落ちているというのもあるのだけれど、力の配分が下手というのもありそう。

大事なこともそうでないことも全部で頑張ってしまうので疲れるうえにアウトカムにもつながりにくい。 大事じゃないことはうまく手を抜いて、大事なところを頑張って結果を出しつつ元気にやりたい。

今日はぎりぎり夜も活動できました。

そういえば睡眠の質が崩壊しているのも関係ありそう。

Bartender 4 を導入した

f:id:Sixeight:20210425192356p:plain

メニューバーにいろいろ置きたいのですが、いろいろ置いてあると気になって生産性が下がるという矛盾を抱えていました。 常に見たいのは一部だけのはずなので隠したいという気持ちになってきます。 しかし、macOSはメニューバーを柔軟にカスタマイズすることは出来ないので諦めていました。

一応 Bartender というアプリで実現出来るといことは知っていたのですが、どんくらい効果があるのか疑っていました。

最近、ふと思い立ってえいやと導入してみたところめちゃくちゃ快適だったので常用するようになりました。 記事の先頭に貼ったようにメニューバーがめちゃんこりすっきりします。

隠れているアイテムはメニューバーにカーソルをもっていくと即座に表示されるので使いにくくなることもなくて、見た目と使い勝手が両立されていて快適です。 ショートカットキーで出し入れも出来るので、通知系を見たい場合もキーボードだけでささっと確認できます。 また、トリガーが指定出来るので、例えば通知が来たときだと15秒だけメニューを出すとかも出来てかなり柔軟です。

これは個人的な好みですが、アイコンがダサすぎてメニューバーには出したくないけど設定でメニューバーから消せないものも非表示に出来るのが地味に助かっています。

www.macbartender.com