GitHub CLI使ってみた

GitHubからCLI上でPRやIssueの操作をすることができるGitHub CLIがリリースされたので早速触ってみました。 PRの操作とIssueの操作はだいたい似ているのでPRの方だけレポートしたいと思いますー。

cli.github.com

環境は、OSが macOS Mojave 10.14.6GitHub CLIはhomebrewで入れました。

公式のドキュメントはこちら

gh pr create

現在使っているブランチを元にCLI上でPRが作れるコマンド。 タイトルやディスクリプションもCLI上で書くことが可能です。

gh pr create を実行するとPRのタイトルを求められます。少し時間がかかるんですが、これは裏でremoteにブランチをpushしているからでした。

  $ gh pr create

Creating pull request for test into master in kamillle/tutorial_app

? Title gh pr createで作ってみた

ディスクリプション部分を入力することができます。 e を入力するとnvimが開いてmarkdownを編集するモードになり、enterを入力するとディスクリプションの入力をスキップできます。 e で開けるエディタは $EDITOR の値を見ていました。

  $ gh pr create

Creating pull request for test into master in kamillle/tutorial_app

? Title gh pr create で作ってみた
? Body [(e) to launch nvim, enter to skip]

Bodyを入力 or スキップすると、Preview in browser, Submit, Cancelの3択が選べます。矢印キーで移動可能、文字入力による絞り込みもできました。

  $ gh pr create
gh pr create で
Creating pull request for test into master in kamillle/tutorial_app

? Title gh pr create で作ってみた
? Body <Received>
? What's next?  [Use arrows to move, type to filter]
> Preview in browser
  Submit
  Cancel

Preview in browser

Preview in browserをするとブラウザでいつものこの画面が開きます。

f:id:kamillle:20200213153302p:plain
gh pr statsuでPreview in browserを選んだ図

CLIで入力した項目がクエリパラメータで載っかってました。 f:id:kamillle:20200213153509p:plain

Submit

Submitを選択するとPRが作成され、そのURLが返ってきます。

  $ gh pr create

Creating pull request for test into master in kamillle/tutorial_app

? Title gh pr create で作ってみた
? Body <Received>
? What's next? Submit
https://github.com/kamillle/tutorial_app/pull/62

Cancel

Discarding. が返ってきて、処理が中断されます。入力していたタイトルとかはリストアできないので注意。

gh pr list

PRの番号、タイトル、ブランチ名が返ってきます。 一度に表示されるのは最新の30件まででした。

  $ gh pr list

Pull requests for kamillle/tutorial_app

#62  gh pr create で作ってみた                             test
#61  [Security] Bump rack from 2.0.7 to 2.2.1        dependabot/bundler/rack-2.2.1
#60  [Security] Bump nokogiri from 1.10.4 to 1.10.8  dependabot/bundler/nokogiri-1.10.8
#58  [Security] Bump excon from 0.65.0 to 0.72.0     dependabot/bundler/excon-0.72.0
#57  Bump faker from 2.2.1 to 2.10.1                 dependabot/bundler/faker-2.10.1
#56  Bump pg from 0.18.4 to 1.2.2                    dependabot/bundler/pg-1.2.2
#46  Bump listen from 3.1.5 to 3.2.1                 dependabot/bundler/listen-3.2.1
#44  [Security] Bump puma from 4.1.0 to 4.3.1        dependabot/bundler/puma-4.3.1
#42  [Security] Bump loofah from 2.2.3 to 2.4.0      dependabot/bundler/loofah-2.4.0
#39  Bump guard from 2.15.0 to 2.16.1                dependabot/bundler/guard-2.16.1
#37  Bump minitest-reporters from 1.3.6 to 1.4.2     dependabot/bundler/minitest-reporters-1.4.2
#33  Bump will_paginate from 3.1.7 to 3.2.1          dependabot/bundler/will_paginate-3.2.1
#28  Bump carrierwave from 2.0.1 to 2.0.2            dependabot/bundler/carrierwave-2.0.2
#27  Bump uglifier from 4.1.20 to 4.2.0              dependabot/bundler/uglifier-4.2.0
#25  Bump turbolinks from 5.2.0 to 5.2.1             dependabot/bundler/turbolinks-5.2.1

gh pr status

Current branch に現在のブランチ Created by you に自分が作成したPR Requesting a code review from you に自分以外の人が作成したPRで、自分がReviewerに追加されているPR が並びます。

  $ gh pr status

Relevant pull requests in kamillle/tutorial_app

Current branch
  There is no pull request associated with [master]

Created by you
  #62  gh pr create で作ってみた [test]
   - Checks passing

Requesting a code review from you
  #60  [Security] Bump nokogiri from 1.10.4 to 1.10.8 [dependabot/bundler/nokogiri-1.10.8]
   - Checks passing
  #58  [Security] Bump excon from 0.65.0 to 0.72.0 [dependabot/bundler/excon-0.72.0]
   - Checks passing
  #57  Bump faker from 2.2.1 to 2.10.1 [dependabot/bundler/faker-2.10.1]
   - Checks passing
  #56  Bump pg from 0.18.4 to 1.2.2 [dependabot/bundler/pg-1.2.2]
   - Checks passing
  #46  Bump listen from 3.1.5 to 3.2.1 [dependabot/bundler/listen-3.2.1]
   - Checks passing
  #44  [Security] Bump puma from 4.1.0 to 4.3.1 [dependabot/bundler/puma-4.3.1]
   - Checks passing
  #42  [Security] Bump loofah from 2.2.3 to 2.4.0 [dependabot/bundler/loofah-2.4.0]
   - Checks passing
  #39  Bump guard from 2.15.0 to 2.16.1 [dependabot/bundler/guard-2.16.1]
   - Checks passing
  #37  Bump minitest-reporters from 1.3.6 to 1.4.2 [dependabot/bundler/minitest-reporters-1.4.2]
   - Checks passing
  #33  Bump will_paginate from 3.1.7 to 3.2.1 [dependabot/bundler/will_paginate-3.2.1]
   - Checks passing

Created by you, Requesting a code review from youに表示されるのは最新の10件までです。 Created by youではChecksがグリーンになっているかとapproveがついていれば approved と表示されます。

Created by you
  #1  Test Pr... [test-pr]
   - Checks passing - approved

レビュー済みのものは Requesting a code review from you には表示されなくなります。

gh pr view

gh pr view 1 とすると1番が割り当てられているPRがブラウザで開かれます。番号でなくてもURLやブランチ名でも開けるみたいです。 番号を省略した時にcurrent branchのPRを開いてくれるので便利だなと思いました。(PRが存在しない場合はエラー)

-p or --preview をつけるとCLI上でPRの情報を閲覧できます。

gh pr checkout

gh pr checkout 1 とすると1番が割り当てられてるブランチにcheckoutできます。番号でなくてもURLやブランチ名でも開けるみたいです。 他の人がforkして作ったブランチにもcheckoutできるので便利です。( user_name:branch_name で開けます) 同じことをhubコマンドでできたはずですが、hubコマンドはVCSの表示が遅くなるのが理由で使用を避けていたのでこれは嬉しい!!

Railsの自動読み込み eager_loadの処理を調べた

eager_loadがどのように行われているのか知りたいので調べた。 環境は

eager_loadの処理

Railsのサーバーを立ち上げ時に config.ru ファイルが読み込まれる。

# config.ru

# This file is used by Rack-based servers to start the application.

require_relative 'config/environment'

run Rails.application

config.ruはconfig/environment.rbを読み込む。

# config/environment.rb

# frozen_string_literal: true

# Load the Rails application.
require_relative 'application'

# Initialize the Rails application.
Rails.application.initialize!

config/environment.rbは config/application.rb を読み込み、アプリケーションの設定などを確保する。

その後 Rails.application.initialize! を実行する。 initialize! から処理がRailsの内部に入っていく。

# https://github.com/rails/rails/blob/v6.0.2/railties/lib/rails/application.rb#L359-L366

# Initialize the application passing the given group. By default, the
# group is :default
def initialize!(group = :default) #:nodoc:
  raise "Application has been already initialized." if @initialized
  run_initializers(group, self)
  @initialized = true
  self
end

実際の初期化処理は run_initializers が行っている。

# https://github.com/rails/rails/blob/v6.0.2/railties/lib/rails/initializable.rb#L58-L64

def run_initializers(group = :default, *args)
  return if instance_variable_defined?(:@ran)
  initializers.tsort_each do |initializer|
    initializer.run(*args) if initializer.belongs_to?(group)
  end
  @ran = true
end

最後にinitializeしたというフラグを @ran に格納している。すでに実行済みであれば再実行されないようになっている。

initializers.tsort_each のinitializersは Rails::Application#initializers を実行している。

※ run_initializersが定義されているRails::Initializeableにも #initializers メソッドはあるが、Rails::Application#initializersが実行されるのはメソッド探索時にRails::Application#initializersが先に見つかるから

# https://github.com/rails/rails/blob/v6.0.2/railties/lib/rails/application.rb#L368-L372

def initializers #:nodoc:
  Bootstrap.initializers_for(self) + railties_initializers(super) + Finisher.initializers_for(self)
end

eager_loadの処理はFinisherに定義されてる

# https://github.com/rails/rails/blob/v6.0.2/railties/lib/rails/application/finisher.rb#L116-L125

initializer :eager_load! do
  if config.eager_load
    ActiveSupport.run_load_hooks(:before_eager_load, self)
    # Checks defined?(Zeitwerk) instead of zeitwerk_enabled? because we
    # want to eager load any dependency managed by Zeitwerk regardless of
    # the autoloading mode of the application.
    Zeitwerk::Loader.eager_load_all if defined?(Zeitwerk)
    config.eager_load_namespaces.each(&:eager_load!)
  end
end

config.eager_load は config/environments/development.rb とかで代入している config.eager_load の値が参照される。

まず ActiveSupport.run_load_hooks(:before_eager_load, self) でbefore_eager_loadという名前に登録されたブロックをselfをselfのコンテキストで実行する。

その後 Zeitwerk::Loader.eager_load_all が実行される(autoloaderがzeitwerkであろうと、clasicだろうと関係なくZeitwerk::Loader.eager_load_allが実行される必要があるらしいが、詳しくどういう理由なのはわからなかった。zeitwerk gemが必要としているのかな)。

config.eager_load_namespaces.each(&:eager_load!) ではeager_loadする名前空間をそれぞれeager_loadします。

[1] pry(main)> TestApp::Application
=> [I18n,
 ActiveSupport,
 ActionDispatch,
 ActiveModel,
 GlobalID,
 ActionView::Railtie,
 ActionView,
 ActionController,
 ActiveRecord,
 ActionMailer,
 ActionCable::Engine,
 ActionCable,
 Bootstrap::Rails::Engine,
 Devise::Engine,
 TestApp::Application]

eager_load! の実体は下記

# https://github.com/rails/rails/blob/v6.0.2/railties/lib/rails/engine.rb#L472-L483

def eager_load!
  # Already done by Zeitwerk::Loader.eager_load_all in the finisher.
  return if Rails.autoloaders.zeitwerk_enabled?

  config.eager_load_paths.each do |load_path|
    # Starts after load_path plus a slash, ends before ".rb".
    relname_range = (load_path.to_s.length + 1)...-3
    Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
      require_dependency file[relname_range]
    end
  end
end

zeitwerkを使っている場合はreturn、classicの場合はrequire_dependencyを使ってファイルをロードする。

参考

memo

require, require_dependencyの違い

require(path)

  • pathが絶対パスのときはそのパスのファイルを読み込む
  • 相対パスのときは $LOAD_PATH 内のパスを順番に探して最初に見つかったファイルをロードする
  • 拡張子は補完される
    • .rb, .so,.o,.dll など
    • .rbが補完される
  • 同じファイルを複数回読み込む

require_dependency(path)

  • rails(active_support)のメソッド
  • production環境ではrequire, development環境ではloadが実行される

OpenID Summit Tokyoに参加しました

f:id:kamillle:20200127100217p:plain

少し前までは認証認可、何それ。OAuth?OmniAuthなら触ったことある。ってくらいの今文字に起こすと恥ずかしいレベルだったのですが、ここ数ヶ月で急に認証認可やID管理の領域にも関わることになり、勉強しながら業務でも楽しく触れているイマココ、くらいの感じです。 そんな感じなのですが、所属している企業がOIDF-Jに参加していて、会員企業枠で参加できるチャンスがあったのでお願いして参加させていただきました。

www.openid.or.jp

開催された週に食中毒になってしまって体調がずっと悪かったこともあり、残念ながら午前中は参加できなかったのだが(Ian GrezarがIDプロビジョニングの話をしていたそうなので生で聞きたかった...)、それでも大満足の内容で、業務としてID領域に関われていることがすごくラッキーだなと思える一日だった。

運営の公式twitter

と言っているので、ほとんどの資料は後ほど公開してもらえると思う。 なので、ここではsummitを通して感じたこと、なぜそう思ったのか、あたりを書いておく。

全体での感想

2つの会場に分けて発表が行われていたが、僕はGrand hallにいる時間が多かった。 Grand hallではOIDCが世界と日本でどのように使われてきたか、今後どのように使っていきたいかが主に話されており、僕は下記のメッセージ性を感じた。

  • 6年前に仕様が策定されたOIDCは、今では様々な認証認可システムに実装されて世界ではインフラとして成り立った
  • 日本のID領域はまだまだ取り組み不足
  • 日本に関しては、OIDCをベースにインターネット上での我々の分身であるDigital Identityをどのように管理して、どのように社会インフラに組み込んでいくかが次の10年、20年を決める鍵になる

世界でOIDCはインフラとして成り立った

  • OIDCは100以上のcertificatedな実装例がある
  • OIDCだけでなく他の認証技術の導入も進んでいる
    • 本人確認はFIDO
    • IDプロビジョニングはSCIM
    • IDフェデレーションはSAML2.0が以前として使われているが、OIDCでフェデレーションが実現できるように仕様を検討していく
  • 韓国の金融機関の9割ではFIDO導入している
  • 経済産業省も、政府が提供する様々な電子申請システムに一つのアカウントでログインが可能になるgBizIDを昨年?一昨年?開発し、運用フェーズに載っている
    • 政府がIdPを作って、しかもOIDCを使ってるのはすごいなと思った

日本のID領域はまだまだ取り組み不足

  • 2000年代からGAFAMがIdentityを中心としたプラットフォーム戦略を実行して今がある
    • 中国も共産党体制による独自の方法でプラットフォームを築いた
  • 日本はプラットフォームを作れなかった

日本の未来を決めるDigital Identityへの取り組み方

@_nat さんのClosing Keynoteが熱かった...!!!

  • アメリカが取ったIT戦略を変法、日本が取ったIT戦略を西用に例えた話はとてもわかりやすいし、クラウド会計ソフトの会社にいる自分としてとても納得感があった
  • この話を経産省CIO補佐官だったり、他のカンファレンスと比べて官系の方が多いあの場で言えるのはすごく価値があるんじゃないかな

当日の資料はまだ公開されてないみたいだけど、過去の登壇資料がほぼ同じスライドだったのでリンクを置いておく。

https://www.sakimura.org/wp-content/uploads/2019/06/19604-The-8th-Continenten-v.2-%E5%85%AC%E9%96%8B%E7%94%A8.pdf

OpenID Connect活用したgBizID(法人共通認証基盤)の現状と今後の展望

経済産業省では、政府が提供する様々な電子申請システムに一つのアカウントでログインが可能になるgBizIDを昨年?一昨年?開発し、運用フェーズに載せているそうです。

印象に残っているのは、登壇者の満塩さんがgBizIDを作るにあたっての苦労した点として、開発・導入にあたって丁寧なコミュニケーションが求められると述べられていたことでした。

登壇では下記の事例が紹介されたのですが、自分も業務で社内にID技術を導入することに取り組んでいるので、同じように丁寧にコミュニケーションを取って導入・運用まで持っていくことが大事だなと再認識しました。

  • 共有認証基盤により一つのアカウント(id/password)でその他のシステムにログインが可能になると話すと、パスワードを他のシステムにコピーすると思われるので、そうでないことを説明する
  • システム導入費用に数億円かかると思われて導入が進まなくなってしまうので、OIDF-Jが公開しているcertificatedなライブラリ(?)を紹介する

最後に

弊社SlackではOpenIDコネクたんが圧倒的人気を誇っていました。(僕はOAuthたん派です)

f:id:kamillle:20200128010159p:plain
OpenIDコネクたんとOAuthたん