Created
March 5, 2022 10:29
-
-
Save brownhash/05ce5fb14493986c275b42e7c394c820 to your computer and use it in GitHub Desktop.
Private HomeBrew tap formula
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# formula/lib/private.rb | |
require "download_strategy" | |
# GitHubPrivateRepositoryDownloadStrategy downloads contents from GitHub | |
# Private Repository. To use it, add | |
# `:using => :github_private_repo` to the URL section of | |
# your formula. This download strategy uses GitHub access tokens (in the | |
# environment variables `HOMEBREW_GITHUB_API_TOKEN`) to sign the request. This | |
# strategy is suitable for corporate use just like S3DownloadStrategy, because | |
# it lets you use a private GitHub repository for internal distribution. It | |
# works with public one, but in that case simply use CurlDownloadStrategy. | |
class GitHubPrivateRepositoryDownloadStrategy < CurlDownloadStrategy | |
require "utils/formatter" | |
require "utils/github" | |
def initialize(url, name, version, **meta) | |
super | |
parse_url_pattern | |
set_github_token | |
end | |
def parse_url_pattern | |
unless match = url.match(%r{https://github.com/([^/]+)/([^/]+)/(\S+)}) | |
raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Repository." | |
end | |
_, @owner, @repo, @filepath = *match | |
end | |
def download_url | |
"https://#{@github_token}@github.com/#{@owner}/#{@repo}/#{@filepath}" | |
end | |
private | |
def _fetch(url:, resolved_url:, timeout:) | |
curl_download download_url, to: temporary_path | |
end | |
def set_github_token | |
@github_token = ENV["HOMEBREW_GITHUB_API_TOKEN"] | |
unless @github_token | |
raise CurlDownloadStrategyError, "Environmental variable HOMEBREW_GITHUB_API_TOKEN is required." | |
end | |
validate_github_repository_access! | |
end | |
def validate_github_repository_access! | |
# Test access to the repository | |
GitHub.repository(@owner, @repo) | |
rescue GitHub::HTTPNotFoundError | |
# We only handle HTTPNotFoundError here, | |
# becase AuthenticationFailedError is handled within util/github. | |
message = <<~EOS | |
HOMEBREW_GITHUB_API_TOKEN can not access the repository: #{@owner}/#{@repo} | |
This token may not have permission to access the repository or the url of formula may be incorrect. | |
EOS | |
raise CurlDownloadStrategyError, message | |
end | |
end | |
# GitHubPrivateRepositoryReleaseDownloadStrategy downloads tarballs from GitHub | |
# Release assets. To use it, add `:using => :github_private_release` to the URL section | |
# of your formula. This download strategy uses GitHub access tokens (in the | |
# environment variables HOMEBREW_GITHUB_API_TOKEN) to sign the request. | |
class GitHubPrivateRepositoryReleaseDownloadStrategy < GitHubPrivateRepositoryDownloadStrategy | |
def initialize(url, name, version, **meta) | |
super | |
end | |
def parse_url_pattern | |
url_pattern = %r{https://github.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(\S+)} | |
unless @url =~ url_pattern | |
raise CurlDownloadStrategyError, "Invalid url pattern for GitHub Release." | |
end | |
_, @owner, @repo, @tag, @filename = *@url.match(url_pattern) | |
end | |
def download_url | |
"https://api.github.com/repos/#{@owner}/#{@repo}/releases/assets/#{asset_id}" | |
end | |
private | |
def _fetch(url:, resolved_url:, timeout:) | |
# HTTP request header `Accept: application/octet-stream` is required. | |
# Without this, the GitHub API will respond with metadata, not binary. | |
curl_download download_url, "--header", "Accept: application/octet-stream", "--header", "Authorization: token #{@github_token}", to: temporary_path | |
end | |
def asset_id | |
@asset_id ||= resolve_asset_id | |
end | |
def resolve_asset_id | |
release_metadata = fetch_release_metadata | |
assets = release_metadata["assets"].select { |a| a["name"] == @filename } | |
raise CurlDownloadStrategyError, "Asset file not found." if assets.empty? | |
assets.first["id"] | |
end | |
def fetch_release_metadata | |
release_url = "https://api.github.com/repos/#{@owner}/#{@repo}/releases/tags/#{@tag}" | |
GitHub::API.open_rest(release_url) | |
end | |
end | |
class DownloadStrategyDetector | |
class << self | |
module Compat | |
def detect_from_symbol(symbol) | |
case symbol | |
when :github_private_repo | |
GitHubPrivateRepositoryDownloadStrategy | |
when :github_private_release | |
GitHubPrivateRepositoryReleaseDownloadStrategy | |
else | |
super(symbol) | |
end | |
end | |
end | |
prepend Compat | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# formula/tool.rb | |
require_relative "lib/private" | |
class ToolName < Formula | |
desc "Tap for a private Github repository" | |
homepage "https://github.com/owner/repository" | |
version "1.0.0" | |
# For MacOs Intel based systems | |
if OS.mac? && Hardware::CPU.intel? | |
url "https://github.com/owner/repository/releases/download/v1.0.0/tool_darwin_amd64.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy | |
sha256 "ba833d556af4a47923fcb1234ca31492369808eea2165c733f5b5fd25c3885a7" | |
end | |
# For MacOs M1 based systems | |
if OS.mac? && Hardware::CPU.arm? | |
url "https://github.com/owner/repository/releases/download/v1.0.0/tool_darwin_arm64.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy | |
sha256 "4c5d45c7ad41cd217aa9f1bc7654921161a2554cb3e5084f3188ffd347ccc7b9" | |
end | |
# For Linux X64 based systems | |
if OS.linux? && Hardware::CPU.intel? | |
url "https://github.com/owner/repository/releases/download/v1.0.0/tool_linux_amd64.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy | |
sha256 "801e95a44248765a111qab0d650321f286cd6bf506c88ae571db3d0624dac37e" | |
end | |
def install | |
bin.install "tool" | |
end | |
test do | |
system "#{bin}/tool --version && #{bin}/tool --help" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment