esm アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

Rails / OSS パッチ会オンライン 2022年1月のお知らせ

2022年1月の Rails / OSS パッチ会を 1月19日(水)に Discord でオンライン開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS について、upstream にパッチを送る会です。

会には Ruby と Rails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。

Discord の Rails/OSS パッチ会サーバーへの招待 URL は以下です👇

discord.gg

パッチ会では、先月リリースされた Rails 7.0 や Ruby 3.1 に関する話題などが旬のネタとしてありそうです。

これからパッチ会に参加してみようという方も、ぜひどうぞ。Discord でお会いしましょう。


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

CI fail は突然に ~CircleCI の cimg が compose v2 を使うようになって~

メリークリスマス! yucao24hours です。

こちらがおそらく 2021 年最後のアジャイル開発ブログとなります(予定)。今年も一年、私たちのブログに目を通していただきありがとうございました。

さて、今回は自分が関わっている数プロジェクトで発生した、突然の CI のふるまいの変化とその原因について調べた結果を書いてみます。

ことの発端

去る 12 月 8 日の夕方のことです。 GitHub にてとある Pull Request をマージしたところ、main ブランチにて CI が fail したことに気づきました。 CircleCI を使っているプロジェクトでしたので CircleCI の実行画面を見に行ったところ、以下のようなエラーが出ていました。

/bin/bash: line 5: docker-compose: command not found

Exited with code exit status 127
CircleCI received exit code 127

ちなみに、対応する .circleci/config.yml の記述は以下のとおりです。

- run:
    name: Create services
    command: |
      if [ -f /tmp/cache/images.tar ]; then
        docker load -i /tmp/cache/images.tar
      fi

      docker images
      docker-compose up --build --no-start --quiet-pull rails

つまり、最後の行の docker-compose コマンドが見つからないと言われているのです。

つい昨日まではなにも異常なく実行できていたし、CircleCI の設定も変更していないのに... こんなことってある!?

何が起きたか

状況から察するに、私たちの repository とは直接関係ないどこかでなにかの変更が入ったとみるのが妥当でしょう。

cimg のベースイメージの repository に、まさに今起きていることに関係していそうな issue が。

https://github.com/CircleCI-Public/cimg-base/issues/133

Starting with this month's base image release, Docker Compose is on v2 instead of v1. So instead of running docker-compose you'd run docker compose.

なるほど。今回起きたことに対する答えが、ほぼそのまま書いてありました。

が、せっかくなのでここで一旦立ち止まって、もう少し詳しく各要素のことを調べてみましょう。

cimg とは

まず、今見てきた cimg とはなんなのでしょうか。

cimg は、CircleCI があらかじめ用意している CI/CD 向けの Docker image です。

もともと CircleCI が開発・管理していた、 circleci/ というプレフィックスのついた公式 image を置き換えるものとしてリリースされています。

circleci/ からはじまるこのレガシーな CircleCI image は、2021 年 12 月 31 日で廃止となります。もうすぐですね。もしご自分の .circleci/config.yml に circleci/ruby などと書かれている場合は、移行が必要ですのでお忘れなく!

circleci.com

Git やその他ライブラリのインストールに加え、アプリケーションを動かすのに必要な動作環境をセットアップした状態の image がさまざまな言語向けに用意してあります。

そのため利用者は各 image を .circleci/config.yml に記載するだけで、すぐに CI/CD ワークフローを構築することができるというわけです。

私たちのプロジェクトでは cimg/base を使い、その Docker コンテナ上で Rails アプリケーション用の Docker コンテナを起動するようにしています。

実際に使いはじめてしばらく経ちますが、このおかげで config.yml の記述量が大幅に減りスッキリ見やすくなりましたし、CI に関するメンテナンス負荷がとても軽くなったと感じています。

circleci.com

なお、今回 issue を見に行った cimg/base は、その名の通り各種言語向け image のベースとなる image です。

circleci.com

先ほど見た issue のコメントを再掲しますが、

Starting with this month's base image release, Docker Compose is on v2 instead of v1. So instead of running docker-compose you'd run docker compose.

とのことで、このベースイメージ(のうち当時の stable タグがついたイメージ)で使われる Docker Compose のバージョンが v1 から v2 になったとあります。 1

では、Docker Compose v2 でどのような変更がなされてこのエラーが出たのでしょうか。

docker-compose が docker compose に

Docker Compose v2 についてのすべてを紹介するのは今回の記事の主目的ではないので割愛しますが、今回修正が必要な点は、以下の内容に関連していそうです。

docs.docker.com

You can test the Compose V2 by simply replacing the dash (-) with a space, and by running docker compose, instead of docker-compose.

即ち、 .circleci/config.yml に記載されている docker-compose は、 docker compose に変える必要があるということがわかりました。

コンテナ名の表記が変わった

さて、以上で対応完了!と思って再度 CI を run させたところ、今度は

docker: Error response from daemon: No such container: myapp_rails_1.

というエラーが出ました。

どうやらこれは、v2 で以下の変更が入ったことによるもののようです。

github.com

もともと docker-compose が自動生成していた project_service_number といったコンテナ名は hostname の表記規則に違反しているものであったため、v2 に移行する機会にこの変更が追加されることになったようです。

よって、 .circleci/config.yml に

- run:
    name: Copy rails dependencies
    command: |
      mkdir -p /tmp/cache
      docker cp myapp_rails_1:/usr/local/bundle/. /tmp/cache/bundle

のようにアンダースコア区切り(旧表記)のコンテナ名を記載している場合、 myapp-rails-1 のようにハイフン区切りに修正する必要があったのでした。

まとめ

今回は CircleCI の cimg がきっかけとなって、Docker Compose v2 の変更について少し触れることができました。

どうしてこういう事が起きるようになったのか?を確認するために、issue や Pull Request 、コード等を探索して影響箇所を突き詰めるのはとても楽しいですね!

この調子で来年も、楽しいエンジニアライフを過ごせたらいいな~と思います。

それではみなさまも、よいお年をお迎えください :D


  1. 本当は https://circleci.com/developer/images/image/cimg/base#image-tags を見れば、どのタグのイメージにバージョンいくつの Docker Compose が入っているかを調べられるはずなのですが、今見るとちょっとおかしな文字列が入っているようにみえて、ドキュメントの自動更新がうまくいっていないのかな… という状態です。

Railsアプリケーションでフロントエンドのパフォーマンス改善:初歩編

この記事は ESM Advent Calendar 2021 - Adventar の21日目の記事です。

こんにちは、swamp09です。

とあるRailsアプリケーション開発プロジェクトで、フロントエンドのパフォーマンスを計測するのに Lighthouse を使いました。パフォーマンスの項目を見てみると「レンダリングを妨げるリソースの除外」が指摘されており中身をみるとapplication.jsで多くの無駄が発生しているようです。Railsアプリケーションでは application.js が肥大化してしまうケースがたまに見られますね。 Eliminate render-blocking resources を読むと、まずはカバレッジを見て必要なリソースだけを読み込むこと、次いでスクリプトがレンダリングブロックしないようにするとのことです。ある画面ではGoogle ChromeのDevToolsのカバレッジを見るとapplication.jsは91%使用していないという結果になっていました、なんと…。未使用のコードが多すぎるという問題は画面ごとに必要なJSだけ読み込むように地道にリファクタリングしていくしかないですね…。

レンダリングブロックを除く

スクリプトがレンダリングブロックしないようにするには、application.jsを読み込みをasyncdeferにします。 これらがないとJavaScriptがHTMLパーサーをブロックしてしまうのでパフォーマンスに悪影響があります。asyncdeferの違いは、 ブラウザの仕組み: 最新ウェブブラウザの内部構造 の スクリプトとスタイル シートの処理順序 によると、asyncがHTMLのパースとは別スレッドで処理され、deferはHTMLのパースが終わってから順番に処理されるということのようです。application.jsではライブラリの読み込みなどを行っており、読み込む順序を意識する必要があったのでdeferを使うことにして、application.jsの読み込みを javascript_include_tag 'application', defer: true のように変更しました。

ちなみにパーサーブロックとレンダリングブロックは微妙に違うようなのですが、MDNではパーサーブロックと書いてあり Eliminate render-blocking resources ではレンダリングブロックと書いてあります。あんまり気にしなくて良いのかな…。

インラインスクリプトの対応が必要だった

さておき、よしこれでパーサー|レンダリング ブロックしなくなって良くなったな!!と思いきや問題が起き、application.jsで読み込んでいるライブラリに依存しているコードがインラインスクリプトにありそれらが動作しなくなってしまいました。じゃあインラインじゃなくして全部JSファイルにしてdeferで読み込めばいいか!!!と思ったのですがそんなことはなく、レンダリングを妨げる JavaScript を削除する によると、小さいコードならインラインが最適なケースがありなんでもかんでもJSファイルに切り出すのは良くないようです。

インラインスクリプトのままでJSファイルにあるライブラリ読み込みの遅延を待つために、DOMContentLoadedでライブラリの読み込みを待ったあとで処理を開始するようにします。defer によると「defer 属性の付いたスクリプトは、スクリプトが読み込まれて評価が完了するまで、 DOMContentLoaded イベントの発生が抑制されます。」とのことなのでdeferでライブラリを読み込み DOMContentLoadedイベントを待てば安心ですね。

おまけ

余談なのですが、最近リリースされたRails 7.0ではデフォルトでimportmap を使用しています。importmapはES Modulesを読み込むもので、ES moduleの読み込みはクラシックスクリプトとは別でモジュールスクリプトとなっており、defer は「defer 属性はモジュールスクリプトには効果がありません。」とのことなのでasyncしか使えないようです。deferとの違いを意識していないとimportmapを使うとき処理順序が起因のエラーが起きるのかもしれません。

Rails / OSS パッチ会オンライン 2021年12月のお知らせ

【重要】Rails/OSS パッチ会で運用していた Idobata ルームは閉鎖されました。本記事で言及している Discord へ引越しをお願いします。

2021年12月の Rails / OSS パッチ会を 12月21日(火)に Discord でのオンライン開催をします。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS について、upstream にパッチを送る会です。

会には Ruby と Rails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。

Discord の Rails/OSS パッチ会サーバーへの招待 URL は以下です👇

discord.gg

パッチ会では、先日リリースされた Rails 7.0 や、クリスマスにリリース予定されている Ruby 3.1 に関する話題などあるかもしれません。

これからパッチ会に参加してみようという方や、24 Pull Requests の活動機会にできそうな方も、ぜひどうぞ。Discord でお会いしましょう。


永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

red-datasets の使い方と利用できるデータセットを調べてみた

この記事は、ESM Advent Calendar 2021 10日目の記事です。

adventar.org

はじめに

こんにちは、@wai_doi です。

今年開催された RubyKaigi Takeout 2021 で、@kou さんの 「Red Arrow - Ruby and Apache Arrow」 発表がありました。

rubykaigi.org

こちらの発表の中で、@kouさんが開発された red-data-tools/red-datasets という Gem が紹介されていました。

github.com

簡単に様々なジャンルのデータセットを Ruby から利用できる Gem です。発表中のデモでは、日本の郵便番号のデータセットをRubyで簡単に利用できており、すごく便利な Gem だなと感じました。そこで、郵便番号データの他にどのようなデータセットが red-datasets から利用できるのか気になったため、調べてみることにしました。

red-datasets の使い方

まずどのように利用するか確認します。

Gem をインストールします。このブログ執筆時点では v0.14 が最新です。

gem install red-datasets

次に実際に使ってみます。各データセットのクラスが Dataset クラスを継承しているため、同じ参照方法となっています。

例として、郵便番号データの Datasets::PostalCodeJapan を使ってみます。

クラスが enumerable を include しており、each メソッドを呼び出すと、インターネット上のオープンデータをzipなどでダウンロードする処理が行われます。

first を呼んで内部で each を呼ぶこともできます。

require "datasets"

dataset = Datasets::PostalCodeJapan.new

dataset.first # ここでダウンロード処理が入る

#=>
<struct Datasets::PostalCodeJapan::Record
 organization_code="01101",
 old_postal_code="060",
 postal_code="0600000",
 prefecture_reading="ホッカイドウ",
 city_reading="サッポロシチュウオウク",
 address_reading="イカニケイサイガナイバアイ",
 prefecture="北海道",
 city="札幌市中央区",
 address="以下に掲載がない場合",
 have_multiple_postal_codes=false,
 have_address_number_per_koaza=false,
 have_chome=false,
 postal_code_is_shared=false,
 changed=false,
 change_reason=nil>

どのデータセットのクラスも同じように利用できます。ただし、new メソッドに引数を必要とするものもあります。

ダウンロード先について

ダウンロード処理が走ると、ローカルにデータセットがダウンロードされます。例えば MacOS の場合、~/Library/Caches/red-datasets/ 以下に保存されます。

Dataset.clear_cache! を実行すると、ローカルにダウンロードしたファイルを消すことができます。

https://github.com/red-data-tools/red-datasets/blob/0.1.4/lib/datasets/dataset.rb

データセットの種類

red-datasets で利用できるデータセットは、機械学習に用いるデータセットとそれ以外に大まかに分けることができることがわかりました。

Datasetクラスを継承しているクラスを分類して列挙してみました。

機械学習で用いるデータセット

  • Datasets::Adult
  • Datasets::CIFAR
  • Datasets::Communities
  • Datasets::FashionMNIST
  • Datasets::Hepatities
  • Datasets::Iris
  • Datasets::LIBSVM
  • Datasets::MNIST
  • Datasets::Mushroom
  • Datasets::Penguins
  • Datasets::Rdatasets
  • Datasets::Seaborn
  • Datasets::Wine

それ以外のデータセット

  • Datasets::CLDRPlurals
  • Datasets::EStatJapan::StatsData
  • Datasets::PennTreebank
  • Datasets::PostalCodeJapan
  • Datasets::SudachiSynonymDictionary
  • Datasets::Wikipedia

この中から特に気になった 5 つのデータセットを紹介します。

Datasets::CLDRPlurals

英語や日本語などの言語ごとの、数の表し方のルール集のようなものです。 例えば英語だと、複数系になると末尾に s が付くことや、序数は 1st、2nd、3rd、4th..と表すことがルールとして書かれています。

unicode-org.github.io

Datasets::EStatJapan::StatsData

e-Stat という日本の統計データのサイトからデータを取ってきています。都市の人口など取得することができます。

www.e-stat.go.jp

内部では e-Stat の API を叩いています。 new に引数を渡す必要があるため、ドキュメント見るのがよいです。

https://www.rubydoc.info/gems/red-datasets/Datasets/EStatJapan/StatsData

Datasets::PostalCodeJapan

日本郵便が公開している、日本の郵便番号データです。

www.post.japanpost.jp

過去に仕事でこのデータをダウンロードして使ったことがあったため、意外と利用されるデータセットなのかなと思いました。

Datasets::SudachiSynonymDictionary

Sudachi という日本語形態素解析器で使われている同義語辞書です。自然言語処理で使えそうなデータだなと思いました。

github.com

Datasets::Wikipedia

言語を指定して、その言語のウィキペディアページをダンプすることができます。 ただしダウンロード処理にすごく時間がかかるため自分は途中で諦めました...。

dumps.wikimedia.org

まとめ

red-datasets の使い方と利用できるデータセットを調べてみました。 自分の知らなかったデータセットがいろいろあるため興味深かったです。どこかで利用できる機会があれば使ってみたいなと思いました。


最後に、株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

自作キーボードの魅力と PRK Firmware

こんにちは、@kasumi8pon です。

この記事は、PRK Firmware Advent Calendar 2021ESM Advent Calendar 2021 9日目の記事です。

わたしが感じている自作キーボードの魅力

わたしは昨年の 9 月に初めて自作キーボードの組み立てをして、今メインでつかっているこちらのキーボードはもう 1 年以上使っています。

f:id:kasumi8pon:20211207141618j:plain
my keyboard
そんなわたしが感じている自作キーボードの魅力をお伝えします。(初級者のわたしがまだ味わっていない魅力は他にもたくさんありそうです。光らせるとか、1 から自分で設計できるとか……)

自分に合う形が選べる

自作キーボードの形はとても種類が豊富です。市販のキーボードと同じような形もありますし、わたしがそれまで見たことがないような形のものもありました。例えば、キーが格子型に配置されているものや、キー数が少ないものなど、たくさんの種類から自分の好きな形が選べることは大きな魅力です。写真は ErgoDash mini というキーボードです。数字の段のキーがなくてコンパクトなので手を大きく移動させなくてもキーが打ちやすいところや、親指で押せるキーが多いところが気に入っています。また、分割型ということで自然な姿勢でキーボードを使えるので、肩が凝りにくい気がします。

好きなキーキャップを選んでつけられる

見た目は大事です。メインは astrolokeys というキーキャップをつけています。とても可愛くて気分が上がります。 左上につけているのは Zen Pond III というキーキャップです。とても美しいです。

押しごこちを追求できる

キーを押したときの感触も自分好みにすることができます。 初めはあまり興味がなかったのに、いざ自分でキーボードを組み立てよう!と思い立つと「せっかくなので」と押しごこちもこだわりたくなってしまいました。写真のキーボードには Input Club Hako Violet というキースイッチを使っています。 比較的な軽めなキースイッチですが、キーを押したと判定される反応点の手前にある触感のピークはしっかりしていて「押した感」もあるところが気に入っています。

自分でキーマップを設定できる

自作キーボードはキーマップを自分で書き込むので好きなように設定ができます。よく使うキーを押しやすいところに配置したり、タップ時とホールド時で別の入力を設定したりするなど、無限に調整ができます。

ここまで語ってきましたが、実はキーマップの利点について、わたしはあまり活用できていませんでした。 最初に自分好みに設定したつもりでも、使っていくうちにちょっと違うな、調整したいなと感じることが何度かありました。ここでキーマップを育てていけるのも良いところなのに、実際にはあまり変更をしていません。 なぜなら、すこし手間がかかるためです。 今メインで使っているキーボードは QMK Firmware というファームウェアで動かしており、ビルドにいくつかの手順と時間が必要です。大したことはない手順ですが、現在のキーマップでも問題なく利用できることと、わたし自信の面倒くさがりという性質からどうも後回しにしてしまい、キーマップをいじることがあまりなくなってしまいました。 そして、すでに組み立てたキーボードは気に入っているけれど、新しい自作キーボードを組み立てたり、もっとカスタマイズしていこうという気持ちはしぼんでしまっていました。

PRK Firmware との出会い

それからしばらく時が経ち、今年の 9 月 RubyKaigi Takeout 2021 での hasumikin さんの PRK Firmware: Keyboard is Essentially Ruby トークを聞きました。Ruby でキーマップを書けるファームウェア PRK Firmware についての話です。 トーク内でいくつかのデモが行われてどれもすごく面白かった中で、わたしが一番感動したのは「PRK Firmware を使うと、コンパイルする必要がない」というところです。 すごい!!! PRK Firmware を使うとキーボード内の keymap.rb というファイルを直接編集することでキーマップを設定できて、すぐにその変更が反映されるのです。キーマップを変更して使ってみて、もし思っていたのと違ったらすぐに微調整して再度試すということがとても手軽にできるんですね。 これがわたしの中で小さくなってきていた自作キーボードの火を再び起こしてくれました。ぜひ PRK Firmware を使って、自分のキーボードをもっとカスタマイズしていきたい!と。

ということで、トーク内のデモでも使われていた meishi2 というキーが 4 つの小さなキーボードを PRK Firmware を使って動かしてみました。meishi2 は元々 QMK Firmware で動いていたため、Pro Micro を付け替えて、ダウンロードしてきたバイナリをドラック&ドロップして、keymap.rb という Ruby のファイルを配置するだけで動きました。自作キーボードが初めての方でも、かなり簡単に入門できると思います! (実はそれだけのところでずいぶん詰まって、ruby-jp の #keyboard チャンネルでみなさまに助けていただきました。なんと、Pro Micro をつける向きを間違えていたという凡ミス……。画像の通り付ければ間違いないです!)

ふつうの文字を割り当てることもできますが、Ruby のコードを書けるので、試しに押すとランダムなフルーツ(など)の絵文字が出てくるキーをつくってみました。 🍒 🍇 🍓 🍒 🍍 🥑 🍋 🍋 🍐 🥝 🥒 🥔 🍇 🥬 🍉 🍋 🍍 🍑 🥜 🍋 🥜 🍎 押すのが楽しいです。キーボードの中に cherries とか grapes の文字列を持っておいて、ランダムに選んでコロンと一緒に出力しているだけです。(わたしの利用しているエディタやサービスは大体絵文字に変換してくれる。)このキーにフルーツの絵柄のキーキャップをつけたら面白そう、などと想像がふくらみます。このキーはちょっとした思いつきでしたが、何かアイデアが思い浮かんだらいつものようにコードを書くことで気軽にメンテナンスできるので、これからもいろんなカスタマイズをしていこうと思います。

最後に、『達人プログラマー 職人から名匠への道』からの引用です。

道具を手に入れた後は、その学習と適合段階が始まります。それぞれの道具 には独自の個性やくせがあり、道具ごとに固有の取り扱いが必要となります。 また、それぞれの道具を独自の方法で研ぎ上げ、維持していく必要もあります。

道具は手に入れて終わりではなく、研ぎ上げて自分にあわせていく過程が必要です。普段 Ruby を書いているわたしにとって、 PRK Firmware で動くキーボードはとても研ぎ上げるのが楽しい道具になりそうです。

まとめ

  • 自作キーボードは楽しい!

  • PRK Firmware ならそんな楽しい自作キーボードをもっと気軽に始められそう!

  • keymap.rb をメンテナンスしながら道具を磨いて、効率的に・楽しく作業をしよう!

集中する技術

こんにちは。@color_box です。

この記事は、ESM Advent Calender 2021 の8日目の記事です。

みなさん集中できてますか?

ついついTwitterとか見てませんか? 私は見ちゃいます。

この記事では私が集中する時に気が散るのを防ぐためにやっていることを紹介します。

/etc/hostsを書き換えてtwitterなどへのアクセスを遮断する

手始めに/etc/hostsを書き換えましょう。 私は下記のように書き換えて運用しています。

0.0.0.0 www.youtube.com
0.0.0.0 abs.twimg.com
0.0.0.0 twitter.com
0.0.0.0 tweetdeck.twitter.com
0.0.0.0 www.tumblr.com
0.0.0.0 www.facebook.com

StayFocusdを使う

chrome.google.com

Chromeユーザー限定ですが、こちらの拡張機能を使用すると、特定サイトのアクセスを1日10分などに制限できます。

UnDistractedを使う

chrome.google.com

こちらもChromeユーザー限定の拡張機能ですが、使用することで特定サイトのアクセスを遮断できます。

ツイートしたいときは専用ソフトを使う

ツイートはしたいけど、Twitterは見たくないって時ありますよね?私はあります。

そういうときはツイートに特化したアプリを使いましょう。 ツイートしかできないようなアプリであれば完璧です。 私はそんなアプリを作ってローカルで運用しています。

github.com


今回、私が集中したい時にやっていることを紹介しました。

今回紹介した制限は、その気になれば自分ではずせるものばかりで、完全に防止できるわけではありません。 しかし、こういった制限があることで、脇道にそれづらくなります、それづらくなると本来やりたい作業に集中しやすくなる、という寸法です。

この記事が集中したいどなたかのお役に立てば幸いです。