Update Repology parser and bump command
This commit is contained in:
commit
3265650279
@ -17,7 +17,8 @@ module Homebrew
|
|||||||
|
|
||||||
def bump
|
def bump
|
||||||
bump_args.parse
|
bump_args.parse
|
||||||
puts "command run"
|
# puts "command run"
|
||||||
# parse_repology_api()
|
outdated_repology_pacakges = RepologyParser.parse_api_response()
|
||||||
|
puts RepologyParser.validate__packages(outdated_repology_pacakges)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,12 +4,12 @@ require "open3"
|
|||||||
|
|
||||||
module Livecheck
|
module Livecheck
|
||||||
def livecheck_formula_response(formula_name)
|
def livecheck_formula_response(formula_name)
|
||||||
puts "- livecheck formula : #{formula_name}"
|
ohai "- livecheck formula : #{formula_name}"
|
||||||
command_args = [
|
command_args = [
|
||||||
"brew",
|
"brew",
|
||||||
"livecheck",
|
"livecheck",
|
||||||
formula_name,
|
formula_name,
|
||||||
"--quiet"
|
"--quiet",
|
||||||
]
|
]
|
||||||
|
|
||||||
response = Open3.capture2e(*command_args)
|
response = Open3.capture2e(*command_args)
|
||||||
@ -17,11 +17,12 @@ module Livecheck
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse_livecheck_response(response)
|
def parse_livecheck_response(response)
|
||||||
output = response.first.gsub(' ', '').split(/:|==>|\n/)
|
output = response.first.delete(" ").split(/:|==>|\n/)
|
||||||
|
|
||||||
# eg: ["burp", "2.2.18", "2.2.18"]
|
# eg: ["burp", "2.2.18", "2.2.18"]
|
||||||
package_name, brew_version, latest_version = output
|
package_name, brew_version, latest_version = output
|
||||||
|
|
||||||
{'name' => package_name, 'current_brew_version' => brew_version, 'livecheck_latest_version' => latest_version}
|
{ "name" => package_name, "current_brew_version" => brew_version,
|
||||||
|
"livecheck_latest_version" => latest_version }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,47 +1,75 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "net/http"
|
require "utils/curl"
|
||||||
require "json"
|
require "formula_info"
|
||||||
|
|
||||||
module RepologyParser
|
module RepologyParser
|
||||||
def call_api(url)
|
module_function
|
||||||
puts "- Calling API #{url}"
|
|
||||||
uri = URI(url)
|
|
||||||
response = Net::HTTP.get(uri)
|
|
||||||
|
|
||||||
puts "- Parsing response"
|
def query_api(last_package_in_response = "")
|
||||||
JSON.parse(response)
|
|
||||||
end
|
|
||||||
|
|
||||||
def query_repology_api(last_package_in_response = "")
|
|
||||||
url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=homebrew&outdated=1"
|
url = "https://repology.org/api/v1/projects/#{last_package_in_response}?inrepo=homebrew&outdated=1"
|
||||||
|
ohai "Calling API #{url}" if Homebrew.args.verbose?
|
||||||
|
|
||||||
call_api(url)
|
output, errors, status = curl_output(url.to_s)
|
||||||
|
output = JSON.parse(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_repology_api
|
def parse_api_response()
|
||||||
puts "\n-------- Query outdated packages from Repology --------"
|
ohai "Querying outdated packages from Repology"
|
||||||
page_no = 1
|
page_no = 1
|
||||||
puts "\n- Paginating repology api page: #{page_no}"
|
ohai "Paginating repology api page: #{page_no}" if Homebrew.args.verbose?
|
||||||
|
|
||||||
outdated_packages = query_repology_api("")
|
outdated_packages = query_api()
|
||||||
last_pacakge_index = outdated_packages.size - 1
|
last_pacakge_index = outdated_packages.size - 1
|
||||||
response_size = outdated_packages.size
|
response_size = outdated_packages.size
|
||||||
|
page_limit = 15
|
||||||
|
|
||||||
while response_size > 1
|
while response_size > 1 && page_no <= page_limit
|
||||||
page_no += 1
|
page_no += 1
|
||||||
puts "\n- Paginating repology api page: #{page_no}"
|
ohai "Paginating repology api page: #{page_no}" if Homebrew.args.verbose?
|
||||||
|
|
||||||
last_package_in_response = outdated_packages.keys[last_pacakge_index]
|
last_package_in_response = outdated_packages.keys[last_pacakge_index]
|
||||||
response = query_repology_api("#{last_package_in_response}/")
|
response = query_api("#{last_package_in_response}/")
|
||||||
|
|
||||||
response_size = response.size
|
response_size = response.size
|
||||||
outdated_packages.merge!(response)
|
outdated_packages.merge!(response)
|
||||||
last_pacakge_index = outdated_packages.size - 1
|
last_pacakge_index = outdated_packages.size - 1
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "\n- #{outdated_packages.size} outdated packages identified by repology"
|
ohai "#{outdated_packages.size} outdated packages identified"
|
||||||
|
|
||||||
outdated_packages
|
outdated_packages
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate__packages(outdated_repology_packages)
|
||||||
|
ohai "Verifying outdated repology packages as Homebrew Formulae"
|
||||||
|
|
||||||
|
packages = {}
|
||||||
|
outdated_repology_packages.each do |_name, repositories|
|
||||||
|
# identify homebrew repo
|
||||||
|
repology_homebrew_repo = repositories.find do |repo|
|
||||||
|
repo["repo"] == "homebrew"
|
||||||
|
end
|
||||||
|
|
||||||
|
next if repology_homebrew_repo.empty?
|
||||||
|
latest_version = nil
|
||||||
|
|
||||||
|
# identify latest version amongst repology repos
|
||||||
|
repositories.each do |repo|
|
||||||
|
latest_version = repo["version"] if repo["status"] == "newest"
|
||||||
|
end
|
||||||
|
|
||||||
|
info = FormulaInfo.lookup(repology_homebrew_repo["srcname"])
|
||||||
|
next unless info
|
||||||
|
current_version = info.pkg_version
|
||||||
|
|
||||||
|
packages[repology_homebrew_repo["srcname"]] = {
|
||||||
|
"repology_latest_version" => latest_version,
|
||||||
|
"current_formula_version" => current_version.to_s
|
||||||
|
}
|
||||||
|
puts packages
|
||||||
|
end
|
||||||
|
# hash of hashes {"aacgain"=>{"repology_latest_version"=>"1.9", "current_formula_version"=>"1.8"}, ...}
|
||||||
|
packages
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -22,15 +22,15 @@ module Versions
|
|||||||
parse_formula_bump_response(response)
|
parse_formula_bump_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_formula_bump_response(response)
|
def parse_formula_bump_response(formula_bump_response)
|
||||||
response, status = formula_bump_response
|
response, _status = formula_bump_response
|
||||||
response
|
response
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_for_open_pr(formula_name, download_url)
|
def check_for_open_pr(formula_name, download_url)
|
||||||
puts "- Checking for open PRs for formula : #{formula_name}"
|
ohai "- Checking for open PRs for formula : #{formula_name}"
|
||||||
|
|
||||||
response = bump_formula_pr(formula_name, download_url)
|
response = bump_formula_pr(formula_name, download_url)
|
||||||
!response.include? 'Error: These open pull requests may be duplicates'
|
!response.include? "Error: These open pull requests may be duplicates"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
# 0.0.1-API-Parser
|
|
||||||
|
|
||||||
Parser for fixing this: https://github.com/Homebrew/brew/issues/5725
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Homebrew is used to install software (packages). Homebrew uses 'formulae' to determine how a package is installed.
|
|
||||||
This project will automatically check which packages have had newer versions released, whether the package has an open PR on homebrew, and display the results.
|
|
||||||
|
|
||||||
## High-level Solution
|
|
||||||
|
|
||||||
- Fetch latest package version information from [repology.org](https://repology.org/) and store on file system.
|
|
||||||
- Fetch Homebrew Formulae information from [HomeBrew Formulae](https://formulae.brew.sh)
|
|
||||||
- Compare Current Homebrew Formulae version numbers and those coming from Repology's API and Livecheck.
|
|
||||||
- Determine whether package has open PR.
|
|
||||||
- Display results.
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
- This project can be run automatically at set intervals via GitHub Actions.
|
|
||||||
- Executing `ruby printPackageUpdates.rb` from the command line will query
|
|
||||||
both the Repology and Homebrew APIs. Homebrew's current version of each
|
|
||||||
package will be compared to the latest version of the package, per Repology's response.
|
|
||||||
- Homebrew's livecheck is also queried for each package, and that data is parsed, if available.
|
|
||||||
- Checks whether there is open PR for package.
|
|
||||||
- Each outdated package will be displayed to the console like so:
|
|
||||||
- Note that some packages will not be included in the Livecheck response. Those will have a 'Livecheck latest:' value of 'Not found'.
|
|
||||||
|
|
||||||
```
|
|
||||||
Package: openclonk
|
|
||||||
Brew current: 7.0
|
|
||||||
Repology latest: 8.1
|
|
||||||
Livecheck latest: 8.1
|
|
||||||
Has Open PR?: true
|
|
||||||
|
|
||||||
Package: openjdk
|
|
||||||
Brew current: 13.0.2+8
|
|
||||||
Repology latest: 15.0.0.0~14
|
|
||||||
Livecheck latest: Not found.
|
|
||||||
Has Open PR?: false
|
|
||||||
|
|
||||||
Package: opentsdb
|
|
||||||
Brew current: 2.3.1
|
|
||||||
Repology latest: 2.4.0
|
|
||||||
Livecheck latest: 2.4.0
|
|
||||||
Has Open PR?: true
|
|
||||||
```
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
require_relative 'helpers/parsed_file'
|
require_relative "helpers/parsed_file"
|
||||||
require_relative 'helpers/brew_commands.rb'
|
require_relative "helpers/brew_commands.rb"
|
||||||
|
|
||||||
brew_commands = BrewCommands.new
|
brew_commands = BrewCommands.new
|
||||||
|
|
||||||
@ -11,10 +11,10 @@ File.foreach(outdated_pckgs_to_update) do |line|
|
|||||||
puts "\n bumping package: #{line_hash['name']} formula"
|
puts "\n bumping package: #{line_hash['name']} formula"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
bump_pr_response, bump_pr_status = brew_commands.bump_formula_pr(line_hash['name'], line_hash['download_url'], line_hash['checksum'])
|
bump_pr_response, bump_pr_status = brew_commands.bump_formula_pr(line_hash["name"], line_hash["download_url"], line_hash["checksum"])
|
||||||
puts "#{bump_pr_response}"
|
puts "#{bump_pr_response}"
|
||||||
rescue
|
rescue
|
||||||
puts "- An error occured whilst bumping package #{line_hash['name']} \n"
|
puts "- An error occured whilst bumping package #{line_hash["name"]} \n"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,133 +0,0 @@
|
|||||||
require 'net/http'
|
|
||||||
require 'json'
|
|
||||||
|
|
||||||
require_relative 'brew_commands'
|
|
||||||
require_relative 'homebrew_formula'
|
|
||||||
|
|
||||||
class ApiParser
|
|
||||||
def call_api(url)
|
|
||||||
puts "- Calling API #{url}"
|
|
||||||
uri = URI(url)
|
|
||||||
response = Net::HTTP.get(uri)
|
|
||||||
|
|
||||||
puts "- Parsing response"
|
|
||||||
JSON.parse(response)
|
|
||||||
end
|
|
||||||
|
|
||||||
def query_repology_api(last_package_in_response = '')
|
|
||||||
url = 'https://repology.org/api/v1/projects/' + last_package_in_response + '?inrepo=homebrew&outdated=1'
|
|
||||||
|
|
||||||
self.call_api(url)
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_repology_api()
|
|
||||||
puts "\n-------- Query outdated packages from Repology --------"
|
|
||||||
page_no = 1
|
|
||||||
puts "\n- Paginating repology api page: #{page_no}"
|
|
||||||
|
|
||||||
outdated_packages = self.query_repology_api('')
|
|
||||||
last_pacakge_index = outdated_packages.size - 1
|
|
||||||
response_size = outdated_packages.size
|
|
||||||
|
|
||||||
while response_size > 1 do
|
|
||||||
page_no += 1
|
|
||||||
puts "\n- Paginating repology api page: #{page_no}"
|
|
||||||
|
|
||||||
last_package_in_response = outdated_packages.keys[last_pacakge_index]
|
|
||||||
response = self.query_repology_api("#{last_package_in_response}/")
|
|
||||||
|
|
||||||
response_size = response.size
|
|
||||||
outdated_packages.merge!(response)
|
|
||||||
last_pacakge_index = outdated_packages.size - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "\n- #{outdated_packages.size} outdated pacakges identified by repology"
|
|
||||||
outdated_packages
|
|
||||||
end
|
|
||||||
|
|
||||||
def query_homebrew
|
|
||||||
puts "\n-------- Get Homebrew Formulas --------"
|
|
||||||
self.call_api('https://formulae.brew.sh/api/formula.json')
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_homebrew_formulas()
|
|
||||||
formulas = self.query_homebrew()
|
|
||||||
parsed_homebrew_formulas = {}
|
|
||||||
|
|
||||||
formulas.each do |formula|
|
|
||||||
parsed_homebrew_formulas[formula['name']] = {
|
|
||||||
"fullname" => formula["full_name"],
|
|
||||||
"oldname" => formula["oldname"],
|
|
||||||
"version" => formula["versions"]['stable'],
|
|
||||||
"download_url" => formula["urls"]['stable']['url'],
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
parsed_homebrew_formulas
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_packages(outdated_repology_packages, brew_formulas)
|
|
||||||
puts "\n-------- Verify Outdated Repology packages as Homebrew Formulas --------"
|
|
||||||
packages = {}
|
|
||||||
|
|
||||||
outdated_repology_packages.each do |package_name, repo_using_package|
|
|
||||||
# Identify homebrew repo
|
|
||||||
repology_homebrew_repo = repo_using_package.select { |repo| repo['repo'] == 'homebrew' }[0]
|
|
||||||
next if repology_homebrew_repo.empty?
|
|
||||||
|
|
||||||
latest_version = nil
|
|
||||||
|
|
||||||
# Identify latest version amongst repos
|
|
||||||
repo_using_package.each do |repo|
|
|
||||||
latest_version = repo['version'] if repo['status'] == 'newest'
|
|
||||||
end
|
|
||||||
|
|
||||||
repology_homebrew_repo['latest_version'] = latest_version if latest_version
|
|
||||||
homebrew_package_details = brew_formulas[repology_homebrew_repo['srcname']]
|
|
||||||
|
|
||||||
# Format package
|
|
||||||
packages[repology_homebrew_repo['srcname']] = format_package(homebrew_package_details, repology_homebrew_repo)
|
|
||||||
end
|
|
||||||
|
|
||||||
packages
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def format_package(homebrew_details, repology_details)
|
|
||||||
puts "- Formatting package: #{repology_details['srcname']}"
|
|
||||||
|
|
||||||
homebrew_formula = HomebrewFormula.new
|
|
||||||
new_download_url = homebrew_formula.generate_new_download_url(homebrew_details['download_url'], homebrew_details['version'], repology_details['latest_version'])
|
|
||||||
|
|
||||||
brew_commands = BrewCommands.new
|
|
||||||
livecheck_response = brew_commands.livecheck_check_formula(repology_details['srcname'])
|
|
||||||
has_open_pr = brew_commands.check_for_open_pr(repology_details['srcname'], new_download_url)
|
|
||||||
|
|
||||||
formatted_package = {
|
|
||||||
'fullname'=> homebrew_details['fullname'],
|
|
||||||
'repology_version' => repology_details['latest_version'],
|
|
||||||
'homebrew_version' => homebrew_details['version'],
|
|
||||||
'livecheck_latest_version' => livecheck_response['livecheck_latest_version'],
|
|
||||||
'current_download_url' => homebrew_details['download_url'],
|
|
||||||
'latest_download_url' => new_download_url,
|
|
||||||
'repology_latest_version' => repology_details['latest_version'],
|
|
||||||
'has_open_pr' => has_open_pr
|
|
||||||
}
|
|
||||||
|
|
||||||
formatted_package
|
|
||||||
end
|
|
||||||
|
|
||||||
def display_version_data(outdated_packages)
|
|
||||||
puts "==============Formatted outdated packages============\n"
|
|
||||||
|
|
||||||
outdated_packages.each do |package_name, package_details|
|
|
||||||
puts ""
|
|
||||||
puts "Package: #{package_name}"
|
|
||||||
puts "Brew current: #{package_details['homebrew_version']}"
|
|
||||||
puts "Repology latest: #{package_details['repology_version']}"
|
|
||||||
puts "Livecheck latest: #{package_details['livecheck_latest_version']}"
|
|
||||||
puts "Has Open PR?: #{package_details['has_open_pr']}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -16,12 +16,12 @@ class BrewCommands
|
|||||||
end
|
end
|
||||||
|
|
||||||
def parse_livecheck_response(livecheck_output)
|
def parse_livecheck_response(livecheck_output)
|
||||||
livecheck_output = livecheck_output.first.gsub(' ', '').split(/:|==>|\n/)
|
livecheck_output = livecheck_output.first.gsub(" ", "").split(/:|==>|\n/)
|
||||||
|
|
||||||
# eg: ["burp", "2.2.18", "2.2.18"]
|
# eg: ["burp", "2.2.18", "2.2.18"]
|
||||||
package_name, brew_version, latest_version = livecheck_output
|
package_name, brew_version, latest_version = livecheck_output
|
||||||
|
|
||||||
{'name' => package_name, 'current_brew_version' => brew_version, 'livecheck_latest_version' => latest_version}
|
{"name" => package_name, "current_brew_version" => brew_version, "livecheck_latest_version" => latest_version}
|
||||||
end
|
end
|
||||||
|
|
||||||
def bump_formula_pr(formula_name, url)
|
def bump_formula_pr(formula_name, url)
|
||||||
@ -48,7 +48,7 @@ class BrewCommands
|
|||||||
|
|
||||||
response = bump_formula_pr(formula_name, download_url)
|
response = bump_formula_pr(formula_name, download_url)
|
||||||
|
|
||||||
!response.include? 'Error: These open pull requests may be duplicates'
|
!response.include? "Error: These open pull requests may be duplicates"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
require 'net/http'
|
require "net/http"
|
||||||
require 'open-uri'
|
require "open-uri"
|
||||||
|
|
||||||
class HomebrewFormula
|
class HomebrewFormula
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
require 'fileutils'
|
|
||||||
|
|
||||||
class ParsedFile
|
|
||||||
|
|
||||||
def get_latest_file(directory)
|
|
||||||
puts "- retrieving latest file in directory: #{directory}"
|
|
||||||
Dir.glob("#{directory}/*").max_by(1) {|f| File.mtime(f)}[0]
|
|
||||||
end
|
|
||||||
|
|
||||||
def save_to(directory, data)
|
|
||||||
# Create directory if does not exist
|
|
||||||
FileUtils.mkdir_p directory unless Dir.exists?(directory)
|
|
||||||
|
|
||||||
puts "- Generating datetime stamp"
|
|
||||||
#Include time to the filename for uniqueness when fetching multiple times a day
|
|
||||||
date_time = Time.new.strftime("%Y-%m-%dT%H_%M_%S")
|
|
||||||
|
|
||||||
# Writing parsed data to file
|
|
||||||
puts "- Writing data to file"
|
|
||||||
File.write("#{directory}/#{date_time}.txt", data)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
require_relative 'helpers/api_parser'
|
require_relative "helpers/api_parser"
|
||||||
|
|
||||||
api_parser = ApiParser.new
|
api_parser = ApiParser.new
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user