From 0279dda595248d6e0bc288387619d4784a1b8704 Mon Sep 17 00:00:00 2001 From: Sean Molenaar Date: Thu, 13 Aug 2020 16:17:47 +0200 Subject: [PATCH] add cask pre-release check --- Library/Homebrew/cask/audit.rb | 64 ++++++++++++++++++++++++- Library/Homebrew/dev-cmd/audit.rb | 28 +++++++---- Library/Homebrew/utils/shared_audits.rb | 25 ++++++++++ 3 files changed, 105 insertions(+), 12 deletions(-) diff --git a/Library/Homebrew/cask/audit.rb b/Library/Homebrew/cask/audit.rb index f9628b1d4c..b0b8b115a8 100644 --- a/Library/Homebrew/cask/audit.rb +++ b/Library/Homebrew/cask/audit.rb @@ -54,8 +54,12 @@ module Cask check_latest_with_auto_updates check_stanza_requires_uninstall check_appcast_contains_version - check_github_repository check_gitlab_repository + check_gitlab_repository_archived + check_gitlab_prerelease_version + check_github_repository + check_github_repository_archived + check_github_prerelease_version check_bitbucket_repository self rescue => e @@ -447,7 +451,60 @@ module Cask " the version number '#{adjusted_version_stanza}':\n#{appcast_contents}" end + def check_github_prerelease_version + odebug "Auditing GitHub prerelease" + user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @online + return if user.nil? + + metadata = SharedAudits.github_release_data(user, repo, cask.version) + return if metadata.nil? + + if metadata["prerelease"] + problem "#{cask.version} is a GitHub prerelease" + elsif metadata["draft"] + problem "#{cask.version} is a GitHub draft" + end + end + + def check_gitlab_prerelease_version + user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @online + return if user.nil? + + odebug "Auditing GitLab prerelease" + + metadata = SharedAudits.gitlab_release_data(user, repo, cask.version) + return if metadata.nil? + + problem "#{cask.version} is a GitLab prerelease" if Date.parse(metadata["released_at"]) > Date.today + end + + def check_github_repository_archived + user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @online + return if user.nil? + + odebug "Auditing GitHub repo archived" + + metadata = SharedAudits.github_repo_data(user, repo) + return if metadata.nil? + + problem "GitHub repo is archived" if metadata["archived"] + end + + def check_gitlab_repository_archived + user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) if @online + return if user.nil? + + odebug "Auditing GitLab repo archived" + + metadata = SharedAudits.gitlab_repo_data(user, repo) + return if metadata.nil? + + problem "GitLab repo is archived" if metadata["archived"] + end + def check_github_repository + return unless @new_cask + user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) return if user.nil? @@ -458,6 +515,8 @@ module Cask end def check_gitlab_repository + return unless @new_cask + user, repo = get_repo_data(%r{https?://gitlab\.com/([^/]+)/([^/]+)/?.*}) return if user.nil? @@ -468,6 +527,8 @@ module Cask end def check_bitbucket_repository + return unless @new_cask + user, repo = get_repo_data(%r{https?://bitbucket\.org/([^/]+)/([^/]+)/?.*}) return if user.nil? @@ -479,7 +540,6 @@ module Cask def get_repo_data(regex) return unless online? - return unless new_cask? _, user, repo = *regex.match(cask.url.to_s) _, user, repo = *regex.match(cask.homepage) unless user diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb index c03574b4a7..5dde260cca 100644 --- a/Library/Homebrew/dev-cmd/audit.rb +++ b/Library/Homebrew/dev-cmd/audit.rb @@ -701,6 +701,8 @@ module Homebrew "libepoxy" => "1.5", }.freeze + GITLAB_PRERELEASE_ALLOWLIST = {}.freeze + GITHUB_PRERELEASE_ALLOWLIST = { "cbmc" => "5.12.6", "elm-format" => "0.8.3", @@ -802,6 +804,17 @@ module Homebrew return if stable_url_minor_version.even? problem "#{stable.version} is a development release" + + when %r{https?://gitlab\.com/([\w-]+)/([\w-]+)} + owner = Regexp.last_match(1) + repo = Regexp.last_match(2) + + return unless @online && (release = SharedAudits.gitlab_release_data(owner, repo, stable.version)) + + release_date = Date.parse(release["released_at"]) + if release_date > Date.today && (GITLAB_PRERELEASE_ALLOWLIST[formula.name] != formula.version) + problem "#{stable.version} is a GitLab prerelease" + end when %r{^https://github.com/([\w-]+)/([\w-]+)} owner = Regexp.last_match(1) repo = Regexp.last_match(2) @@ -813,17 +826,12 @@ module Homebrew .second tag ||= formula.stable.specs[:tag] - begin - if @online && (release = GitHub.open_api("#{GitHub::API_URL}/repos/#{owner}/#{repo}/releases/tags/#{tag}")) - if release["prerelease"] && (GITHUB_PRERELEASE_ALLOWLIST[formula.name] != formula.version) - problem "#{tag} is a GitHub prerelease" - elsif release["draft"] - problem "#{tag} is a GitHub draft" - end + if @online && (release = SharedAudits.github_release_data(owner, repo, tag)) + if release["prerelease"] && (GITHUB_PRERELEASE_ALLOWLIST[formula.name] != formula.version) + problem "#{tag} is a GitHub prerelease" + elsif release["draft"] + problem "#{tag} is a GitHub draft" end - rescue GitHub::HTTPNotFoundError - # No-op if we can't find the release. - nil end end end diff --git a/Library/Homebrew/utils/shared_audits.rb b/Library/Homebrew/utils/shared_audits.rb index 7e13fe0afc..09a48074f9 100644 --- a/Library/Homebrew/utils/shared_audits.rb +++ b/Library/Homebrew/utils/shared_audits.rb @@ -17,6 +17,16 @@ module SharedAudits nil end + def github_release_data(user, repo, tag) + id = "#{user}/#{repo}/#{tag}" + @github_release_data ||= {} + @github_release_data[id] ||= GitHub.open_api("#{GitHub::API_URL}/repos/#{user}/#{repo}/releases/tags/#{tag}") + + @github_release_data[id] + rescue GitHub::HTTPNotFoundError + nil + end + def gitlab_repo_data(user, repo) @gitlab_repo_data ||= {} @gitlab_repo_data["#{user}/#{repo}"] ||= begin @@ -29,6 +39,21 @@ module SharedAudits @gitlab_repo_data["#{user}/#{repo}"] end + def gitlab_release_data(user, repo, tag) + id = "#{user}/#{repo}/#{tag}" + @gitlab_release_data ||= {} + @gitlab_release_data[id] ||= begin + out, _, status= curl_output( + "--request", "GET", "https://gitlab.com/api/v4/projects/#{user}%2F#{repo}/releases/#{tag}" + ) + return unless status.success? + + JSON.parse(out) + end + + @gitlab_release_data[id] + end + def github(user, repo) metadata = github_repo_data(user, repo)