# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # frozen_string_literal: true require 'net/http' require 'json' require_relative '../config/config' require 'term/ansicolor' module SlackBuilder extend Term::ANSIColor # Remote repository for a single package. class Repository # Request the latest tag in the given repository. def latest raise NotImplementedError end end # Reads the list fo tags from the GitHub API. class GitHub < Repository GITHUB_QUERY = <<~GQL query ($name: String!, $owner: String!) { repository(name: $name, owner: $owner) { refs(last: 10, refPrefix: "refs/tags/", orderBy: { field: TAG_COMMIT_DATE, direction: ASC }) { nodes { id, name } } } } GQL private_constant :GITHUB_QUERY def initialize(owner, name, version_transform = ->(v) { v.delete_prefix 'v' }) super() @owner = owner @name = name @version_transform = version_transform end def latest post_data = { 'query' => GITHUB_QUERY, 'variables' => { 'name' => @name, 'owner' => @owner } } uri = URI('https://api.github.com/graphql') response = Net::HTTP.post uri, post_data.to_json, { 'content-type' => 'application/json', 'authorization' => "Bearer #{CONFIG[:gh_token]}" } filter_versions_from_response JSON.parse(response.body) end private def filter_versions_from_response(response) response['data']['repository']['refs']['nodes'] .map { |node| @version_transform.call node['name'] } .compact .last end end # Request the latest version from the packagist API. class Packagist < Repository def initialize(vendor, name) super() @vendor = vendor @name = name end def latest `./bin/slackbuilder #{@vendor} #{@name}`.strip end end # Reads a remote LATEST file. class LatestText < Repository def initialize(latest_url) super() @latest_url = URI latest_url end def latest response = Net::HTTP.get @latest_url, { 'content-type' => 'text/plain' } response.strip end end module_function # Checks if there is a new version for the package and returns the latest # version if an update is available, otherwise returns nil. def check_for_latest(package_name, repository) package = find_package_info package_name latest_version = repository.latest if package.version == latest_version puts green "#{package_name} is up to date (Version #{package.version})." nil else puts red "#{package_name}: Current version is #{package.version}, #{latest_version} is available." latest_version end end private_class_method def find_package_info(package_name) package_path = Pathname.new Dir.glob("#{CONFIG[:repository]}/*/#{package_name}").first package_category = package_path.dirname.basename.to_s Package.parse("#{package_category}/#{package_name}", File.read("#{package_path}/#{package_name}.info")) end end