homebrew

プライベートなツールをGitHub Releaseにおいてbrewで配布していたのがエラーになった件の対処メモ

GitHubのプライベートリポジトリのReleaseにおいてHomebrewのtapをつかってインストールできるようにしていたところ、以下がエラーが出るようになった。

==> Installing XXXX from xxxx/xxxx

Error: An exception occurred within a child process:
MethodDeprecatedError: Calling GitHubPrivateRepositoryReleaseDownloadStrategy is disabled! Use a vendored GitHubPrivateRepositoryReleaseDownloadStrategy in your own formula or tap (using require_relative) instead.

GitHubPrivateRepositoryReleaseDownloadStrategyは使えなくなったのでえ、自分のtapで読みこんで使って、と書かれている気がする。


対処した内容


download_strategy.rbの配置

自前のtapの lib/download_strategy.rb を配置


lib/download_strategy.rb

# 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:)
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://#{@github_token}@api.github.com/repos/#{@owner}/#{@repo}/releases/assets/#{asset_id}"
end

private

def _fetch(url:, resolved_url:)
# 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.open_api(release_url)
end
end



Formulaの修正

各Formulaの先頭に以下を追加

require_relative '../lib/download_strategy'


作業メモ

以下の変更で、非推奨になって、コードの位置が移動した。

https://github.com/Homebrew/brew/pull/5112

以下の変更で、コードが消えた。

https://github.com/Homebrew/brew/pull/5598

消えたファイルの中身

https://github.com/Homebrew/brew/blob/193af1442f6b9a19fa71325160d0ee2889a1b6c9/Library/Homebrew/compat/download_strategy.rb


修正方法


  1. 使いたいストラテジーをコピーしてもってくる。


  2. odisableの呼び出しを削除する

  3. もってきたものを各Formulaで読み込む

消えたストラテジー


  • S3DownloadStrategy

  • GitHubPrivateRepositoryDownloadStrategy

  • GitHubPrivateRepositoryReleaseDownloadStrategy

  • ScpDownloadStrategy

マージするまえに、特定のブランチの作業を確認してもらう方法

brew tap [リポジトリ名]/[tap名]

cd /usr/local/Homebrew/Library/Taps/[リポジトリ名]/homebrew-[tap名]
git fetch origin [作業ブランチ名]
git checkout FETCH_HEAD
brew install [確認するformula名]