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 commandsMakeInit.mk: Variable initialization and helper functionsMakeBuild.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 cachingdocker-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 supportbuild-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
unit-test: Run all tests with HTML coverage report (skips CGO-dependent packages)testcov: Run tests with coverage for specific modules
Development Utilities
mod-tidy: Tidy Go module dependenciesshell: Get an interactive shell in the build containerpre-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 modulecallvis-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 modedocker: Build a Docker image using the compiled binarydirty-dog-deploy: Update container with latest binary (use withreload)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 cosasorrefactor: client handler mangler - Create branches with
author/type/titlewhere 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