I really like ki
, but I didn’t want to run the shell script every time. Other folks felt the same, so I ended up writing this Homebrew formula. Here’s an abbreviated version of how I did it.
How does Homebrew work?
Homebrew is a package manager and artifact builder. All of the programs/tools/packages that core Homebrew knows about are located at brew --repo homebrew/core
repository.
The repository contains instructions (called formulae) for the Homebrew build servers to make and test the programs. Once the build servers build the formulae, they store the result as “bottles”. When you run brew install <formula>
, you download the bottle along with any other dependency.
Creating the Ki formula
Getting started is super easy because Homebrew has a command to generate a template formula. In my case, I ran the following by pointing at the released version of ki
.
brew create https://github.com/Kotlin/kotlin-interactive-shell/archive/refs/tags/v0.3.3.tar.gz
… which resulted in (more-or-less) this:
class KotlinInteractiveShell < Formula
desc "Kotlin Language Interactive Shell"
url "https://github.com/Kotlin/kotlin-interactive-shell/archive/refs/tags/v0.3.3.tar.gz"
sha256 "46913b17c85711213251948342d0f4d0fec7dc98dd11c1f24eedb0409338e273"
license "Apache-2.0"
def install
# ...
end
test do
# ...
end
end
I renamed the generated kotlin-interactive-shell.rb
file to ki.rb
and changed the KotlinInteractiveShell
class name to Ki
because I wanted the command line tool to be ki
.
Build Ki locally (think globally)
The only build dependency is Maven, and the runtime is Java, so those are the only two packages I needed to call out.
depends_on "maven" => :build
depends_on "openjdk"
I then took the build instructions from the ki
README and plopped them into the install block. I put the Java artifact into the libexec
folder to avoid name collisions, which I learned about from this StackExchange post.
Homebrew has some nice pre-built commands including one for wiring up JAR files, so making the command line script is also very little work.
def install
system "mvn", "-DskipTests", "package"
libexec.install "lib/ki-shell.jar"
bin.write_jar_script libexec/"ki-shell.jar", "ki"
end
To test out my script, I made my laptop pretend it was a Homebrew build server, and built the package.
brew install --build-from-source ki
I didn’t actually write the correct code the first time, so I ran the build command with an additional --debug
flag that let me try things out in the build environment. I spent most of my time doing this.
Test it out
The test
block of the formula is a very basic check to see if the tool runs at all. I tried to not over-think it.
When you run the ki
shell, and then close it, this is the output.
$ ki
ki-shell 0.3/1.4.32
type :h for help
[0] :q
Bye!
For my test, I just wanted to make sure the initial “ki-shell” and final “Bye!” message appeared.
test do
output = pipe_output(bin/"ki", ":q")
assert_match "ki-shell", output
assert_match "Bye!", output
end
I then tested with brew test ki
. My first draft of the test
also didn’t work, so I used the --debug
flag here too.
When the test worked, I made sure the automated auditor passed.
brew audit --strict --online ki
Open the pull request
Last, but not least I opened up a pull request against the Homebrew/homebrew-core repo and watched the tests run.
Once all of the tests passed, and I got sign-off from the reviewers, the formula was merged, and Homebrew built ki
for the various macOS environments.
I ran brew install ki
, and was very excited to see it work.
Look around and borrow
Most of everything I did, I figured out by looking at other formulae, trial, and error. If you ever decide to write a formula, you might want to do the same.