Create Homebrew Taps for Private GitHub Repos

This page summarizes the projects mentioned and recommended in the original post on dev.to

Our great sponsors
  • WorkOS - The modern identity platform for B2B SaaS
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • SaaSHub - Software Alternatives and Reviews
  • cobra

    A Commander for modern Go CLI interactions

  • I started a new job in July 2022. While the developer experience is great, one of the things that I missed at my new job was a CLI to rule them all (like I had at my old job). I thought of building an easily extensible CLI tool which I did with go and cobra. To handle distribution to the engineers, we decided to use both go install and homebrew.

  • goreleaser

    Deliver Go binaries as fast and easily as possible

  • The first thing to do is create a Github release, if you use go, I highly recommend using goreleaser. I wrote a tutorial on how to do that here. It truly makes releases in go easy. If you're using another language, you should check out how to manage releases in GitHub here.

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
  • tokens

  • We're almost done. To install our tool via Homebrew, we need to export a Github token that provides access to our private repos. A new token can be created here. The token needs to have repo permissions. We need to export the token as HOMEBREW_GITHUB_API_TOKEN. To export the token, we run:

  • homebrew-tap

    A Homebrew Tap (by justdamilare)

  • Create a GitHub repo called homebrew-tap. An example is here. Create a Formula folder. In the root of the repo, create a file called custom_download_strategy.rb. The contents are shown above In the Formula folder, create a ruby file with the name of your tool like mytool.rb

  • Puts Debuggerer

    Ruby library for improved puts debugging, automatically displaying bonus useful information such as source line number and source code.

  • require "download_strategy" 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, timeout: timeout 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 => 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, timeout: timeout 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 GitHub.get_release(@owner, @repo, @tag) end end

  • HomeBrew

    🍺 The missing package manager for macOS (or Linux)

  • I started a new job in July 2022. While the developer experience is great, one of the things that I missed at my new job was a CLI to rule them all (like I had at my old job). I thought of building an easily extensible CLI tool which I did with go and cobra. To handle distribution to the engineers, we decided to use both go install and homebrew.

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts