<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>The Ops Community ⚙️: Damilare Ogunmola</title>
    <description>The latest articles on The Ops Community ⚙️ by Damilare Ogunmola (@justdamilare).</description>
    <link>https://community.ops.io/justdamilare</link>
    <image>
      <url>https://community.ops.io/images/16rJbIPBoNo3A5TnSfhQxeribkg6fYQ5_g6U6DE-ddU/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL3Vz/ZXIvcHJvZmlsZV9p/bWFnZS83MDYvYzNm/MjljNTUtNjIwZi00/YjcxLTgwOWQtMjQ4/OThiMTJlYzA5Lmpw/ZWc</url>
      <title>The Ops Community ⚙️: Damilare Ogunmola</title>
      <link>https://community.ops.io/justdamilare</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://community.ops.io/feed/justdamilare"/>
    <language>en</language>
    <item>
      <title>Publish Go Packages with Goreleaser</title>
      <dc:creator>Damilare Ogunmola</dc:creator>
      <pubDate>Tue, 04 Oct 2022 22:46:21 +0000</pubDate>
      <link>https://community.ops.io/justdamilare/publish-go-packages-with-goreleaser-241n</link>
      <guid>https://community.ops.io/justdamilare/publish-go-packages-with-goreleaser-241n</guid>
      <description>&lt;p&gt;&lt;a href="https://goreleaser.com/"&gt;Goreleaser&lt;/a&gt; is awesome. It's a simple tool that allows you to release your &lt;em&gt;go&lt;/em&gt; packages. Recently, my team and I used it with a company wide CLI tool that we built. &lt;/p&gt;

&lt;p&gt;In this tutorial, we'll use &lt;em&gt;goreleaser&lt;/em&gt; to automate the release of a simple &lt;code&gt;go&lt;/code&gt; package. &lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;On macOS, to install &lt;em&gt;goreleaser&lt;/em&gt;, we can install using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install github.com/goreleaser/goreleaser@latest

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we use the popular &lt;a href="https://brew.sh/"&gt;&lt;em&gt;homebrew&lt;/em&gt;&lt;/a&gt; package manager for macOS and Linux with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install goreleaser/tap/goreleaser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Ubuntu Linux, we can use &lt;code&gt;apt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list
sudo apt update
sudo apt install goreleaser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More options can be found &lt;a href="https://goreleaser.com/install/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Package
&lt;/h2&gt;

&lt;p&gt;Create a new folder to house our project. Then initialize the modules with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go mod init main 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we create a file called &lt;code&gt;main.go&lt;/code&gt;. In &lt;code&gt;main.go&lt;/code&gt;, copy and paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This is a tutorial about Goreleaser!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initialize Goreleaser
&lt;/h2&gt;

&lt;p&gt;The next step is to setup &lt;em&gt;goreleaser&lt;/em&gt;. To do this, we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goreleaser init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates &lt;code&gt;.goreleaser.yaml&lt;/code&gt; file in our directory. We'll take a closer look at this file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update &lt;code&gt;.goreleaser.yaml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I have added a few more fields to the generated &lt;code&gt;.goreleaser.yaml&lt;/code&gt; file. We'll go through the important parts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;justdamilare&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mytool&lt;/span&gt;

&lt;span class="na"&gt;before&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hooks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;go mod tidy&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;go generate ./...&lt;/span&gt;

&lt;span class="na"&gt;builds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GO_VERSION=1.19&lt;/span&gt;
    &lt;span class="na"&gt;goos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;windows&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;darwin&lt;/span&gt;

&lt;span class="c1"&gt;# replaces architecture naming in the archive name&lt;/span&gt;
&lt;span class="na"&gt;archives&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;replacements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;darwin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Darwin&lt;/span&gt;
      &lt;span class="na"&gt;linux&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Linux&lt;/span&gt;
      &lt;span class="na"&gt;windows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Windows&lt;/span&gt;
      &lt;span class="na"&gt;386&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;i386&lt;/span&gt;
      &lt;span class="na"&gt;amd64&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x86_64&lt;/span&gt;

    &lt;span class="na"&gt;format_overrides&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;goos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;windows&lt;/span&gt;
        &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zip&lt;/span&gt;

&lt;span class="na"&gt;checksum&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name_template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;checksums.txt'&lt;/span&gt;

&lt;span class="na"&gt;snapshot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name_template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;incpatch&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}-next"&lt;/span&gt;

&lt;span class="na"&gt;changelog&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;sort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asc&lt;/span&gt;
  &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^docs:'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;^test:'&lt;/span&gt;

&lt;span class="c1"&gt;# upload binaries to gcloud bucket called `mytool`&lt;/span&gt;
&lt;span class="na"&gt;blobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gs&lt;/span&gt;
    &lt;span class="na"&gt;bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mytool&lt;/span&gt;
    &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;.Version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;

&lt;span class="c1"&gt;# generate homebrew-tap  &lt;/span&gt;
&lt;span class="na"&gt;brews&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;justdamilare&lt;/span&gt;
    &lt;span class="na"&gt;tap&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mytool&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;homebrew-tap&lt;/span&gt;
    &lt;span class="na"&gt;folder&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Formula&lt;/span&gt;
    &lt;span class="na"&gt;homepage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/justdamilare/mytool&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A simple go project&lt;/span&gt;
    &lt;span class="c1"&gt;# use custom download strategy in case the Github repository is private&lt;/span&gt;
    &lt;span class="na"&gt;download_strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GitHubPrivateRepositoryReleaseDownloadStrategy&lt;/span&gt;
    &lt;span class="na"&gt;custom_require&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;../custom_download_strategy"&lt;/span&gt;
    &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;system "#{bin}/mytool"&lt;/span&gt;
    &lt;span class="na"&gt;install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;bin.install "mytool"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It should be noted that if &lt;code&gt;homebrew-tap&lt;/code&gt; and &lt;code&gt;blobs&lt;/code&gt; are not needed, the sections can be removed. If &lt;code&gt;homebrew-tap&lt;/code&gt; is needed, a Githib repo called &lt;code&gt;homebrew-tap&lt;/code&gt; should be created also.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release Package
&lt;/h2&gt;

&lt;p&gt;Finally, we can release our packages. To do that, we need to create a tag for our release on Git. For example, to create a tag for version &lt;code&gt;0.1.0&lt;/code&gt;, we can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git tag v0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin v0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the directory with &lt;code&gt;main.go&lt;/code&gt;, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;goreleaser release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Goreleaser will build all the binaries. These binaries will be uploaded automatically to Github using the local GitHub credentials. The builds will also be located in a &lt;code&gt;/dist&lt;/code&gt; folder in the home directory. If the &lt;code&gt;brew&lt;/code&gt; publish method is included, a generated &lt;code&gt;*.rb&lt;/code&gt; file will also be in the &lt;code&gt;/dist&lt;/code&gt; folder. In case Goreleaser does not copy the generated &lt;code&gt;Formula&lt;/code&gt; to the &lt;code&gt;homebrew-tap&lt;/code&gt; repo automatically, it can be copied manually. You can see checkout how to publish the build to a private homebrew-tap &lt;a href="https://blog.devgenius.io/create-homebrew-taps-for-private-github-repos-44daf2f4cff8"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install goreleaser&lt;/li&gt;
&lt;li&gt;Create &lt;em&gt;go&lt;/em&gt; package&lt;/li&gt;
&lt;li&gt;Initialize Goreleaser with &lt;code&gt;goreleaser init&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;.goreleaser.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Release build by creating a tag with &lt;code&gt;git tag vX.X.X&lt;/code&gt; and then run &lt;code&gt;goreleaser release&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Create Homebrew Taps for Private GitHub Repos</title>
      <dc:creator>Damilare Ogunmola</dc:creator>
      <pubDate>Mon, 03 Oct 2022 22:29:11 +0000</pubDate>
      <link>https://community.ops.io/justdamilare/create-homebrew-taps-for-private-github-repos-af3</link>
      <guid>https://community.ops.io/justdamilare/create-homebrew-taps-for-private-github-repos-af3</guid>
      <description>&lt;p&gt;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 &lt;em&gt;to rule them all&lt;/em&gt; (like I had at my old job). I thought of building an easily extensible CLI tool which I did with &lt;em&gt;go&lt;/em&gt; and &lt;a href="https://github.com/spf13/cobra"&gt;cobra&lt;/a&gt;. To handle distribution to the engineers, we decided to use both &lt;code&gt;go install&lt;/code&gt; and &lt;a href="https://brew.sh/"&gt;&lt;em&gt;homebrew&lt;/em&gt;&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Homebrew is a very popular package manager for macOS and Linux users. Users can easily install new packages with &lt;code&gt;brew install [PACKAGE]&lt;/code&gt;. Homebrew handles the downloading and the installation of the packages to the appropriate directories and then creates symlinks to &lt;code&gt;/usr/local&lt;/code&gt; (on Intel machines).&lt;/p&gt;

&lt;p&gt;To create a Homebrew package, we create Ruby classes called &lt;em&gt;Formulas&lt;/em&gt;. A Formula looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Wget&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Formula&lt;/span&gt;
  &lt;span class="n"&gt;homepage&lt;/span&gt; &lt;span class="s2"&gt;"https://www.gnu.org/software/wget/"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="s2"&gt;"https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"&lt;/span&gt;
  &lt;span class="n"&gt;sha256&lt;/span&gt; &lt;span class="s2"&gt;"52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;install&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;"./configure"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--prefix=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;"make"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"install"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While adding an open-source package is fairly straightforward, doing the same with a private package involves a bit of hacking. &lt;/p&gt;

&lt;h2&gt;
  
  
  First Steps
&lt;/h2&gt;

&lt;p&gt;The first thing to do is create a Github release, if you use &lt;em&gt;go&lt;/em&gt;, I highly recommend using &lt;a href="https://github.com/goreleaser/goreleaser"&gt;&lt;em&gt;goreleaser&lt;/em&gt;&lt;/a&gt;. I wrote a tutorial on how to do that &lt;a href="https://justdamilare.github.io/blog/goreleaser"&gt;here&lt;/a&gt;. It truly makes releases in &lt;em&gt;go&lt;/em&gt; easy. If you're using another language, you should check out how to manage releases in GitHub &lt;a href="https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Homebrew Tap
&lt;/h2&gt;

&lt;p&gt;The next thing to do is to create a &lt;a href="https://docs.brew.sh/Taps"&gt;Homebrew tap&lt;/a&gt;. A Homebrew tap is a GitHub repository that houses our Formulas. To add non-Homebrew core taps, we need to add the taps locally to homebrew with &lt;code&gt;brew tap username/package&lt;/code&gt;. &lt;br&gt;
For us to use the single argument form of &lt;code&gt;brew tap&lt;/code&gt;, we need to follow the &lt;a href="https://docs.brew.sh/Taps#repository-naming-conventions-and-assumptions"&gt;naming convention&lt;/a&gt; and name our GitHub repo &lt;code&gt;homebrew-tap&lt;/code&gt; since the GitHub repo must start with &lt;code&gt;homebrew-&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Formula
&lt;/h2&gt;

&lt;p&gt;If you have a release already in Github, we can go ahead with creating the Formula. In our &lt;code&gt;homebrew-tap&lt;/code&gt; repo, we'll create a folder called &lt;code&gt;Formula&lt;/code&gt;. In the &lt;code&gt;Formula&lt;/code&gt; directory, we'll create a file called &lt;code&gt;mytool.rb&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Now, in our &lt;code&gt;Formula&lt;/code&gt;, we cannot use the standard way of downloading the packages since our package is hosted in a private repo. To do this we simply add a new download strategy like such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"formula"&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s2"&gt;"../custom_download_strategy.rb"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Wget&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Formula&lt;/span&gt;
  &lt;span class="n"&gt;homepage&lt;/span&gt; &lt;span class="s2"&gt;"https://www.gnu.org/software/wget/"&lt;/span&gt;
  &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="s2"&gt;"https://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:using&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;GitHubPrivateRepositoryReleaseDownloadStrategy&lt;/span&gt; 
  &lt;span class="n"&gt;sha256&lt;/span&gt; &lt;span class="s2"&gt;"52126be8cf1bddd7536886e74c053ad7d0ed2aa89b4b630f76785bac21695fcd"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;install&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;"./configure"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--prefix=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;"make"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"install"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;system&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/wget --help"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the addition of &lt;code&gt;, :using =&amp;gt; GitHubPrivateRepositoryReleaseDownloadStrategy&lt;/code&gt; on the third line of the class.&lt;/p&gt;

&lt;p&gt;In the root folder of &lt;code&gt;homebrew-tap&lt;/code&gt;, we'll create a new file called &lt;code&gt;custom_download_strategy.rb&lt;/code&gt;. Here, we'll add some code to support our download strategy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"download_strategy"&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GitHubPrivateRepositoryDownloadStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategy&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"utils/formatter"&lt;/span&gt;
  &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"utils/github"&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
    &lt;span class="n"&gt;parse_url_pattern&lt;/span&gt;
    &lt;span class="n"&gt;set_github_token&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_url_pattern&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;%r{https://github.com/([^/]+)/([^/]+)/(&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="sr"&gt;+)}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Invalid url pattern for GitHub Repository."&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@filepath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_url&lt;/span&gt;
    &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@github_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@github.com/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@filepath&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;resolved_url&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="n"&gt;curl_download&lt;/span&gt; &lt;span class="n"&gt;download_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;temporary_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_github_token&lt;/span&gt;
    &lt;span class="vi"&gt;@github_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"HOMEBREW_GITHUB_API_TOKEN"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vi"&gt;@github_token&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Environmental variable HOMEBREW_GITHUB_API_TOKEN is required."&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;validate_github_repository_access!&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;validate_github_repository_access!&lt;/span&gt;
    &lt;span class="c1"&gt;# Test access to the repository&lt;/span&gt;
    &lt;span class="no"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;GitHub&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTPNotFoundError&lt;/span&gt;
    &lt;span class="c1"&gt;# We only handle HTTPNotFoundError here,&lt;/span&gt;
    &lt;span class="c1"&gt;# becase AuthenticationFailedError is handled within util/github.&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;EOS&lt;/span&gt;&lt;span class="sh"&gt;
      HOMEBREW_GITHUB_API_TOKEN can not access the repository: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
      This token may not have permission to access the repository or the url of formula may be incorrect.
&lt;/span&gt;&lt;span class="no"&gt;    EOS&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# GitHubPrivateRepositoryReleaseDownloadStrategy downloads tarballs from GitHub&lt;/span&gt;
&lt;span class="c1"&gt;# Release assets. To use it, add&lt;/span&gt;
&lt;span class="c1"&gt;# `:using =&amp;gt; GitHubPrivateRepositoryReleaseDownloadStrategy` to the URL section of&lt;/span&gt;
&lt;span class="c1"&gt;# your formula. This download strategy uses GitHub access tokens (in the&lt;/span&gt;
&lt;span class="c1"&gt;# environment variables HOMEBREW_GITHUB_API_TOKEN) to sign the request.&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GitHubPrivateRepositoryReleaseDownloadStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;GitHubPrivateRepositoryDownloadStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_url_pattern&lt;/span&gt;
    &lt;span class="n"&gt;url_pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;%r{https://github.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;&lt;span class="sr"&gt;+)}&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vi"&gt;@url&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="n"&gt;url_pattern&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Invalid url pattern for GitHub Release."&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="vi"&gt;@url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url_pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;download_url&lt;/span&gt;
    &lt;span class="s2"&gt;"https://&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@github_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@api.github.com/repos/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/releases/assets/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;asset_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;resolved_url&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="c1"&gt;# HTTP request header `Accept: application/octet-stream` is required.&lt;/span&gt;
    &lt;span class="c1"&gt;# Without this, the GitHub API will respond with metadata, not binary.&lt;/span&gt;
    &lt;span class="n"&gt;curl_download&lt;/span&gt; &lt;span class="n"&gt;download_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"--header"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/octet-stream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;to: &lt;/span&gt;&lt;span class="n"&gt;temporary_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;asset_id&lt;/span&gt;
    &lt;span class="vi"&gt;@asset_id&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;resolve_asset_id&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;resolve_asset_id&lt;/span&gt;
    &lt;span class="n"&gt;release_metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fetch_release_metadata&lt;/span&gt;
    &lt;span class="n"&gt;assets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;release_metadata&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"assets"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vi"&gt;@filename&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;CurlDownloadStrategyError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Asset file not found."&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;

    &lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_release_metadata&lt;/span&gt;
    &lt;span class="no"&gt;GitHub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@tag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should have the following folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── homebrew-tap
│   ├── Formula
│   │   ├── mytool.rb
└── custom_download_strategy.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://github.com/settings/tokens"&gt;here&lt;/a&gt;. The token needs to have &lt;code&gt;repo&lt;/code&gt; permissions. We need to export the token as &lt;code&gt;HOMEBREW_GITHUB_API_TOKEN&lt;/code&gt;. To export the token, we run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export HOMEBREW_GITHUB_API_TOKEN=&amp;lt;GITHUB_TOKEN&amp;gt;
# if you're using fish shell like me, run `set -x HOMEBREW_GITHUB_API_TOKEN &amp;lt;GITHUB_TOKEN&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we can run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install username/homebrew-tap/mytool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This automatically adds the homebrew tap and install our tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a GitHub release with the binaries. This can be done very easily with &lt;em&gt;goreleaser&lt;/em&gt; in the case of &lt;em&gt;go&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Create a GitHub repo called &lt;code&gt;homebrew-tap&lt;/code&gt;. An example is &lt;a href="https://github.com/justdamilare/homebrew-tap"&gt;here&lt;/a&gt;.

&lt;ul&gt;
&lt;li&gt;Create a &lt;code&gt;Formula&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;In the root of the repo, create a file called &lt;code&gt;custom_download_strategy.rb&lt;/code&gt;. The contents are shown above&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;Formula&lt;/code&gt; folder, create a ruby file with the name of your tool like &lt;code&gt;mytool.rb&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create a GitHub token &lt;a href="https://github.com/settings/tokens"&gt;here&lt;/a&gt; and give &lt;code&gt;repo&lt;/code&gt; permissions to the token. &lt;/li&gt;
&lt;li&gt;Export the token with &lt;code&gt;export HOMEBREW_GITHUB_API_TOKEN=&amp;lt;GITHUB_TOKEN&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install the tool with brew using &lt;code&gt;brew install username/homebrew-tap/mytool&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>homebrew</category>
      <category>ruby</category>
      <category>github</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
