-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathgithub-update.rb
115 lines (103 loc) · 4.2 KB
/
github-update.rb
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
require 'net/http'
require 'uri'
require 'json'
# Get release info from github
# Extracted into a class so it can be shared by multiple formulae.
class GithubUpdate
# net::http doesn't handle redirects, so we have to handle them
# here. It also doesnt have raise_for_status (like python requests)
# so we check the http response code and raise if its not a redirect
# or a 200.
def self.get_with_redirect(uri)
for _ in 1..20
# Ruby <3 includes net/http <0.1.1 where get_response doesn't take
# headers. Macos includes ruby 2.6.0, and to avoid users having to
# update ruby in order to brew install this package, we must make
# sure the library calls used are compatible with net/http v0.1.0
request = Net::HTTP::Get.new(uri)
using_token = false
# Homebrew seems to santize its environment variables, so we have to
# use a hombrew recognised environment variable.
if ENV.include? 'HOMEBREW_GITHUB_PACKAGE_TOKEN' and not(ENV['HOMEBREW_GITHUB_PACKAGE_TOKEN'].empty?)
using_token = true
# While github allows unauthenticated requests, the rate limit is low
# and easily hit in CI systems. To avoid this, we allow a GITHUB_TOKEN
# to be specified.
request["Authorization"] = "token #{ENV['HOMEBREW_GITHUB_PACKAGE_TOKEN']}"
end
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(request)
}
redirect = response.header['location']
if redirect != nil
uri = URI.parse(response.header['location'])
elsif response.code == 200.to_s
return response
else
body = response.body
if body.include? "rate limit"
if using_token
raise "Github rate limit exceeded :( "\
"A token was provided, check its valid and has quota."
else
raise "Github rate limit exceeded :( "\
"Rate limits are higher for authenticated users so try with a "\
"Github Personal Access Token eg: " \
"HOMEBREW_GITHUB_PACKAGE_TOKEN=YOUR_PAT_HERE brew install ... "
end
else
raise "Failed to fetch #{response.uri} Code: #{response.code} Response: #{response.body}."
end
end
end
raise "Too many redirects fetching #{uri}"
end
def self.getLatestRelease(repo)
# Can't use graphql unauthenticated, so have to use v3/REST API.
# Find the latest release
releases_uri = URI.parse("https://api.github.com/repos/#{repo}/releases")
releases_response = self.get_with_redirect(releases_uri)
releases = JSON.parse(releases_response.body)
raise "No GitHub releases found for repo #{repo}" if releases.empty?
latest = releases[0]
ver = latest["tag_name"].delete_prefix("v")
# Get list of artifacts from release
artifacts_uri = URI.parse(latest["assets_url"])
artifacts_response = self.get_with_redirect(artifacts_uri)
artifacts_json = JSON.parse(artifacts_response.body)
# Find hashes file generated by goreleaser in list of release assets
hashes_artifact_matches = artifacts_json.filter do |a|
a['name'].include? "SHA256SUMS"
end
if hashes_artifact_matches.empty?
raise "SHA256SUMS asset not found attached to github release #{releases_uri}"
end
hashes_artifact = hashes_artifact_matches[0]
# Download Hashes file
hashes_uri = URI.parse(hashes_artifact['browser_download_url'])
hashes_response = self.get_with_redirect(hashes_uri)
hashes_txt = hashes_response.body
# Parse hashes file into { filename => {'hash' => hash}}
artifacts = {}
for line in hashes_txt.split("\n") do
hash, file = line.split()
artifacts[file] = {"hash" => hash}
end
# Add download url to each artifact
# After this loop we have { filename => {'hash' => hash, 'url' => url}}
for artifact in artifacts_json do
name = artifact['name']
if artifacts.key? name
artifacts[name]['url'] = artifact['browser_download_url']
end
end
return ver, artifacts
end
# Map homebrew to goreleaser arch types
def self.arch(type)
return {
"intel" => "amd64",
"arm" => "arm64"
}[String(type)]
end
end