[gem編] GitHub Package Registry (beta) を使ってみる


beta アクセスの invitation が届いていたのでテストしてみます。

GitHub Package Registry

GitHub パッケージレジストリ はソフトウェアパッケージホスティングサービスで、npmjs.org、rubygems.org、hub.docker.com に似ており、あなたがパッケージとコードを一カ所でホストできるようにします。 ソフトウェアパッケージをプライベートでもパブリックでもホストでき、それらをプロジェクト中で依存関係として利用できます。

対応しているパッケージクライアント

* 2019年7月5日時点

パッケージクライアント パッケージフォーマット
npm (Node) package.json
gem (Ruby) Gemfile
mvn (Java) pom.xml
docker container
nuget (.NET) nupkg

gem package を GitHub Package Registry に公開する

GitHub の設定

Personal access token に権限を追加

GitHub Package Registry を使うには personal access token に対して read:packages write:packages の scope を新たに追加する必要があります。
https://github.com/settings/tokens から当該の token を選択し、下記を選択します。

* パッケージの公開先が private repo の場合には、下記に加えて repo の scope も必要です。

gem & bundle の設定

複数の token を管理するため、keycutterをインストールします。

$ gem install keycutter

先程 scope 設定を変更した personal access token を ~/.gem/credentials に設定します。

---
:github: Bearer ${TOKEN}

bundler の設定をします。
OWNER は公開したい gem パッケージの repository を実際に保持している GitHub ユーザー、または組織アカウントの名前です。続けて GitHub の username, personal access token をここでも入力します。

$ bundle config https://rubygems.pkg.github.com/OWNER(or ORG) USERNAME:TOKEN

パッケージを公開 (gem push) する

注意事項

公開したパッケージは削除できない

現状、GitHub Package Registry では一度公開した pacakge を削除することはできないとのことです。
また、公開済みの特定のバージョンの削除も同様にサポートされていません。gem パッケージだけ?と思って他のパッケージの場合も確認してみましたが、ドキュメント上では全て削除には対応していない同様の文言でした。

あなたのパッケージに依存しているかもしれないプロジェクトを壊すことがないよう、GitHub パッケージレジストリはパッケージの削除や、パッケージのバージョンの削除をサポートしていません。法的な理由やGDPR標準といった特別な状況下では、GitHub Supportを通じてパッケージの削除をリクエストできます。連絡フォームを使って「GitHub パッケージレジストリ」というタイトル行でGitHub Supportに連絡してください。

パッケージの push 先 repository

GitHub Package Registry はデフォルトでは、gem の package name = GitHub repository name とみなしてパッケージを公開します。つまり、gemspec ファイルに下記の設定があるとすると、パッケージは https://github.com/USER(or ORG)/mygem に対して push されます。

Gem::Specification.new do |s|
  s.name        = 'mygem'
  ...

え、名前一致してないんだけど、という場合は、push 先の repository を下記のように指定できます。
また、下記の設定を使うことで、名前の異なる複数の gem パッケージを単一の repository に対して公開することもできるようです。

Gem::Specification.new do |s|
  s.name        = 'mygem'
  ...
  s.metadata = { "github_repo" => "ssh://github.com/USER(or ORG)/reponame" }

push した時の挙動

push されたパッケージは repository の Releases ページから確認ができます。
これまでの Release Tags に加えて、ここに Packages が加わります。

version の運用

特に何も考えずに gem push すると、デフォルトでは gemspec の version 情報を元に、もしまだ push 先の repository にその version の release/tag が存在していなければ、自動的に tag を切りその version で release まで作ってくれます。
この時の release の description は gemspec の description がそのまま適用されるようでした。

もし push 先の repository にその version の release/tag が既に存在している場合、上記の画像のように、自動的にその release に対して package が紐付けられます。

gem push

$ gem push --key github --host https://rubygems.pkg.github.com/USER(or ORG) mygem.gem
Pushing gem to https://rubygems.pkg.github.com/xxxx...
Successfully registered gem: mygem (x.x.x)

公開済みの version を再度 push するとエラーになります。

$ gem push --key github --host https://rubygems.pkg.github.com/USER(or ORG) mygem.gem
Pushing gem to https://rubygems.pkg.github.com/xxxx...
Error: Version x.x.x of "mygem" has already been pushed.

GitHub Package Registry から gem をインストールする

Gemfile に新しく source "https://rubygems.pkg.github.com/USER(or ORG)" を追加する例がドキュメントに公開されています。
https://help.github.com/en/articles/configuring-rubygems-for-use-with-github-package-registry#installing-a-package

gem install--source オプションでもいけるんですかね、未検証です。