How we repurposed NPM to publish and distribute our Go binaries for internal CLI

UTKARSH AGARWAL
Jan 5 · 3 min read

NPM provides an easy way to publish and distribute Node JS packages for both code dependencies as well as global command-line tools. This article demonstrates how it can be used to publish and distribute binaries written in GoLang

Image for post
Image for post

Problem

We recently migrated our internal CLI tool from Node JS to Golang. As the project completed we ran into the issue of distributing the CLI tool to our team of engineers without the need of distributing a new set of tokens or making the binary public. This had been quite easy with the NodeJS version of the CLI as we have a private NPM registry where we published the CLI and the team had access to it. Installing it was a simple command

npm i -g @xendit/xendit-cli

Solution

As the node package manager (npm) doesn’t restrict on what contents or file types that can be published in the package, we hacked our way into making npm publish our pre-built Go binaries compatible with Mac OS, Linux and Windows.

Here is a list of tools used and steps to do it:

Tools

  1. Go Releaser: Tool used to build the go binaries for different platforms and create a release on github.

Steps:

  1. Setup Go Releasers in your project: The binaries can be built locally or in a CI/CD pipeline using this tool.

To use goreleaser a config needs to be created. Here is a sample config

The path and binary names need to be changed as per your project structure

When you run the goreleaser command in the same directory of your project it will create a dist folder in the same directory and place the binary files under the respective OS folders we built it for.

2. Node Package Details: We need to be able to publish the binaries we just built on the node registry. In order to do that we need to create a package.json and package-lock.json for npm commands to read from.

After adding the above file, if you run npm install in the current directory, it will automatically generate the package-lock.json file.

So far we have set up a way to publish the dist folder to the npm registry.

Now we need to add postinstall.js which will help the npm i -g your-package-name the command to pick up the correct binary based on your OS and place it in the correct path so that it's available as a command in your terminal.

That’s it!

Once you publish your package after running goreleaser, it can be downloaded installed by anyone who has access to your npm registry by a simple command as used by packages written in NodeJS

npm i -g @your-registry/your-package-name

Curious about what’ve done? We’re hiring, join us now!

Xendit Engineering

The Untold Story Behind Xendit Engineering

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store