Building PatchMon locally

The three build paths (server, agent, Docker image), what each one produces, and how to run the stack for development.

M
Written By M. Ibrahim (Admin)Last updated 10 days ago

PatchMon is a Go server with an embedded React frontend, plus a separate Go agent. This page explains what the build paths are and what each one produces, so you know which one you want before you start.

CONTRIBUTING.md in the repository is the authority on the exact commands and the full target list. It lives alongside the code, so it moves whenever the build does. This page is the map, not the reference.

What you need

  • Go (the version is pinned in each go.mod, so let your toolchain read it rather than installing a specific release by hand)
  • Node.js (the version is pinned in the root package.json)
  • Docker, only if you want to build the container image
  • A clone with tags and history. Not a shallow clone. The version comes from the nearest git tag, and working it out means walking back through history to find one, so git clone --depth 1 will not do. If you have a shallow clone, run git fetch --unshallow --tags.

The three build paths

Server

cd server-source-code
make build     # build the binary
make run       # build and run
make check     # fmt, vet, golangci-lint, tests. Run before you push

The server serves the REST API and also serves the React frontend, embedded into the binary with Go's embed. That means a plain make build embeds whatever is currently in the frontend build output directory, not a freshly built frontend. For day to day frontend work you want the dev server instead, see below.

Agent

cd agent-source-code
make build        # native binary for your machine
make build-all    # the platforms that ship in a release
make check        # fmt, vet, golangci-lint, tests

make build-all is Linux (amd64, 386, arm64, arm), FreeBSD (amd64, 386, arm64, arm) and Windows (amd64, arm64), copied into the agents directories. Those are the platforms attached to a release.

macOS is not in that set and is not published in releases. make build gives you a native macOS binary if you are working on the agent from a Mac, which is the only way it is built.

Docker image

./docker/build.sh

Use this rather than calling docker build yourself. It builds the agent binaries the image bundles, builds the frontend, and passes the version in as a build argument. That last part matters more than it sounds: see How versioning works.

Useful flags:

Flag

Effect

--tag mytag

Image tag, default local

--version 2.0.1

Report a specific version instead of deriving one

--skip-agents

Reuse the agent binaries already staged, for a faster rebuild

Working on the frontend

The frontend has its own dev server with hot reload, which is what you want for UI work rather than rebuilding the Go binary each time.

cd frontend
npm run dev

It listens on port 3000 and proxies /api through to the server on port 3001. Note that 3000 is the frontend, not the server, which catches people out.

Before you push:

npx biome check --write src/
npx biome check src/

The second command must come back clean. A pre-commit hook runs Biome and will block the commit otherwise.

Running the tests

cd server-source-code && make check   # Go server
cd agent-source-code  && make check   # Go agent
cd frontend           && npm run test:run

make check is the gate for Go work. It runs formatting checks, go vet, golangci-lint and the tests together, and it is what CI runs. If it passes locally it should pass in CI.

One difference to know about: CI runs the Go tests with -race. A data race will fail the build there even if the tests pass for you. If you are touching anything concurrent, run go test -race ./... before you push.

Where to go next

Was this helpful?

Your feedback shapes what we write next.