沖永凌のブログ

株式会社ARTISAN, 現場Hub, SaaS開発, スタートアップ, CTO

DockerfileのRubyのバージョンを上げた時に、bundle installが失敗する問題の解決策

前提

Railsアプリケーション(7.1.0)を動かすためのコンテナで遭遇したバグ。

Dockerfileに記載したRubyのバージョンのみを3.2.2から3.3.0に変更した時に発生。

事象

コンテナを起動しようとすると、以下のエラーを吐き出して、コンテナが終了する。

Ignoring psych-5.1.2 because its extensions are not built. Try: gem pristine psych --version 5.1.2
Ignoring psych-5.1.1.1 because its extensions are not built. Try: gem pristine psych --version 5.1.1.1
Ignoring psych-5.1.1 because its extensions are not built. Try: gem pristine psych --version 5.1.1
Ignoring stringio-3.1.0 because its extensions are not built. Try: gem pristine stringio --version 3.1.0
Ignoring stringio-3.0.9 because its extensions are not built. Try: gem pristine stringio --version 3.0.9
Ignoring stringio-3.0.8 because its extensions are not built. Try: gem pristine stringio --version 3.0.8
<internal:/usr/local/lib/ruby/3.3.0/rubygems/core_ext/kernel_require.rb>:127:in `require': libruby.so.3.2: cannot open shared object file: No such file or directory - /usr/local/bundle/gems/psych-5.1.2/lib/psych.so (LoadError)

コンテナ外から

docker compose run app bundle install

を実行しても、同じエラーが発生。

原因

Gemfile.lockに書かれている&installされているbudlerやgemのバージョンは古いままだが、Rubyのバージョンだけが上がっており競合が起きた。

解消方法

一旦競合の起きているgemをuninstallし、再度bundle installをすると解決した。

1.Gemfile.lockを削除

2.コンテナ外から競合するgemをuninstall(上記のエラー文を参照してgemを特定)

docker compose run app gem uninstall psych
docker compose run app gem uninstall stringio

3.コンテナ外からbundle installを実行

docker compose run app bundle install

何のために働くのか

私が働く理由

私は、日本が天国だと思っている。

何ヶ国か海外に旅行してきた結果、日本だけはずっと住み続けたいと思えた。

衣食住が当たり前に満たされていて、その上様々な娯楽を楽しめる。

これは、多くの人が各々で生産・供給してくれているから成立する。

全員が、巨大な分業・協同社会の中に生かされている。

この素晴らしい社会を、子供やそれより下の世代にも維持し続けたいと考えている。

そのために解決しなければいけない社会問題がある。

その一つが、生産年齢人口の減少による生産量の減少である。

解決しなければ、今当たり前に消費できているものが当たり前でなくなっていく。

私はこの社会問題をソフトウェアで解決していきたい。

SaaSで提供することで、(個別開発に比べれば)少ない開発コストで、多くの会社の生産効率を上げられると考えている。

人口が減っても今の社会を維持していきたい。

私が株式会社ARTISANでやること

上記の社会問題のうち、設備工事・メンテナンス業界の労働人口減少について取り組む。

労働人口が減ることを放置していれば、修繕されないままの設備が多発するようになる。

そうならないように現場Hubを開発・サービスし、コア業務以外の時間を減らすことで、設備工事・メンテナンス会社の生産性を向上する。

株式会社ARTISANのCTOとしてやること

使命

上記課題を解決するためのソフトウェア企業を作る

説明責任

時期によって変わるとは思うので、現時点の認識を記載する

  • 上記課題を解決するソフトウェアについての持続可能なアーキテクチャ
    • 保守性
    • セキュリティ
    • 最適な設計・仕様
    • 品質保証
  • アウトカムが早く出る、最適な開発組織の模索・編成
  • 開発組織の行動指針の決定、それを実行する組織作り
  • 開発者の採用計画と実施

※株式会社ARTISANの創業の経緯についてはこちらに記載しております。 もし興味を持っていただけたら、こちらも読んで頂けると幸いです。 okjnag.hateblo.jp

Renovateで言語・パッケージのバージョンを最新に保つ

Renovateとは

GitHub Apps - Renovate · GitHub

Repository内のパッケージマネージャのファイルを検査し、記載したパッケージのバージョンが新しくなる度にPRを作成するアプリケーションでです。

ほとんどの言語に対応しています。

得られる恩恵

設定ファイルでPR作成頻度やPRのまとまりを定義でき、アップデートを定型業務化できます。

また定期的にアップデートすることで、

  • アップデートのコストが下がる
  • 時々、発生していたbugが解消される

という恩恵が受けられます。

設定ファイル例

React×Typescriptのプロジェクトの場合

設定方針

  • 毎週金曜日朝にPR作成
  • マイナー・パッチバージョンは1つにまとめてPR作成
  • Node, Typescriptは別途PR作成
{
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
  "extends": ["config:base"],
  "timezone": "Asia/Tokyo",
  "automerge": false,
  "prHourlyLimit": 0,
  "schedule": ["after 8am on friday", "before 10am on friday"],
  "dependencyDashboard": true,
  "packageRules": [
    {
      "groupName": "Minor and Patch Dependencies",
      "matchUpdateTypes": ["minor", "patch"]
    },
    {
      "groupName": "Node Version",
      "matchUpdateTypes": ["minor", "patch"],
      "matchPackageNames": ["node", "node-version"]
    },
    {
      "groupName": "Typescript Version",
      "matchUpdateTypes": ["minor", "patch"],
      "matchPackageNames": ["typescript"]
    }
  ]
}

この設定で毎週金曜日午前に、

  • メジャーバージョンの更新(破壊的変更あり)は、パッケージごとにPR作成
  • マイナー/パッチバージョンの更新は、Node, Typescript, その他 それぞれ1つずつPR作成

が行われます。

是非お試しください。

カレンダーバージョニングのためのGitHubアクションを作った

背景

もともとは、プロダクトのAPIサーバー・フロントエンドのリポジトリそれぞれで、セマンティックバージョンを利用していた。

しばらく運用していくなかで、

  • デプロイの頻度が高まってきたことで、上げる数字の判断が面倒になってきた(メジャー?マイナー?パッチ?)
  • 少数の開発メンバーしか触らないので、そもそも後方互換性があるかどうかを示す必要がないことに気づく

という理由で、カレンダーバージョニングを利用するようになった。

現在日付とbuild回数でバージョン番号が自動で決まるため、運用してみると便利なバージョニング方法だとわかる。

せっかくなのでみんなが使えるようGitHubのカスタムアクションを作ることにした。

GitHubのカスタムアクション

github.com

セマンティックバージョニングと違い、カレンダーバージョニングには画一的なスキーマはなく、 プロダクトのデプロイ頻度に併せて自由に定義する。 作成したカスタムアクションでも、スキーマを定義できるようにした。

例えば、1日に数回デプロイすることがある場合は、

YYYY.0M.0D.MICRO

年に数回のデプロイであれば、

YYYY.MICRO

と定義する。

特にセマンティックバージョニングを使う理由がなければ、是非カレンダーバージョニングを始めよう。

なぜか時々Macでファイルを開けないことがあった

MacBookを使っていると、なぜか時々ファイルを開けない機会に遭遇していた。

Webアプリケーションでファイルを生成する機能を実装しており、その機能の検証時によく発生した。

デバッグに結構な時間を費やしてしまったので、わざわざ記事にしてみる。

 

結論から書くと、濁点・半濁点が含まれるファイルにおいてのみ発生することがわかった。昔からある有名な問題らしく、macOSのみ文字の正規化方法が異なることによって引き起こされるものだ。

詳しくはNFD・NFCのワードでググると出てくる。

濁点・半濁点を含む文字について1つの文字で扱うか2つの文字で扱うかが、OSによって異なっているのだ。

 

以下が原因特定までの道のりである。

1. ファイルの生成プログラムには問題ないことを確認

2. 生成時に利用しているライブラリには問題ないことを確認

3. 特定のファイルにのみ発生することを確認

4. ファイルの中身が関係ないことを確認

5. 特定のファイル名にのみ発生することを確認

6. 濁点・半濁点がファイル名に含まれている時にのみ発生することを確認

 

知っているか否かでデバッグ速度が大きく変わってしまう、典型的な問題だと思う。

NFDという概念を知らないことにより、調べるべきキーワードが思いつかない負のループに陥っていた。

なので、この記事のタイトルを「なぜか時々Macでファイルを開けないことがあった」という、NFDを知らない人が検索した時に引っかかりそうなものに設定した。

studioで公開しているHPの独自ドメインを変更する

地味にハマったので記録しておく。

達成したいこと

  1. studioで公開しているHPの独自ドメインを変更したい
  2. ドメインのHPの検索順位を維持したい

背景

  • コーポレートサイトをstudioというホスティングサービスで公開している。
  • 会社名を検索すると一番上に出てくるので、ドメイン変更後、ページランクをまた一から育てるのは苦しい
  • studioのサポートに連絡したところ、提示してくれた方法では2が達成できなかったので色々調べる必要があった。
  • ドメイン・新ドメインの両方とも、AWSのRoute53で管理している。

やる必要がある作業まとめ

注意点

  1. ドメインの接続が解除されてから、新ドメインの接続が完了するまでダウンタイムが発生する。 サポートの方は、予め新ドメインでAレコードにIPアドレスを設定していれば問題ないという話だったが、Aレコードの値が解除前と異なったので、結局ダウンタイムは発生していた。
  2. リダイレクトの方法は複数ある。Googleが最も推奨している301リダイレクトを実施する。

参考: リダイレクトによる SEO への影響 | Google 検索セントラル  |  ドキュメント  |  Google Developers

リダイレクト設定の手順

httpsプロトコルでリダイレクトするにはAWSのS3のみでは不可で、Cloudfrontを使う必要があるとのこと。 なので、

  1. S3でbucketを作成
  2. 1で作成したbucketをオリジンドメインに指定して、CloudFrontのディストリビューションを作成
  3. ドメインを2のディストリビューションに紐付け(Aレコード)
  4. 2のディストリビューションに「新ドメインにリダイレクトする」関数を定義

サンプル: ビューワーを新しい URL にリダイレクトさせる - Amazon CloudFront

検証

curlコマンドで旧ドメインにリクエストし、301が帰ってきたら成功。

創業の経緯と現場Hub開発の面白さについて

初めまして。株式会社ARTISANの取締役CTOの沖永です。

2022年4月に現・代表取締役CEOの岡田と共同創業しました。

中小規模工事会社向けの基幹システム「現場Hub」を開発しています。

 

創業の経緯

2021年2月に大学時代の同級生だった岡田と、たまたま再会しました。

話してみると、岡田は工事会社の課題を深く知っていて、それを強く解決したいと思っていることがわかりました。

そこからプロトタイピングしながら、工事会社にヒアリングする活動を始めました。

一緒に始める決断をしたのは、

- 岡田がドメインエキスパートだった

- 誰かの課題を解決するソフトウェアを自ら設計して作りたい私の強い欲求があった

という要因が大きかったです。

課題を解決しよく使われるソフトウェアは、対象領域について深く理解している人にしか作れないです。

仮に、ネタはなんでも良いから起業したい、というような人の誘いであればノらなかったと思います。

 

現場Hub開発の面白さについて

個別要件があるなかの汎用化

まず現場Hubのゴールを、工事会社が利用するソフトウェアのデファクトスタンダードにすることに置いています。

デファクトスタンダードにするには、いかに大きな個別カスタマイズを減らすかが鍵だと考えます。数多くの工事会社に対して個別要件の保守チームを設けるのは非現実的だからです。

現場Hubは、元々1社向けの受託開発のシステムとして開発していました。

1社受注が決まる度に、開発したいくつかの仕様が個別要件であることがわかり、汎用化作業をします。

ここまでは自然な流れなのですが、複数方面からの要望を同時に実現することが難しい場面にしばしば遭遇します。

これらをうまい具合に単一機能にまとめる作業が要件定義・設計チームの腕の見せ所であり、議論に多くの時間を費やしています。

 

デザインの探求

ドメインエキスパート・デザイナー・プログラマー全員で、各々の異なる視点を出しつつ議論しながら決めます。

議論の内容として、画面構成はもちろん文言レベルにも渡ります。どの文言がユーザーにとって認知しやすいのか、議論して決めていきます。

また、隔週でDogFoodingMeetingを開催し、使いにくい機能を洗い出し、Issueを立てます。このMeeting にもデザイナー・プログラマーも参加するため、どう設計・実装すればよいかという議論が有意義かつスピーディにでき、サービスを爆速で改善していくことができます。

そしてお客さんからのF/Bも開発チームで共有し、再びみんなで議論し、改善します。

どんどん理想のソフトウェアに近づけている実感を得られます。

このように、ユースケース・デザインの意図・実装や保守の容易性などの共通認識を全員で持ち、最適なデザインを作り上げていきます。

 

我々にしかできない開発

現場Hubほど工事会社に寄り添えているソフトウェアは存在しないと思っています。

時にお客さんの事務所や工事現場に、開発チームが出向いたりもします。ドメイン理解にもっとも効果的だと考えているからです。

また実際に現場Hubを工事会社に見せた時の反応が、バーニングニーズを捉えられているように感じます。

このように開発できている理由は、ドメインエキスパートと開発チームの会話がうまくいっており、デザイナー・プログラマーがきちんと形にできているからだとおもいます。

工事会社のデファクトスタンダードになる可能性は高いと感じています。

 

これから

株式会社ARTISANはこれからどんどん拡大していきます。

その過程を一緒に楽しめる仲間を募集しています。

これまでにないサービスを作りたい方、ぜひ一緒に働いてみましょう。

私のTwitterから連絡いただけると幸いです。