Skip to content

Development

This page is for contributors. It covers how to build and test the project locally, the CI/CD pipeline, what ships inside the default container image, and the coding conventions the codebase follows.

Prerequisites

  • Go 1.26+
  • Docker with Compose V2

Building and testing

# Build the binary
go build ./cmd/jailoc

# Run unit tests
go test ./...

# Run integration tests (requires a running Docker daemon)
go test -tags=integration ./internal/...

# Lint
go vet ./...

CI/CD pipeline

The pipeline runs on GitHub Actions. Most workflows trigger on every branch and pull request; release workflows are gated on version tags (v*).

Workflow Trigger Purpose
CI Every branch/PR — runs on push and pull_request events Build (go build with ldflags), test (go test + go vet), and lint with golangci-lint
Release Tags matching v* — runs on push with v* ref GoReleaser publishes static binaries and generates a GitHub Release with changelog
Docs Tags matching v* — runs on push with v* ref Builds documentation with MkDocs and deploys to GitHub Pages

Integration tests run as part of the CI workflow on v* tags with go test -tags=integration. GoReleaser builds static binaries (CGO_ENABLED=0) for linux/darwin x amd64/arm64. Configs live in .goreleaser.yml and .github/workflows/.

Default container contents

The embedded Dockerfile defines an Ubuntu 24.04 base image. Exact versions are pinned there and kept up to date by Renovate.

Category Tools
Runtimes Go, Node.js, Bun, Python 3 + uv
Package managers npm, Yarn (via corepack), Homebrew
Language servers gopls, typescript-language-server, pyright, yaml-language-server, bash-language-server, jsonnet-language-server, helm-ls
CLI tools Docker CLI, ripgrep, fd, fzf, jq, vim, git, openssh-client
Agent stack OpenCode, oh-my-openagent

Source: internal/embed/assets/Dockerfile

Project conventions

Module

github.com/seznam/jailoc

Commit format

type(scope): description

Valid types: feat, fix, docs, chore, refactor, test. Use imperative mood in the description.

Error handling

Always wrap errors with context. Never return a bare err.

// correct
return fmt.Errorf("resolve workspace: %w", err)

// wrong
return err

There are no custom error types in this codebase. fmt.Errorf wrapping is the only pattern used. There is no logging library either: fmt.Printf handles user-facing output, and errors propagate up the call stack.

File organization

One file per package concern: docker.go, compose.go, workspace.go, config.go. When a concern grows large enough to split, create a new file with a descriptive name (e.g. fetch.go for HTTP fetching inside the docker package). All packages live under internal/ — nothing is exported.

Testing

Unit tests live beside their source files as *_test.go. Integration tests live in internal/integration_test.go and require the //go:build integration build tag. Tests use t.Parallel() and a table-driven style with t.Run. There are no mocks, fixtures, or testdata directories.