Skip to content

fornellas/rrb

Repository files navigation

Latest Release Push Go Report Card Go Reference License: GPL v3 Buy me a beer: donate

rrb

Re-Run Build helps continuously build your projects based on source file changes, much like a CI server. It works with any project, written in any language. It helps iterate quick when writing code, by giving fast & reliable build results as you do changes to the source.

How does it work?

Just call rrb [your build command], that simple! In this example we use it to run our build with the make lint test build command:

$ rrb make lint test build
> make lint test build
goimports -w -local github.com/fornellas/ .
go generate ./...
go mod tidy
gocyclo -over 10 -avg .
Average: 4.37
golangci-lint run --timeout 10m
go vet ./...
gotest ./... -v -race -cover -count=1
?   	github.com/fornellas/rrb	[no test files]
?   	github.com/fornellas/rrb/cmd	[no test files]
?   	github.com/fornellas/rrb/log	[no test files]
?   	github.com/fornellas/rrb/process	[no test files]
?   	github.com/fornellas/rrb/runner	[no test files]
?   	github.com/fornellas/rrb/watcher	[no test files]
go build .
Success: exit status 0

From now onward, just edit the source code with your preferred text editor. As soon as you save a source file rrb automatically runs the build:

Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
> make lint test build
goimports -w -local github.com/fornellas/ .
go generate ./...
go mod tidy
gocyclo -over 10 -avg .
Average: 4.37
golangci-lint run --timeout 10m
go vet ./...
gotest ./... -v -race -cover -count=1
?   	github.com/fornellas/rrb	[no test files]
?   	github.com/fornellas/rrb/cmd	[no test files]
?   	github.com/fornellas/rrb/log	[no test files]
?   	github.com/fornellas/rrb/process	[no test files]
?   	github.com/fornellas/rrb/runner	[no test files]
?   	github.com/fornellas/rrb/watcher	[no test files]
go build .
Success: exit status 0

But what happens if while the build is running, a source file changes? This build will yield stale / broken results, so there's no point in waiting for it to finish. In this case, rrb terminates the stale in-flight build before starting a new build:

Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
Changed: /home/fornellas/src/rrb/runner/runner.go (WRITE)
Killing...
make: *** [Makefile:133: golangci-lint] Terminated
Failure: signal: terminated
> make lint test build
goimports -w -local github.com/fornellas/ .
go generate ./...
go mod tidy
gocyclo -over 10 -avg .
Average: 4.37
golangci-lint run --timeout 10m
go vet ./...
gotest ./... -v -race -cover -count=1
?   	github.com/fornellas/rrb	[no test files]
?   	github.com/fornellas/rrb/cmd	[no test files]
?   	github.com/fornellas/rrb/log	[no test files]
?   	github.com/fornellas/rrb/process	[no test files]
?   	github.com/fornellas/rrb/runner	[no test files]
?   	github.com/fornellas/rrb/watcher	[no test files]
go build .
Success: exit status 0

rrb does this deterministically, ensuring that there are no stray process from a stale build left behind1 before starting a new build. No matter how often you save your files, you will never get a stale build signal with rrb. This sets rrb apart from most similar tools.

Install

Pick the latest release with:

GOARCH=$(case $(uname -m) in i[23456]86) echo 386;; x86_64) echo amd64;; armv6l|armv7l) echo arm;; aarch64) echo arm64;; *) echo Unknown machine $(uname -m) 1>&2 ; exit 1 ;; esac) && wget -O- https://github.com/fornellas/rrb/releases/latest/download/rrb.linux.$GOARCH.gz | gunzip > rrb && chmod 755 rrb
./rrb --help

Development

Docker is used to create a reproducible development environment on any machine:

git clone git@github.com:fornellas/rrb.git
cd rrb/
./builld.sh

Typically you'll want to stick to ./builld.sh rrb, as it enables you to edit files as preferred, and the build will automatically be triggered on any file changes.

Footnotes

  1. This is achieved by use of PR_SET_CHILD_SUBREAPER (see prctl(2) ).