Skip to content

Commit

Permalink
Add article
Browse files Browse the repository at this point in the history
  • Loading branch information
r7kamura committed Nov 30, 2024
1 parent 8aacc38 commit d4df1a7
Showing 1 changed file with 164 additions and 0 deletions.
164 changes: 164 additions & 0 deletions articles/2024-11-30-gemfile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
title: Gemfileの運用
---

長年の運用で「Gemfileはこう運用すると上手くいった」という知見が蓄積されてきたので、ここに書き出してみておく。

## Bundler/OrderedGemsを有効化する

RuboCopの `Bundler/OrderedGems` Copを有効化する。

悪い例:

```ruby
gem 'puma'
gem 'jbuilder'
```

良い例:

```ruby
gem 'jbuilder'
gem 'puma'
```

## セクションを分けない

基本的に、独自の判断で空行を入れてセクションを分けたりしない。

ここで言うセクションとは「空行で区切られた1つのまとまり」のことである。`Bundler/OrderedGems` は、このまとまりの中で辞書順であることを要求する。

悪い例:

```ruby
gem 'aws-sdk-rails'
gem 'aws-sdk-s3'

gem 'graphql'
gem 'graphql-batch'
```

良い例:

```ruby
gem 'aws-sdk-rails'
gem 'aws-sdk-s3'
gem 'graphql'
gem 'graphql-batch'
```

但し、1つの例外を認める。`Bundler.require` を活用しているプロジェクトで、どうしても先に読み込ませたいgemがある場合である。代表的な例だと、`if defined?(Rails)` のためにrails gemを先に読み込ませておきたいといった例が挙げられる。

悪い例:

```ruby
gem 'jbuilder'
gem 'puma'
gem 'rails'
```

良い例:

```ruby
gem 'rails'

gem 'jbuilder'
gem 'puma'
```

## コメントにWhatを書かない

そのGemのdescriptionを見れば分かるような情報をコメントに書かない。

コメントはあればあるほど情報量が増えて嬉しいという訳ではない。重要性の低い情報が増えれば増えるほど、重要な情報がより見られなくなってしまう。また、コメントは無料ではなく、意外とそれを保守するためにコストが支払われる。

どのコメントが「必要」でどのコメントが「不要」かを決めるのは容易ではない。指針として、5W1Hで言うところのWhyを表す情報は残すに足る価値があり、Whatには無い、という指針が良いと考えている。

悪い例:

```ruby
gem 'jbuilder' # JSON生成用のDSLを提供する。
gem 'listen' # i18n-jsの自動更新機能に必要。
gem 'vcr', '<= 5' # 次のバージョンからライセンスが変更されてしまう。
```

良い例:

```ruby
gem 'jbuilder'
gem 'listen' # i18n-jsの自動更新機能に必要。
gem 'vcr', '<= 5' # 次のバージョンからライセンスが変更されてしまう。
```

## 機械的なアップグレードのためにバージョンを指定する

バージョン指定は「この範囲までのアップグレードを機械的に提案してほしい」という意図を持って指定する。

その時点で採用したバージョンにとりあえず `~>` を付けて指定しておこう、といった類の行為は避ける。

悪い例:

```ruby
gem 'aws-sdk-rails', '~> 5.0.0'
```

良い例:

```ruby
gem 'aws-sdk-rails'
```

## dependabotにlockfile-onlyを指定する

dependabotに `versioning-strategy: lockfile-only` を設定する。

dependabotは、デフォルトではGemfileでのバージョン指定を考慮してくれない。この状態では、どのようにバージョンを指定していてもその指定ごと変更を提案されてしまい、先述したようなバージョン指定の運用ができない。

またこのデフォルト設定で運用していると、dependabotの設定ファイルに特定のGemのアップグレードを提案しない設定やその理由が書かれることになるため、情報の分散を招き保守性を下げるという点でも好ましくない。

悪い例:

```yaml
updates:
- package-ecosystem: bundler
directory: ...
schedule: ...
```
良い例:
```yaml
updates:
- package-ecosystem: bundler
directory: ...
schedule: ...
versioning-strategy: lockfile-only
```
## dependabotの付けるラベルを変更する
デフォルトの `dependencies` + `ruby` のラベルから、`dependabot-bundler` 等に変更しておく。

デフォルトで用意される `ruby` ラベルは特に誤解を招きやすく、まともな運用に適さない。`ruby` ラベルの説明文には「Pull requests that update Ruby code」と記載されるが、こういうものがあると「Rubyのコードを変更するから、自分のつくったPull Requestに `ruby` ラベルを付けておこう」と考えてこのラベルを付けたり付けなかったりする者が後を絶たない。

`dependencies` ラベルは `author:dependabot` で代替できるので、このラベルの存在によって付加される情報量は少ない。

悪い例:

```yaml
updates:
- package-ecosystem: bundler
directory: ...
schedule: ...
```

良い例:

```yaml
updates:
- package-ecosystem: bundler
directory: ...
schedule: ...
labels:
- dependabot-bundler
```

0 comments on commit d4df1a7

Please sign in to comment.