Class: GitHubClient

Inherits:
Object
  • Object
show all
Defined in:
lib/github_client.rb

Constant Summary collapse

API_BASE =
"https://api.github.com"

Instance Method Summary collapse

Constructor Details

#initialize(token: nil) ⇒ GitHubClient

Returns a new instance of GitHubClient.



10
11
12
# File 'lib/github_client.rb', line 10

def initialize(token: nil)
    @token = token || ENV["GITHUB_TOKEN"]
end

Instance Method Details

#api_get(path) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/github_client.rb', line 68

def api_get(path)
    uri = URI("#{API_BASE}#{path}")
    req = Net::HTTP::Get.new(uri)
    req["Accept"] = "application/vnd.github+json"
    req["Authorization"] = "Bearer #{@token}" if @token
    req["X-GitHub-Api-Version"] = "2022-11-28"

    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.open_timeout = 10
    http.read_timeout = 30

    resp = http.request(req)

    case resp.code.to_i
    when 200
        JSON.parse(resp.body)
    when 404
        nil
    when 403
        $stderr.puts "Rate limited or forbidden: #{path}"
        nil
    else
        $stderr.puts "API error #{resp.code}: #{path}"
        nil
    end
end

#fetch_dependabot_config(repo) ⇒ Object



57
58
59
60
61
62
63
64
65
66
# File 'lib/github_client.rb', line 57

def fetch_dependabot_config(repo)
    content = fetch_file_content(repo, ".github/dependabot.yml")
    content ||= fetch_file_content(repo, ".github/dependabot.yaml")
    return nil unless content
    begin
        YAML.safe_load(content)
    rescue StandardError => e
        nil
    end
end

#fetch_file_content(repo, path) ⇒ Object



29
30
31
32
33
# File 'lib/github_client.rb', line 29

def fetch_file_content(repo, path)
    data = api_get("/repos/#{repo}/contents/#{path}")
    return nil unless data.is_a?(Hash) && data["content"]
    Base64.decode64(data["content"])
end

#fetch_repos(org) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/github_client.rb', line 35

def fetch_repos(org)
    repos = []
    page = 1
    loop do
        batch = api_get("/orgs/#{org}/repos?per_page=100&page=#{page}&type=all")
        break unless batch.is_a?(Array) && !batch.empty?
        batch.each do |r|
            next if r["archived"]
            repos << r["full_name"]
        end
        page += 1
        break if batch.length < 100
    end
    repos.sort
end

#fetch_workflows(repo) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/github_client.rb', line 14

def fetch_workflows(repo)
    workflows = []
    files = api_get("/repos/#{repo}/contents/.github/workflows")
    return workflows unless files.is_a?(Array)

    files.each do |f|
        next unless f["name"].end_with?(".yml", ".yaml")
        content = fetch_file_content(repo, f["path"])
        next unless content
        workflows << { filename: f["name"], content: content }
    end

    workflows
end

#file_exists?(repo, path) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
54
55
# File 'lib/github_client.rb', line 51

def file_exists?(repo, path)
    !api_get("/repos/#{repo}/contents/#{path}").nil?
rescue StandardError
    false
end