File: merge_commit.rb

package info (click to toggle)
ruby-gh 0.21.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,644 kB
  • sloc: ruby: 1,793; makefile: 4
file content (89 lines) | stat: -rw-r--r-- 2,324 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# frozen_string_literal: true

require 'gh'
require 'timeout'

module GH
  # Public: ...
  class MergeCommit < Wrapper
    wraps GH::Normalizer
    double_dispatch

    def setup(backend, options)
      @ssl = options[:ssl]
      super
    end

    def modify_hash(hash)
      setup_lazy_loading(super)
    rescue StandardError => e
      raise Error.new(e, hash)
    end

    private

    def lazy_load(hash, key)
      return unless key =~ (/^(merge|head|base)_commit$/) && hash.include?('mergeable')
      return unless merge_commit?(hash)

      fields = pull_request_refs(hash)
      fields['base_commit'] ||= commit_for hash, hash['base']
      fields['head_commit'] ||= commit_for hash, hash['head']
      fields
    rescue StandardError => e
      raise Error.new(e, hash)
    end

    def commit_for(from, hash)
      { 'sha' => hash['sha'], 'ref' => hash['ref'],
        '_links' => { 'self' => { 'href' => git_url_for(from, hash['sha']) } } }
    end

    def git_url_for(hash, commitish)
      hash['_links']['self']['href'].gsub(%r{/pulls/(\d+)$}, "/git/#{commitish}")
    end

    def pull_request_refs(hash)
      link = git_url_for(hash, 'refs/pull/\1')
      commits = self[link].map do |data|
        ref = data['ref']
        name = "#{ref.split('/').last}_commit"
        object = data['object'].merge 'ref' => ref
        [name, object]
      end
      commits.to_h
    end

    def merge_commit?(hash)
      force_merge_commit(hash)
      hash['mergeable']
    end

    def github_done_checking?(hash)
      case hash['mergeable_state']
      when 'checking' then false
      when 'unknown' then hash['merged']
      when 'clean', 'dirty', 'unstable', 'stable', 'blocked', 'behind', 'has_hooks', 'draft' then true
      else raise "unknown mergeable_state #{hash['mergeable_state'].inspect} for #{url(hash)}"
      end
    end

    def force_merge_commit(hash)
      Timeout.timeout(180) do
        update(hash) until github_done_checking? hash
      end
    rescue TimeoutError
      status = hash['mergeable_state'].inspect
      raise TimeoutError, "gave up waiting for github to check the merge status (current status is #{status})"
    end

    def update(hash)
      hash.merge! backend[url(hash)]
      sleep 0.5
    end

    def url(hash)
      hash['_links']['self']['href']
    end
  end
end