[180731]Gitlab の Merge Request から学ぶ

サボっていたわけではなく、MRがなかったのです！

# [Add support for searching users by confirmed e-mails](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20893/diffs)

`find_by_any_email` に `confirmed` の条件を追加してる。これによって動きが変わるのでは？と思ったけど、たぶんこれがユーザーが想定しているであろう正常な動きなんだと思う。

`take` も順序保証とかしてないし大丈夫なのかな？と思ったけど、メソッド名が `find_by_any_email` なので納得。

```diff
    # Find a User by their primary email or any associated secondary email
-   def find_by_any_email(email)
-     by_any_email(email).take
+   def find_by_any_email(email, confirmed: false)
+     by_any_email(email, confirmed: confirmed).take
    end

    # Returns a relation containing all the users for the given Email address
-   def by_any_email(email)
+   def by_any_email(email, confirmed: false)
      users = where(email: email)
+     users = users.confirmed if confirmed
+
      emails = joins(:emails).where(emails: { email: email })
+     emails = emails.confirmed if confirmed
      union = Gitlab::SQL::Union.new([users, emails])

      from("(#{union.to_sql}) #{table_name}")
```

# [Extend gitlab-ci.yml to request junit.xml test reports](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20390/diffs)

このMRとは直接関係ないけど、動的に関連を定義する方法は初めて見たのでメモ :memo:

```diff
-   has_one :job_artifacts_archive, -> { where(file_type: Ci::JobArtifact.file_types[:archive]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
-   has_one :job_artifacts_metadata, -> { where(file_type: Ci::JobArtifact.file_types[:metadata]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
-   has_one :job_artifacts_trace, -> { where(file_type: Ci::JobArtifact.file_types[:trace]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
+
+   Ci::JobArtifact.file_types.each do |key, value|
+     has_one :"job_artifacts_#{key}", -> { where(file_type: value) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id
+   end
```

# [Fix /admin/jobs failing to load due to statement timeout](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20909/diffs)

> The ORDER BY created_at DESC clause causes a sequential scan because
there is no index on the created_at column. We can sort by id
or by updated_at to make things fast.

うっかり `created_at` でやらないように気をつけねば！

# [Add /-/health basic health check endpoint](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20456/diffs)
Health Check のための middleware を定義してる。

```ruby
# frozen_string_literal: true

# This middleware provides a health check that does not hit the database. Its purpose
# is to notify the prober that the application server is handling requests, but a 200
# response does not signify that the database or other services are ready.
#
# See https://thisdata.com/blog/making-a-rails-health-check-that-doesnt-hit-the-database/ for
# more details.

module Gitlab
  module Middleware
    class BasicHealthCheck
      # This can't be frozen because Rails::Rack::Logger wraps the body
      # rubocop:disable Style/MutableConstant
      OK_RESPONSE = [200, { 'Content-Type' => 'text/plain' }, ["GitLab OK"]]
      EMPTY_RESPONSE = [404, { 'Content-Type' => 'text/plain' }, [""]]
      # rubocop:enable Style/MutableConstant
      HEALTH_PATH = '/-/health'

      def initialize(app)
        @app = app
      end

      def call(env)
        return @app.call(env) unless env['PATH_INFO'] == HEALTH_PATH

        request = Rack::Request.new(env)

        return OK_RESPONSE if client_ip_whitelisted?(request)

        EMPTY_RESPONSE
      end

      def client_ip_whitelisted?(request)
        ip_whitelist.any? { |e| e.include?(request.ip) }
      end

      def ip_whitelist
        @ip_whitelist ||= Settings.monitoring.ip_whitelist.map(&IPAddr.method(:new))
      end
    end
  end
end
```