Skip to content

Development Guide

First take a look at the Configuration File guide and Testing Guide.

Makefile Structure

The project uses a modular Makefile setup split across multiple files:

  • Makefile: Main entry point with user-facing commands
  • MakeInit.mk: Variable initialization and helper functions
  • MakeBuild.mk: Build system implementation and Docker image caching

This structure separates high-level targets from implementation details, making the build system more maintainable.

Build Environment and Caching

The build system uses Docker to provide a consistent build environment across different platforms:

  • .tool_cache/: Directory that stores build environment state and caching
  • docker-run: Helper target for running commands within the build container
  • Automatic caching of Go modules and build artifacts between runs
  • TTY detection for better interactive shell experience
# Rebuild the cached Docker build image if needed
make rebuild-cache

# Run a custom command in the build environment
GO_BUILD_CMD="go version" make docker-run

# Get an interactive shell in the build container
make shell

Build Targets

  • build-c: Production build with Lua support (recommended for deployment)
  • build-dev-c: Development build with Lua support (recommended for development)
  • build: Production build without Lua support
  • build-dev: Development build without Lua support

Testing Targets

  • testgo: Run tests for specific modules with granular control
# Example: Test specific modules with verbose output
make testgo MUTEST=internal/utils,internal/config TESTARGS="-v -count=1"
  • testgo-cover: Run tests with coverage report for specific modules
make testgo-cover MUTEST=internal/parser
  • unit-test: Run all tests with HTML coverage report (skips CGO-dependent packages)
  • testcov: Run tests with coverage for specific modules
make testcov MUCOV=internal/utils,internal/config

Development Utilities

  • mod-tidy: Tidy Go module dependencies
  • shell: Get an interactive shell in the build container
  • pre-commit: Run pre-commit hooks for linting and formatting

Code Visualization

The project includes integration with go-callvis for visualizing the call graph of Go packages. This can be very helpful for understanding the codebase structure and dependencies.

NOTE: the ondrajz version doesn't seem to run in mac or docker. trying with ondrajz

  • callvis: Generate a static call graph visualization for a module
  • callvis-server: Run go-callvis in server mode for interactive visualization
# Generate a call graph for the handler package (default)
make callvis

# Generate a call graph for a specific module
make callvis ARGS="-m mysql-cache-go/internal/config"

# Focus on specific packages
make callvis ARGS="-m mysql-cache-go/internal/handler -f Handler"

# Run in server mode for interactive exploration
make callvis-server

# Save as PDF
make callvis ARGS="--format pdf"

# See all available options
make callvis ARGS="--help"

The generated visualization files are saved in .tool_cache/go-callvis/output/ and will automatically open in your browser or PDF viewer.

Runtime and Deployment

  • run: Build and run the application in server mode
  • docker: Build a Docker image using the compiled binary
  • dirty-dog-deploy: Update container with latest binary (use with reload)
  • reload: Send a soft reload signal to the running proxy service

Running the Project Locally

Always build the project before running it.

# Build the binary with Lua support
make build-dev-c

# Create a local Docker image
make docker

# Run with docker-compose
docker-compose -f deployments/docker-compose.proxy-dev.yml up -d

# Quick update a running container (development)
make dirty-dog-deploy reload

Development Notes

Project Structure

Follow the golang-standards/project-layout as much as possible.

Testing

Use helpers to keep tests clean: benbjohnson/testing

Log Levels

The log levels are as follows:

  • Debug: All data, each query and its response stats
  • Info: Only the query and response
  • Security: Only startup, authentication, and errors
  • Warning: Only errors and warnings

Conventions

  • Use Conventional Commit, like docs: manual de cosas or refactor: client handler mangler
  • Create branches with author/type/title where author is your shorthand, type is 'feature','docs' or other conv commit terms, and title a brief name for the feature.
  • Methods that require a lock to be already held are suffixed with InLock
  • Methods that handle their own mutex locking/unlocking are suffixed with Mutter