Skip to content

Commit c7da5c9

Browse files
authored
Merge pull request #7 from AstraBert/feat/bleve-v2-and-second-blog
feat: migrate to bleve/v2 and add second blog post
2 parents 3f1ab46 + 680fa23 commit c7da5c9

File tree

6 files changed

+285
-190
lines changed

6 files changed

+285
-190
lines changed

contents/2.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
---
2+
title: How to distribute Go binaries with NPM
3+
publishing_date: 2025-09-27
4+
author: Clelia Astra Bertelli
5+
---
6+
7+
[NPM](https://npmjs.org) is a foundational piece of modern software development, since it's the registry (and package manager) that stores all the packages for JavaScript and Typescript world.
8+
9+
Despite clearly being oriented toward the JS/TS world, NPM can also be used to distribute binaries from other languages, like Go, Rust or C/C++.
10+
11+
In this article, I would like to walk you through how you can easily release a Go package and distribute it through npm, thanks to an extremely useful utility called [`go-npm`](https://github.com/Nelwhix/go-npm).
12+
13+
To do so, we'll follow these steps:
14+
15+
- create a very simple ‘hello world’ program in Go
16+
- create a `.goreleaser.yaml` file to configure [GoReleaser](https://goreleaser.com) so that we can easily carry out cross-platform builds
17+
- create a `package.json` to package and distribute the binaries
18+
- create a `.github/workflows/release.yaml` file to automate the release whenever we want to publish the package
19+
20+
Without further ado, let's dive in!
21+
22+
## 1. Create a Hello World in Go
23+
24+
If you're interested in this tutorial, you probably already know Go, but, assuming you don't, let's create a very simple ‘hello world’ script that we will save under `main.go`:
25+
26+
```go
27+
package main
28+
29+
import "fmt"
30+
31+
func main() {
32+
fmt.Println("Hello world!")
33+
}
34+
```
35+
36+
In order to build and run this Go script, you simply need to run:
37+
38+
```bash
39+
go build . -o hello-world
40+
./hello-world
41+
```
42+
43+
And you will get a nice `Hello world` printed out on the console.
44+
45+
## 2. Create a .goreleaser.yaml
46+
47+
GoReleaser is an extremely useful utility to publish Go binaries on platforms such as GitHub.
48+
49+
In order to run it, you simply need to add a `.goreleaser.yaml` file in the root directory of the Go program you want to build.
50+
51+
Here is an example for our hello world:
52+
53+
```yaml
54+
builds:
55+
- binary: hello-world
56+
goos:
57+
- windows
58+
- darwin
59+
- linux
60+
goarch:
61+
- amd64
62+
- arm64
63+
```
64+
65+
As you can see, we specify:
66+
67+
- The name of the binary (`binary`)
68+
- The Operative Systems for which the binary will be built (`goos` , which in our case is an array of the most common OS, Windows, Dawin/macOS and Linux)
69+
- The processor architecture for the target operating system (`goarch`, which in our case is an array with the two major available architectures, AMD64 and ARM64)
70+
71+
Once this is configured, you will be able to automate the builds of your binary effortlessly.
72+
73+
## 3. Create a package.json
74+
75+
`package.json` is the file that is used to specify package information for NPM packages. Specifically, in our `package.json` we will specify:
76+
77+
- Name of the package and several other metadata useful for discovery on the NPM registry (like the source repository, the name of the author, keywords, where to submit issues…)
78+
- Dependencies, among which we will specify `go-npm`, which is crucial for building our package locally, once it has been pulled from NPM registry
79+
- A post-install script, which will install the Go binary on our system
80+
- The target Go binary to install from our GitHub repository (binary that we built and published with GoReleaser)
81+
82+
Here is an example of the `package.json` file for our hello world project:
83+
84+
```json
85+
{
86+
"name": "@namespace/hello-world", // change @namespace to your actual namespace!
87+
"version": "0.1.0",
88+
"description": "My first Go project published on NPM!",
89+
"main": "index.js",
90+
"scripts": {
91+
"postinstall": "golang-npm install",
92+
"test": "echo \"Error: no test specified\" && exit 1"
93+
},
94+
"repository": {
95+
"type": "git",
96+
"url": "git+https://github.com/your-name/hello-world.git" // change your-name to your actual GitHub username!
97+
},
98+
"keywords": [
99+
"hello world",
100+
"go",
101+
"npm",
102+
"tutorial"
103+
],
104+
"author": "Your Name",
105+
"license": "MIT",
106+
"bugs": {
107+
"url": "https://github.com/your-name/hello-world/issues"
108+
},
109+
"homepage": "https://github.com/Ayour-name/hello-world#readme",
110+
"dependencies": {
111+
"golang-npm": "^0.0.6"
112+
},
113+
"goBinary": {
114+
"name": "hello-world",
115+
"path": "./bin",
116+
"url": "https://github.com/your-name/hello-world/releases/download/v{{version}}/git-push-blog_{{version}}_{{platform}}_{{arch}}.tar.gz"
117+
}
118+
}
119+
120+
```
121+
122+
## 4. Automate with a GitHub Action
123+
124+
Once we have everything in place, we can automate the publishing with a GitHub Action that runs every time we push a tag to it.
125+
126+
Here is the code, that you should save under `.github/workflows/release.yml`:
127+
128+
```yaml
129+
name: Release
130+
on:
131+
push:
132+
tags:
133+
- "v*.*.*"
134+
135+
permissions:
136+
contents: read # for checkout
137+
138+
jobs:
139+
release:
140+
name: Release
141+
runs-on: ubuntu-latest
142+
permissions:
143+
contents: write # to be able to publish a GitHub release
144+
issues: write # to be able to comment on released issues
145+
pull-requests: write # to be able to comment on released pull requests
146+
id-token: write # to enable use of OIDC for npm provenance
147+
steps:
148+
- name: Checkout
149+
uses: actions/checkout@v4
150+
with:
151+
fetch-depth: 0
152+
153+
- name: Setup Node.js
154+
uses: actions/setup-node@v4
155+
with:
156+
node-version: "lts/*"
157+
158+
- name: Install goreleaser
159+
run: npm i -g @goreleaser/goreleaser
160+
161+
- name: Release Go binary
162+
run: goreleaser release
163+
env:
164+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
165+
166+
- name: Setup npm authentication
167+
run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
168+
env:
169+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
170+
171+
- name: Release NPM package
172+
env:
173+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
174+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
175+
run: npm publish --access public
176+
177+
```
178+
179+
As you can see, in this action we:
180+
181+
- Install Node and use `npm` to install GoReleaser globally
182+
- Set up NPM authentication (for which you will need an NPM access token configured under `NPM_TOKEN` in your GitHub repository secrets)
183+
- Release the package to npm via `npm publish` (it is important to specify `--access public` if you do not have a paying account and thus do not have access to private packages)
184+
185+
## 5. Test the Release Pipeline
186+
187+
Once you are ready, create a GitHub repository under `your-name/hello-world` and push all the code you just wrote to the main branch.
188+
189+
Once that is set, you can run:
190+
191+
```bash
192+
git tag v0.1.0
193+
git push origin v0.1.0
194+
```
195+
196+
This way, GitHub will kick off the release action and, in a couple of minutes, you will be able to see the release on GitHub and the package on NPM.
197+
198+
You can then test it by installing it with:
199+
200+
```bash
201+
npm install @namespace/hello-world
202+
hello-world # the binary should be available globally
203+
```
204+
205+
And you’re done: you’ve successfully built, pushed and installed your first Go binary with NPM!

go.mod

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,34 @@ go 1.24.5
44

55
require (
66
github.com/a-h/templ v0.3.943
7-
github.com/blevesearch/bleve v1.0.14
7+
github.com/blevesearch/bleve/v2 v2.5.3
88
github.com/gomarkdown/markdown v0.0.0-20250810172220-2e2c11897d1a
99
)
1010

1111
require (
12-
github.com/RoaringBitmap/roaring v0.4.23 // indirect
12+
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
13+
github.com/bits-and-blooms/bitset v1.22.0 // indirect
14+
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
15+
github.com/blevesearch/geo v0.2.4 // indirect
16+
github.com/blevesearch/go-faiss v1.0.25 // indirect
1317
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
14-
github.com/blevesearch/mmap-go v1.0.2 // indirect
15-
github.com/blevesearch/segment v0.9.0 // indirect
18+
github.com/blevesearch/gtreap v0.1.1 // indirect
19+
github.com/blevesearch/mmap-go v1.0.4 // indirect
20+
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
21+
github.com/blevesearch/segment v0.9.1 // indirect
1622
github.com/blevesearch/snowballstem v0.9.0 // indirect
17-
github.com/blevesearch/zap/v11 v11.0.14 // indirect
18-
github.com/blevesearch/zap/v12 v12.0.14 // indirect
19-
github.com/blevesearch/zap/v13 v13.0.6 // indirect
20-
github.com/blevesearch/zap/v14 v14.0.5 // indirect
21-
github.com/blevesearch/zap/v15 v15.0.3 // indirect
22-
github.com/couchbase/vellum v1.0.2 // indirect
23-
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2 // indirect
23+
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
24+
github.com/blevesearch/vellum v1.1.0 // indirect
25+
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
26+
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
27+
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
28+
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
29+
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
30+
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
2431
github.com/golang/protobuf v1.3.2 // indirect
25-
github.com/golang/snappy v0.0.1 // indirect
32+
github.com/golang/snappy v0.0.4 // indirect
33+
github.com/json-iterator/go v0.0.0-20171115153421-f7279a603ede // indirect
2634
github.com/mschoch/smat v0.2.0 // indirect
27-
github.com/philhofer/fwd v1.0.0 // indirect
28-
github.com/steveyen/gtreap v0.1.0 // indirect
29-
github.com/tinylib/msgp v1.1.0 // indirect
30-
github.com/willf/bitset v1.1.10 // indirect
31-
go.etcd.io/bbolt v1.3.5 // indirect
35+
go.etcd.io/bbolt v1.4.0 // indirect
3236
golang.org/x/sys v0.34.0 // indirect
3337
)

0 commit comments

Comments
 (0)