clap - 簡単にツールをインストールするためのツールを作った

    多分車輪の再生産だとは思いますが、簡単にツールをインストールするための CLI ツールを作りました。 tarball や zip をダウンロードして展開して指定したパスにインストールするツールです。 https://github.com/suzuki-shunsuke/clap Go で書かれています。 ツールの名前(clap)には特別な意味や理由はなく、なんとなくです。 CI で何かしらのツールをインストールすることがままあって、そのためのシェルスクリプトを都度書くのが割と面倒なのでツール化しました。 このブログを書いている時点でバージョンは v0.1.0-1 で、最低限の機能しかありませんが、9割型ニーズを満たせるかなと思います。 使い方は以下のようになっています。 $ clap <URL> <インストールするファイルのアーカイブ内での相対パス>:<インストール先> [<インストールするファイルのアーカイブ内での相対パス>:<インストール先>...] 例えば conftest を /usr/local/bin にインストールする場合次のようになります。 CONFTEST_VERSION=0.18.2 clap install https://github.com/instrumenta/conftest/releases/download/v${CONFTEST_VERSION}/conftest_${CONFTEST_VERSION}_Linux_x86_64.tar.gz conftest:/usr/local/bin/conftest chmod a+x /usr/local/bin/conftest パーミッションの付与はやってくれないので必要に応じてやってください。 ファイルの圧縮形式は URL から自動で判別してくれます。 上記の conftest のインストールを今までは次のようなシェルスクリプトを書いていました。 #!/usr/bin/env bash set -eu CONFTEST_VERSION=0.18.2 dirpath=$(mktemp -d) pushd "$dirpath" TARFILE=conftest_${CONFTEST_VERSION}_Linux_x86_64.tar.gz curl -OL https://github.com/instrumenta/conftest/releases/download/v${CONFTEST_VERSION}/${TARFILE} tar xvzf $TARFILE mv conftest /usr/local/bin/conftest chmod a+x /usr/local/bin/conftest popd rm -R "$dirpath" 地味に面倒ですね。これをツール毎に書いて、しかも圧縮形式によって微妙に変えないといけません。

    CircleCI の run の実行時間を DataDog に送る

    小ネタです。 dd-time を使って CircleCI の run を使ったコマンドの実行時間をどう計測したらいいのかちょっと考えました。 以前、コマンドの実行時間を DataDog に送るツール dd-time を作りました。 https://techblog.szksh.cloud/dd-time/ https://github.com/suzuki-shunsuke/dd-time これは基本的に以下のように引数として -- 以降に実行するコマンドを指定します。 $ dd-time -m dd_time.execution_time -t command:docker-build -- docker build . 実行するスクリプトを標準入力で渡したい場合はこうします。 $ curl https://example.com/install.sh | dd-time -m dd_time.execution_time -- sh もちろんシェルスクリプトである必要はなくて例えば Python だったらこうなります。 $ curl https://example.com/setup.py | dd-time -m dd_time.execution_time -- python CircleCI の run では shell オプションで shell を指定できます。 https://circleci.com/docs/2.0/configuration-reference/#run なので command 全体の時間を計測したい場合は、 shell を次のようにします。 - run: name: test dd-time shell: /usr/local/bin/dd-time -m dd_time.

    CircleCI の checkout の注意点

    CircleCI の組み込みの command checkout の注意点について書きます。 なお、ここに書かれている内容は 2020/04/24 時点のものであり、予告なしに checkout の挙動が変わる可能性があります。 また、今回は話を簡略化するため、 checkout 実行時点で .git がない(つまりキャッシュしていない)ものとします。 最初に結論 先に結論を書くと CircleCI ではローカルのデフォルトブランチを参照しないほうが良い($CIRCLE_BRANCH がデフォルトブランチである場合は除く) 履歴が origin と異なり、 $CIRCLE_BRANCH と同様になっているため 代わりに origin のデフォルトブランチを参照したほうが良い git branch -f <デフォルトブランチ> origin/<デフォルトブランチ> を実行してデフォルトブランチの履歴を修正するのもあり checkout がなにをやっているか checkout でなにをやっているかは実際に使ってみて CircleCI の job の詳細画面(?) から確認できます。 サンプル: https://app.circleci.com/pipelines/github/suzuki-shunsuke/test-circleci/73/workflows/5611059c-d6b1-4a34-91b5-45d6f149d408/jobs/96 ここでは checkout の全てについては触れません。一部抜粋します。 elif [ -n "$CIRCLE_BRANCH" ] then git reset --hard "$CIRCLE_SHA1" git checkout -q -B "$CIRCLE_BRANCH" fi git reset --hard などをしています。

    Skaffold で特定のサービスだけ動かすためのツールを作った

    自作の CLI ツール skaffold-generator の紹介です。 プロトタイピングみたいなノリで半日くらいで割と手早く作れました。 名前が長くて適当なのでもっと良い名前ないかなと思ってます。 Skaffold に欲しい機能がないので補完する感じで作ったのですが、「それ〇〇で出来るよ」とかあったら(GitHub issue とか Twitter で)教えていただけると幸いです。 どんなツールか 設定ファイル skaffold-generator.yaml を監視して変更があったら skaffold.yaml を生成するツールです。設定ファイルでサービスの依存関係を定義できたり、コマンドライン引数で指定したサービス及びそれが依存するサービスに関連した設定だけを使って skaffold.yaml を更新します。 このツールは skaffold.yaml を生成するだけなので実際にアプリケーションをビルド・デプロイするには skaffold と組み合わせて使います。 なぜ作ったか 元々ローカルでアプリケーションを動かしながら開発するために Docker Compose を使ってるリポジトリがあるのですが、それを skaffold に移行出来ないか検証しています。 まだ skaffold を触り始めたばかりで理解が浅いのですが、 本番環境は k8s で動いてるからローカルも k8s で動かせるといいかなと思ったり、あとは変更を検知して自動でビルド・デプロイしてくれたりして便利そうかなと思いました。 まぁ結果的に移行しないことになったとしても、 Skaffold と現状の仕組みについて理解が深まればいいかなくらいのつもりです。 検証の過程で、 以下のようなことが Docker Compose だと出来るけど Skaffold だと難しそうだと思いました。 サービスの依存関係を定義すること Skaffold というより k8s の問題かとは思いますが Docker Compose だと依存するものを自動で起動してくれて便利 コマンドライン引数で指定したサービスだけ起動すること Skaffold だと skafffold.yaml で定義したものすべてがビルド・デプロイされるという認識 サービスの数が少なければ全部ビルド・デプロイでもいいですが、 マイクロサービスをモノレポで管理しているような場合、 すべてのマイクロサービスをビルド・デプロイするのは無駄が大きかったりします。

    Terraform ハンズオン with MySQL Provider

    Terraform を勉強するには実際に使ってみるのが一番手っ取り早いですが、 では手頃な題材はあるかと言われると少し難しいです。 公式の Getting Started では AWS が使われていますが、 AWS のアカウントやクレデンシャルが必要ですしお金もかかってしまいます(無料枠はありますが)。 もう少し手軽なものが欲しいところです。 そこで公式の Provider で丁度いいものはないか探したところ、 MySQL Provider が良さそうでした。 MySQL のユーザーや Database を Terraform で管理したいとは自分は思いませんが、 Terraform の入門で遊ぶにはちょうどよいでしょう。 ちなみに公式の Provider のリストはこちらです。 https://github.com/terraform-providers https://www.terraform.io/docs/providers/index.html また、 Terraform に関しては Terraform 入門 も参照してください。 今回の作業用に適当にディレクトリを作成し、そこで作業しましょう。 以降、コマンドの実行結果は一部省略することがあります。 $ mkdir workspace $ cd workspace Terraform のバージョンと tfenv Terraform を複数人で使う場合、 Terraform のバージョンを揃えるのが重要です。 理由の一つとして、 Terraform の State は State を作成した Terraform のバージョンを記録しており、それより古いバージョンの Terraform で terraform plan などを実行すると失敗するようになっていることが挙げられます(この点については後でも触れます)。 そういう意味では、 tfenv によってバージョン管理するのが良いです。

    Terraform 入門

    参考 10分で理解するTerraform | Qiita Terraform入門資料(v0.12.0対応) ~基本知識から設計や運用、知っておくべきtipsまで~ | Qiita AWSでTerraformに入門 | Developers.io Terraform職人入門: 日々の運用で学んだ知見を淡々とまとめる | Qiita 手を動かしたい方は Terraform ハンズオン with MySQL Provider も参考にしてください。 前提 執筆時点 (2020/01/05) で Terraform の最新バージョンは v0.12.18 です Terraform とは Terraform は Infrastructure as Code を実現する汎用的なCLIツールです。 インフラの状態を設定ファイルに定義し、コマンドを実行することで、 実際のインフラの状態と設定ファイルの差分を検知し、設定ファイルに記述されたとおりになるようにインフラを変更(CRUD)します。 Hashicorp という企業がホストしている OSS になります。 Go で書かれています。 https://github.com/hashicorp/terraform Terraform のインストール Terraform は Go 製なので 1 バイナリをダウンロードしてインストールするだけです。 https://www.terraform.io/downloads.html tfenv を使うと管理が楽です。 https://github.com/tfutils/tfenv tfenv は Terraform のバージョン管理ツールです。 pyenv や rbenv の Terraform 版みたいなものです。

    Terraform の State Locking の概要

    Terraform の State Locking という機能の概要について説明します。 ただし、自分もちゃんと理解しているわけではないので、推測も混じります。 基本的には公式ドキュメントに書いてある内容なのでそちらをご参照ください。 State Locking とは terraform plan などのコマンドは State を変更する場合があります。 その処理は atomic ではないため、同時に複数のコマンドが State を書き換えようとすると不整合が生じる可能性があります。 例えば S3 backend の state を state rm で更新する場合を考えます。 これはコマンド内部で 現在の State を取得する (READ) 修正した State を S3 に push する (WRITE) という処理を行っているはずであり、複数のコマンドを実行した場合、READ と WRITE の間に他のコマンドによって WRITE されると、その WRITE による変更が消えてしまいます。 そこで State Locking を使うと各コマンドで State を変更する前に lock を取り、WRITE 後に lock を解除します。 コマンドラインオプション plan, apply, refresh, state rm, state mv, state push には次のようなオプションがあります。

    dd-time - コマンドの実行時間を Datadog に送るツール

    コマンドの実行時間を Datadog に送る dd-time というツールを作りました。 このツールは circle-dd-bench にインスパイアされていますが、 CircleCI 以外でも需要あると思ったり、他にも幾つか改善したい部分があったので自作することにしました。 circle-dd-bench については circle-dd-bench の作者が書いたブログ https://blog.yuyat.jp/post/circle-dd-bench/ も参考にしてください。 dd-time は Go 製なので GitHub Releases からバイナリをダウンロードしてインストールすれば使えます。 使い方はシンプルで実行時間を計測したいコマンドの前に dd-time -- をつけるだけです。 例えば Docker image のビルドの時間を計測したい場合次のような感じになります。 $ dd-time -t command:docker-build -- docker build . Datadog の API key を環境変数 DATADOG_API_KEY として設定する必要があります。 こうすると Datadog の Post timeseries points API を使い、command_execution_time というメトリックス名(変更可能)でコマンドの実行時間が送られます。 メトリックスの名前や host, tags はそれぞれ --metric-name (-m), --host, --tag (-t) で指定できます。 --tag は複数回指定可能で、 key:value というフォーマットで指定します。

    モブレビューやっていきたい

    最近モブレビュー取り入れたいと感じていて、なんで取り入れたいかなどについて書いてみました。 モブレビュー自体まだ 2, 3 回しかやってないので説得力にかけますが、ご容赦ください。 想定 チームは 6 人以下 Pull Request (以下 PR) をマージするには必ず他の誰かが approve しないといけない 目的 チーム内の情報共有 属人化の解消 退職や異動などによる情報の喪失(誰も分からない状態)を防ぐ チーム外の人とのコミュニケーションにも活用できる レビュー待ちの短縮 レビューの品質の改善 仕事を評価してもらうことで承認欲求を満たす オンボーディングの改善 レビューを通じて必要な知識を吸収してもらう オンボーディングに限ったことではないが、オンボーディングにも有効ではないか 最後までやりきる 箇条書した内容を補足します。 情報共有 属人化の解消は結構重要だと自分は思っていて、特定の人じゃないと出来ないこと、わからないことというのは ボトルネックや技術的負債だったり、障害対応時に致命的になりかねません(深夜に障害が起こってAさんに聞かないとわからないのに、Aさんと連絡が取れないとか最悪)。 チーム全員とはいかなくても 3 人ぐらいは出来る・分かってる必要があるかなと思います。 まぁ、当初は 3 人ぐらい分かってても、時間が経って異動やら退職やらで気づいたら分かっている人いなくなってたというのは ありえなくないので、そういったリスクをどうやって防ぐかというのは考える必要がありますが、今回の話とは外れるので割愛します。 また、チーム外の人とのコミュニケーションにも活用できると思っていて、 例えばランチや飲み会でチーム外の人とのコミュニケーションを取る際に自分のチームの他の人が対応した件とかが話題に上がったときに ちゃんと情報共有できてないと、自分は担当外なので分かりませんとなってしまうでしょう。 知っていればむしろ自分から話題にできるかもしれません。 そこから発展して更に新しいタスクの話もできるかもしれません。 レビューの改善 せっかくいい仕事をしても中々レビューしてもらえないとなると不満がたまります。 モブレビューを実施することでレビューを促進し、レビュー待ちの時間を短くできることを期待します。 レビューしたくても良くわからなくてレビューできないというパターンもあると思うので、 わからない部分をモブレビューで解消されてレビューが進むと良いですね。 また、ちゃんと複数人でレビューすることで目先の問題を解決するだけの本質的でない問題解決を防ぐことが出来ることもあると思います。 「いや、それそもそもPRの前提がおかしくない?前提となっている仕様を見直すべきなのでは」 みたいなこともあるかもしれません。 仕事を評価してもらうことで承認欲求を満たす いい仕事したら他の人にも知ってもらいたいというのは自然なことでしょう。 いい仕事を褒めるのは良いチーム・環境であり働きやすさというところにつながるのではないでしょうか。 ちなみに現職だと Slack で他のチームにも共有して emoji で褒め称えるというのが結構やられていて 気持ちのいい環境だなと思っています。

    go-timeout - command の timeout

    作ったのは 2ヶ月くらい前の話ですが、 Go の command の timeout を実装するためのライブラリを作ったので紹介します。 https://github.com/suzuki-shunsuke/go-timeout 基本的には https://github.com/Songmu/timeout をオススメしますが、これだと上手くいかないパターンがあったので自作しました。 Go の command の timeout に関しては https://junkyard.song.mu/slides/gocon2019-spring/#24 がとても参考になります。 上記のスライドでは 標準ライブラリの exec.CommandContext でも停止できるが、 SIGKILL で強制的に停止することになる 子プロセスが停止しない 公式見解 では、SIGKILL 以外は標準ライブラリではサポートしない。サードパーティでやればよい Songmu/timeout 使えば SIGKILL 以外でより安全に停止できる ということが丁寧に説明されています。 自分は cmdx という task runner を開発していてその中で task の実行時に timeout を設定出来るようにしました。 当初 Songmu/timeout を使って実装したのですが、問題があることに気づきました。 それは、 command の中で fzf を使うと、上手く動かないというものでした。 https://github.com/suzuki-shunsuke/cmdx/issues/52 https://twitter.com/szkdash/status/1165529415238815745 正直この辺の挙動はちゃんと理解できていないのですが、 調べてみると Songmu/timeout だと syscall.SysProcAttr の Setpgid を true に設定していて、そうすると fzf が上手く動かないようでした。