-
-
Save ZPascal/b21c652b811872b3f56db9d54d61d6c6 to your computer and use it in GitHub Desktop.
require "formula" | |
require_relative "lib/private_strategy" | |
class Hoge < Formula | |
homepage "https://github.com/yourcompany/hoge" | |
url "https://github.com/yourcompany/hoge/releases/download/v0.1.0/hoge_v0.1.0_darwin_amd64.tar.gz", :using => GitHubPrivateRepositoryReleaseDownloadStrategy | |
sha256 "6de411ff3e4b1658a413dd6181fcXXXXXXXXXXXXXXXXXXXX" | |
head "https://github.com/yourcompany/hoge.git" | |
version "0.1.0" | |
def install | |
bin.install "hoge" | |
end | |
end |
brew tap yourcompany/tap [email protected]:yourcompany/homebrew-tap.git | |
export HOMEBREW_GITHUB_API_TOKEN=xxx | |
brew install hoge |
# Save this file as `lib/private_strategy.rb` | |
# Add `require_relative "lib/private_strategy"` to your formula. | |
# | |
# This is based on the following, with minor fixes. | |
# https://github.com/Homebrew/brew/blob/193af1442f6b9a19fa71325160d0ee2889a1b6c9/Library/Homebrew/compat/download_strategy.rb#L48-L157 | |
# BSD 2-Clause License | |
# | |
# Copyright (c) 2009-present, Homebrew contributors | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are met: | |
# | |
# * Redistributions of source code must retain the above copyright notice, this | |
# list of conditions and the following disclaimer. | |
# | |
# * Redistributions in binary form must reproduce the above copyright notice, | |
# this list of conditions and the following disclaimer in the documentation | |
# and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
# GitHubPrivateRepositoryDownloadStrategy downloads contents from GitHub | |
# Private Repository. To use it, add | |
# `:using => GitHubPrivateRepositoryDownloadStrategy` 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::API::HTTPNotFoundError | |
# We switched to GitHub::API::HTTPNotFoundError, | |
# because we can now handle bad credentials messages | |
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 => GitHubPrivateRepositoryReleaseDownloadStrategy` 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://#{@github_token}@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", 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) | |
GitHub.get_release(@owner, @repo, @tag) | |
end | |
end |
Hi, sorry for the late reply, the curl
command with the suggested format is working, however I don't know how to translate that to the URL in my cask definition.
Edit: Finally made it work, it seems I was so into it that I missed some parts of the url. Anyways you nailed it, thanks for the support!
Hi @alejakun, great to hear that now everything works as aspected.
I am not sure this is the exact place for it but has anyone using this seen an error Error: can't modify frozen class
while using these scripts? I am running a brew install for a private github repo when I get this error. My google-fu is weak so taking a shot in the dark in case it is more widespread.
Hi @mtintes, could you please post the output of the --debug
flag of the installation command?
One of coworkers ended up finding an answer (sort of). This was the original error. konductor is a cli written in go in this case.
➜ brew install konductor --debug --verbose
/opt/homebrew/Library/Homebrew/brew.rb (Formulary::FormulaLoader): loading /opt/homebrew/Library/Taps/<org>/homebrew-konductor/formula/konductor.rb
/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.4\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 12.5.1\)\ curl/7.79.1 --header Accept-Language:\ en --retry 3 --location https://api.github.com/repos/<org>/konductor --header Accept:\ application/vnd.github\+json --write-out '
'\%\{http_code\} --header Authorization:\ token\ ****** --dump-header /private/tmp/github_api_headers20221005-47324-1n0405m
/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.4\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 12.5.1\)\ curl/7.79.1 --header Accept-Language:\ en --retry 3 --location --silent --head --request GET https://github.com/<org>/konductor/releases/download/v1.17.9/konductor-osx-amd64.tar.gz
==> Downloading https://github.com/<org>/konductor/releases/download/v1.17.9/konductor-osx-amd64.tar.gz
/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.4\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 12.5.1\)\ curl/7.79.1 --header Accept-Language:\ en --retry 3 --location https://api.github.com/repos/<org>/konductor/releases/tags/v1.17.9 --header Accept:\ application/vnd.github\+json --write-out '
'\%\{http_code\} --header Authorization:\ token\ ****** --dump-header /private/tmp/github_api_headers20221005-47324-f7o4v1
/opt/homebrew/Library/Homebrew/shims/shared/curl --disable --cookie /dev/null --globoff --show-error --user-agent Homebrew/3.6.4\ \(Macintosh\;\ arm64\ Mac\ OS\ X\ 12.5.1\)\ curl/7.79.1 --header Accept-Language:\ en --fail --retry 3 --location --remote-time --output /Users/miketintes/Library/Caches/Homebrew/downloads/e21e5b9112fcd59c4caec2c40316e0fe0c08cab973ba491d5ccd1460569812b8--konductor-osx-amd64.tar.gz.incomplete https://******@api.github.com/repos/<org>/konductor/releases/assets/79035814 --header Accept:\ application/octet-stream
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 30.6M 100 30.6M 0 0 13.2M 0 0:00:02 0:00:02 --:--:-- 16.4M
==> Verifying checksum for 'e21e5b9112fcd59c4caec2c40316e0fe0c08cab973ba491d5ccd1460569812b8--konductor-osx-amd64.tar.gz'
==> Installing konductor from <org>/konductor
/opt/homebrew/Library/Homebrew/brew.rb (Formulary::TapLoader): loading /opt/homebrew/Library/Taps/<org>/homebrew-konductor/Formula/konductor.rb
Error: can't modify frozen class
/opt/homebrew/Library/Taps/<org>/homebrew-konductor/Formula/lib/private_strategy.rb:98:in `<class:GitHubPrivateRepositoryReleaseDownloadStrategy>'
/opt/homebrew/Library/Taps/<org>/homebrew-konductor/Formula/lib/private_strategy.rb:97:in `<top (required)>'
/opt/homebrew/Library/Taps/<org>/homebrew-konductor/Formula/konductor.rb:2:in `require_relative'
/opt/homebrew/Library/Taps/<org>/homebrew-konductor/Formula/konductor.rb:2:in `block in load_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:90:in `module_eval'
/opt/homebrew/Library/Homebrew/formulary.rb:90:in `block in load_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:102:in `load_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:122:in `load_formula_from_path'
/opt/homebrew/Library/Homebrew/formulary.rb:321:in `load_file'
/opt/homebrew/Library/Homebrew/formulary.rb:478:in `load_file'
/opt/homebrew/Library/Homebrew/formulary.rb:311:in `klass'
/opt/homebrew/Library/Homebrew/formulary.rb:306:in `get_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:468:in `get_formula'
/opt/homebrew/Library/Homebrew/formulary.rb:560:in `factory'
/opt/homebrew/Library/Homebrew/formula_installer.rb:374:in `install'
/opt/homebrew/Library/Homebrew/upgrade.rb:212:in `install_formula'
/opt/homebrew/Library/Homebrew/install.rb:333:in `install_formula'
/opt/homebrew/Library/Homebrew/install.rb:323:in `block in install_formulae'
/opt/homebrew/Library/Homebrew/install.rb:322:in `each'
/opt/homebrew/Library/Homebrew/install.rb:322:in `install_formulae'
/opt/homebrew/Library/Homebrew/cmd/install.rb:226:in `install'
/opt/homebrew/Library/Homebrew/brew.rb:95:in `<main>'
We had to copy a bunch of old code from homebrew that looks like it got deprecated and put that in the private strategy. This is a copy of that. No idea if that is the best path since neither of us does anything with ruby.
For anyone recently having issues with this, see Homebrew/brew#15169. CurlDownloadStrategy
changed a bit.
This fix worked for me.
For anyone recently having issues with this, see Homebrew/brew#15169.
CurlDownloadStrategy
changed a bit.This fix worked for me.
It worked for me too. Thanks for sharing.
I've started a test on my side to download a file from a private repository directly via
curl
. I've used the following commandcurl https://<TOKEN>@raw.githubusercontent.com/<OWNER>/<REPO>/<BRANCH>/<PATH TO FILE> --output <NAME OF THE FILE>
. Could you please try it out? I think it should be possible, to use the URL at the end directly inside the cask.