kamal icon indicating copy to clipboard operation
kamal copied to clipboard

Release the CLI as downloadable binary

Open lambrospetrou opened this issue 2 years ago • 14 comments
trafficstars

It would be nice to be able to download and use the tool as a CLI without depending on Ruby being on the system (requiring gem install).

Any plans on releasing this as a standalone CLI tool?

lambrospetrou avatar Mar 01 '23 12:03 lambrospetrou

Please Do Investigate!

dhh avatar Mar 01 '23 14:03 dhh

I just stumbled upon mrsk so might not be able to see the bigger picture here (ie. making some incorrect assumptions) but what about containerizing mrsk itself? You might even be able to publish it as a Docker extension, integrating it into Docker Desktop. Assuming Docker is a core dependency.

99linesofcode avatar Mar 02 '23 12:03 99linesofcode

Yes, definitely possible to do that. Same strategy we used with Docked Rails. Happy to see that explored.

dhh avatar Mar 02 '23 12:03 dhh

By adding the Dockerized app to Homebrew, it can be installed with ease on OSX and Linux (and possibly WSL). A global mrsk alias is created, allowing easy access to the mrsk command:

brew install mrsk
mrsk --version

latest version, please..

brew upgrade mrsk 

Brew formula could look something like this:

class MrskApp < Formula
  desc "Mrsk"
  homepage "https://example.com/mrsk"
  url "https://example.com/mrsk.tar.gz"
  version "1.0.0"

  depends_on "docker"

  def install
    system "docker", "pull", "mrsk:latest"
    system "docker", "tag", "mrsk:latest", "mrsk:#{version}"
    system "docker", "save", "-o", "mrsk-#{version}.tar", "mrsk:#{version}"
    bin.install "mrsk"
  end

  test do
    system "#{bin}/mrsk", "--version"
  end
end

kjellberg avatar Mar 03 '23 08:03 kjellberg

That sounds great! Please make it so.

dhh avatar Mar 03 '23 09:03 dhh

PR #73 creates a Dockerfile, but we need to build, tag and upload the Docker image somewhere on every release.

Here's what I propose we do:

  1. Add a new GitHub Actions workflow to the repository that triggers on each release tag.
  2. In the workflow, build a Docker image of our application and tag it with the release version number.
  3. Push the Docker image to a public Docker registry, such as Docker Hub or GitHub Packages.

Or just some extra rows in ./bin/release. It's up to you @dhh.

kjellberg avatar Mar 03 '23 23:03 kjellberg

I've added the GH action to trigger builds on pushes to main. Right now it just pushes latest. It lives in GH Packages 👍.

So let's proceed with the Homebrew setup! Really love that idea of wrapping it such that you don't even know it's running on Docker.

dhh avatar Mar 04 '23 07:03 dhh

Would be nice to upgrade this to properly tag the release when we tag in git. Set latest to latest tagged version and then use next for whatever just hits main. If anyone is interested in exploring that, please do!

dhh avatar Mar 04 '23 15:03 dhh

So I've created a first draft of a Homebrew formula at https://github.com/kjellberg/homebrew-tap

You should be able to try it already.

To install mrsk from my repository, run the following commands:

brew tap kjellberg/tap
brew install mrsk

This should install a global binary that runs mrsk from the docker image.

Please try it out and tell me if it works on your machine.. :)

kjellberg avatar Mar 04 '23 20:03 kjellberg

Awesome! First I tried installing it, and I didn't have Docker running, so I just got this error message. Which seems reasonable?

==> Installing kjellberg/tap/mrsk
==> docker pull ghcr.io/mrsked/mrsk:latest
Last 15 lines from /Users/dhh/Library/Logs/Homebrew/mrsk/01.docker:
2023-03-05 08:33:03 +0000

docker
pull
ghcr.io/mrsked/mrsk:latest

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

If reporting this issue please do so at (not Homebrew/brew or Homebrew/homebrew-core):
  https://github.com/kjellberg/homebrew-tap/issues

What's the next step? Should we just try to get the tap into Homebrew proper or just maintain the tap within mrsk?

dhh avatar Mar 05 '23 08:03 dhh

Awesome! First I tried installing it, and I didn't have Docker running, so I just got this error message. Which seems reasonable?

Yes it makes sense since depends_on "docker" only checks if it's installed and not running.

What's the next step? Should we just try to get the tap into Homebrew proper or just maintain the tap within mrsk?

I was hoping we could add it to Homebrew Core like this, and make it available with brew install mrsk, but unfortunately it seems like formulas just running a docker image isn't allowed in core. They need to build something on install (not sure a docker image is ok either). And it's not built for passing arguments (like --volume, -it to docker) so I had to hack it by creating a shell script that runs docker. code

I was also hoping that we could maintain the formula within this repo, but it needs to be hosted within repo prefixed with homebrew-*.

Proposal 1

Continue with this docker-brew hack and move my repository to mrsked/homebrew-tap. Which would make mrsk available through:

brew tap mrsked/tap && brew install mrsk # or brew install mrsked/tap/mrsk

Proposal 2

Follow Homebrew guidelines and let Homebrew build, install and configure Ruby, dependencies and finally install mrsk globally as a gem. This way we can publish it directly to Homebrew Core and make mrsk available with brew install mrsk.

We can still build docker image(s) for each release and add instructions on how to run it through docker. And users can choose between three options brew install mrsk, gem install mrsk or docker pull ghcr.io/mrsked/mrsk:latest.

kjellberg avatar Mar 05 '23 09:03 kjellberg

Btw, for smooth docker installation we don't need Homebrew. I guess it was a bad idea now after all.

Instead we could just create a small shell script that installs like:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/mrsked/mrsk/HEAD/install-docker.sh)"

(inspired by Homebrew's own installation)

  1. Make sure docker is installed
  2. Pull mrsk
  3. Install a mrsk script globally that runs mrsk from the docker image

kjellberg avatar Mar 05 '23 09:03 kjellberg

I like both! A proper homebrew install that just leans on a global gem and a curl install as well.

dhh avatar Mar 05 '23 12:03 dhh

To use ssh keys within the mrsk docker image, we need to forward/mount the ssh key/agent into the docker container.

Something like this should work, but I'm not sure about the security aspects. Some people may not want us to play with their credentials. What do you say?

-v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent

kjellberg avatar Mar 06 '23 08:03 kjellberg

As a long-time user of brew, I would def. expect mrsk to depend on Ruby and install a global gem as opposed to mrsk depending on Docker. A deployment tool like mrsk should not force me to have a daemon running if there's an alternative option.

jacoscaz avatar Jun 05 '23 12:06 jacoscaz

Feel free to look into that @jacoscaz

dhh avatar Jun 18 '23 12:06 dhh

Here is a homebrew formula based on the findings from @kjellberg , it installs Kamal as a bin, currently stable points to v1.3.1 and main branch can be installed by passing --HEAD

https://github.com/acidtib/homebrew-kamal

tap formula

brew tap acidtib/kamal

install stable version

brew install kamal

install main branch

brew install kamal --HEAD

acidtib avatar Jan 15 '24 00:01 acidtib

@djmb Seems like this can be closed. We already have:

  • Ability to install Kamal in a separate Gemfile
  • Docker image
  • Homebrew formula

igor-alexandrov avatar Mar 28 '24 16:03 igor-alexandrov