Skip to content

Instantly share code, notes, and snippets.

@kateinoigakukun
Last active April 12, 2022 16:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kateinoigakukun/2a4c7840a1efc8e4ab2a78de7e9d4aa5 to your computer and use it in GitHub Desktop.
Save kateinoigakukun/2a4c7840a1efc8e4ab2a78de7e9d4aa5 to your computer and use it in GitHub Desktop.
# $ ruby ./bisect-toolchain-snapshot.rb swift-wasm-DEVELOPMENT-SNAPSHOT-2021-12-12-a swift-wasm-DEVELOPMENT-SNAPSHOT-2022-04-06-a run.sh --workdir /tmp/toolchain-bisect
require "date"
require "net/http"
require "json"
require "tmpdir"
def bisect_date_seq(candidates)
bad = 0
good = candidates.length - 1
loop do
mid = bad + (good - bad) / 2
break if mid == good or mid == bad
puts "select #{candidates[mid]["tag_name"]}, good = #{candidates[good]["tag_name"]}, bad = #{candidates[bad]["tag_name"]}"
ok = yield candidates[mid]
if ok
good = mid
else
bad = mid
end
end
candidates[bad]
end
def snapshot_exist?(tag_name, date)
uri = URI.parse("https://api.github.com/repos/swiftwasm/swift/releases/tags/#{tag_name}")
p uri
response = Net::HTTP.get_response(uri)
if response.code == "200"
true
else
puts "Got #{response}"
false
end
end
def fetch_snapshot(tag_name, workdir)
snapshot_uri = "https://github.com/swiftwasm/swift/releases/download/#{tag_name}/#{tag_name}-ubuntu20.04_x86_64.tar.gz"
dir = File.join(workdir, tag_name)
toolchain_dir = File.join(dir, tag_name)
return toolchain_dir if Dir.exist?(toolchain_dir)
Dir.mkdir(dir) unless Dir.exist?(dir)
puts "Fetching #{snapshot_uri} in #{dir} ..."
Dir.chdir(dir) do
raise "failed to fetch" unless system("curl -L #{snapshot_uri} | tar xz")
end
toolchain_dir
end
def github_get_response(uri)
headers = {}
headers["Authorization"] = "token #{ENV["GITHUB_TOKEN"]}" if ENV["GITHUB_TOKEN"]
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme === "https"
http.get(uri, headers)
end
def fetch_all_candidates(new, old)
page = 1
found_new = false
found_old = false
candidates = []
loop do
uri = URI.parse("https://api.github.com/repos/swiftwasm/swift/releases?page=#{page}&per_page=30")
response = github_get_response(uri)
abort "bad response code #{response.code}" unless response.code == "200"
releases = JSON.parse(response.body)
releases.each do |release|
next unless release["tag_name"].start_with?("swift-wasm-DEVELOPMENT-SNAPSHOT")
found_new ||= release["tag_name"] == new
found_old ||= release["tag_name"] == old
candidates.push(release) if found_new && !found_old
end
page += 1
break if found_new and found_old
end
candidates
end
require "optparse"
opts = OptionParser.new
workdir = nil
opts.on("--workdir DIR") { |v| workdir = v }
opts.parse!(ARGV)
workdir ||= Dir.mktmpdir("toolchain-bisect")
bad_date = ARGV[0]
good_date = ARGV[1]
cmd = ARGV[2]
unless File.exist?(".cache-candidates.json")
candidates = fetch_all_candidates(good_date, bad_date)
File.write(".cache-candidates.json", JSON.dump(candidates))
else
candidates = JSON.parse(File.read(".cache-candidates.json"))
end
oldest_bad = bisect_date_seq(candidates) do |candidate|
dir = fetch_snapshot(candidate["tag_name"], workdir)
new_bin_path = "#{dir}/usr/bin"
puts "Adding #{new_bin_path}, then testing..." if $VERBOSE
ok = system({"PATH" => "#{new_bin_path}#{File::PATH_SEPARATOR}#{ENV['PATH']}"}, cmd, chdir: dir)
puts "#{candidate["tag_name"]} is #{ok ? "good" : "bad"}"
ok
end
puts "#{oldest_bad["tag_name"]} is the oldest bad snapshot"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment