Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ dbName=ecommerce
dbHosts=localhost:27022
DBCredentialsSideCar=./localDevelopment/db-credentials-sidecar.json
printDBQueries=true
logLevel=debug
logLevel=debug
enableTracing=true
19 changes: 19 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Environment Configuration Example
# Copy this file to .env and update with your actual values

# Application Environment (local, dev, staging, prod)
environment=local

# Database Configuration
dbName=ecommerce
dbHosts=localhost:27022
DBCredentialsSideCar=./localDevelopment/db-credentials-sidecar.json
printDBQueries=true

# Logging Configuration
logLevel=debug

# Tracing Configuration
# Enable flight recorder for slow request tracing (>500ms)
# Disabled by default in production to avoid overhead
enableTracing=true
18 changes: 18 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ When generating code for this project, please ensure compliance with the followi

### Linting Compliance
- **golangci-lint**: All generated code must pass our golangci-lint configuration
- **Verify before committing**: Run `make lint` to check for linting issues locally
- **Common lint rules to follow**:
- No unused variables or imports
- Proper error handling (never ignore errors)
- Use `require` for error assertions in tests, `assert` for other validations
- Avoid useless assertions (comparing variables to themselves)
- Add proper context to error messages
- **Fix issues promptly**: Address all linting issues before submitting code

### Testing Standards
- **Test naming**: Use `Test<FunctionName>` pattern
Expand Down Expand Up @@ -141,4 +143,20 @@ lgr.Info().
- Validate all required configuration at startup
- Provide sensible defaults where appropriate

## Development Workflow

### Before Committing Code
1. **Format**: Run `gofmt -s -w .` to format code
2. **Lint**: Run `make lint` to verify code passes all linting rules
3. **Test**: Run `make test` to ensure all tests pass
4. **Build**: Run `make build` to verify the application builds successfully

### Available Make Targets
- `make lint` - Run golangci-lint to check for code quality issues
- `make test` - Run all unit tests
- `make ci-coverage` - Run tests with coverage reporting
- `make build` - Build the application binary
- `make docker-build` - Build the Docker image
- `make docker-start` - Build and run the application in Docker

When generating code, please ensure it follows these patterns and will pass both our linting rules and maintain consistency with the existing codebase architecture.
8 changes: 3 additions & 5 deletions .github/workflows/cibuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: 🧱 Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
go-version: '1.25.4'
cache: true

- name: 🎗️ Check go mod
Expand All @@ -30,9 +30,7 @@ jobs:
run: if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then exit 1; fi

- name: 🛡️ Lint
uses: golangci/golangci-lint-action@v8
with:
version: v2.1.0
uses: golangci/golangci-lint-action@v9

- name: 🏗️ Build
run: make build
Expand All @@ -49,7 +47,7 @@ jobs:
- name: 🧱 Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
go-version: '1.25.4'
cache: true

- name: 👮‍ Run Tests and Check Code Coverage
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ coverage.out
coverage.html
coverage.txt

# Environment variables (sensitive data)
.env

# Flight recorder trace files
traces/
*.trace


# Created by https://www.toptal.com/developers/gitignore/api/go,intellij+iml,vs
# Edit at https://www.toptal.com/developers/gitignore?templates=go,intellij+iml,vs
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1.4 # Enable BuildKit features

# Stage 1: Build the Go binary
FROM golang:1.24.3 AS builder
FROM golang:1.25.4 AS builder
LABEL stage=builder

# Set working directory
Expand Down
133 changes: 96 additions & 37 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
SHELL = /bin/bash

# ========================================
# Configuration & Variables
# ========================================

# Load and export environment variables from .env file if it exists
ifneq (,$(wildcard ./.env))
include .env
Expand All @@ -9,8 +13,6 @@ else
endif

# Get the number of CPU cores for parallelism
#get_cpu_cores := $(shell getconf _NPROCESSORS_ONLN)
# Shell function to determine the number of CPU cores based on the OS
get_cpu_cores = \
if [ "$$(uname)" = "Linux" ]; then \
nproc; \
Expand All @@ -21,59 +23,43 @@ get_cpu_cores = \
echo 1; \
fi

# Assign the result of the get_cpu_cores shell command to a variable
cpu_cores := $(shell $(get_cpu_cores))

# Project-specific variables
PROJECT_NAME := $(shell basename "$(PWD)" | tr '[:upper:]' '[:lower:]')
VERSION ?= $(shell git rev-parse --short HEAD)
LDFLAGS := -ldflags "-X main.version=$(VERSION)"

DOCKER_IMAGE_NAME := $(PROJECT_NAME):$(VERSION)
DOCKER_CONTAINER_NAME := $(PROJECT_NAME)-$(VERSION)
MODULE := $(shell go list -m)
TEST_COVERAGE_THRESHOLD := 70

# Command to calculate test coverage will be computed when needed
# Docker variables
DOCKER_IMAGE_NAME := $(PROJECT_NAME):$(VERSION)
DOCKER_CONTAINER_NAME := $(PROJECT_NAME)-$(VERSION)

# Helper variables
GO_BUILD_CMD := CGO_ENABLED=0 go build $(LDFLAGS) -o $(PROJECT_NAME)
GO_TEST_CMD := go test -race ./... -v -coverprofile=coverage.out -covermode=atomic -parallel=$(cpu_cores)

# ========================================
# Development & Running
# ========================================

## Start all necessary services and API server
.PHONY: start
start: setup run ## Start all necessary services and API server

## Start only dependencies (Docker containers)
## Start only dependencies (Docker Compose services)
.PHONY: setup
setup: docker-compose-up ## Start only dependencies

## Run the API server
## Run the API server locally
.PHONY: run
run: ## Run the API server
go run $(LDFLAGS) main.go

## Start docker-compose services
.PHONY: docker-compose-up
docker-compose-up:
docker-compose up -d

## Stop docker-compose services
.PHONY: docker-compose-down
docker-compose-down:
docker-compose down

## Stop docker-compose services and remove volumes
.PHONY: docker-compose-down-volumes
docker-compose-down-volumes:
docker-compose down -v

## Remove only the docker-compose volumes (database data)
.PHONY: clean-volumes
clean-volumes:
@echo "Removing docker-compose volumes..."
@docker volume ls -q --filter name=orders | xargs -r docker volume rm
@echo "Volumes removed."
# ========================================
# Build & Version
# ========================================

## Build the API server binary
.PHONY: build
Expand All @@ -85,6 +71,10 @@ build: ## Build the API server binary
version: ## Display the current version of the API server
@echo $(VERSION)

# ========================================
# Testing & Coverage
# ========================================

## Run tests with coverage
.PHONY: test
test: ## Run tests with coverage
Expand All @@ -97,7 +87,7 @@ coverage: test ## Generate and display the code coverage report
@go tool cover -func=coverage.out | grep total
@go tool cover -html=coverage.out

## Check if test coverage meets the threshold
## Check if test coverage meets the threshold (for CI)
.PHONY: ci-coverage
ci-coverage: test ## Check if test coverage meets the threshold
@coverage=$(shell go tool cover -func=coverage.out | grep total | awk '{print $$3}' | sed 's/%//g'); \
Expand All @@ -113,6 +103,10 @@ ci-coverage: test ## Check if test coverage meets the threshold
echo "Test coverage meets the threshold."; \
fi

# ========================================
# Code Quality & Formatting
# ========================================

## Tidy Go modules
.PHONY: tidy
tidy: ## Tidy Go modules
Expand All @@ -133,6 +127,37 @@ lint: ## Run the linter
lint-fix: ## Run the linter and fix issues
golangci-lint run --fix

# ========================================
# Debugging & Diagnostics
# ========================================

## Analyze a trace file with go tool trace
.PHONY: trace
trace: ## Analyze a trace file (usage: make trace TRACE_FILE=./traces/slow-request-GET-orders-1234567890.trace)
@if [ -z "$(TRACE_FILE)" ]; then \
echo "Error: TRACE_FILE is required"; \
echo "Usage: make trace TRACE_FILE=./traces/slow-request-GET-orders-1234567890.trace"; \
echo ""; \
echo "Available trace files:"; \
if [ -d "./traces" ] && [ -n "$$(ls -A ./traces 2>/dev/null)" ]; then \
ls -lhtr ./traces/*.trace 2>/dev/null | tail -10 || echo " No .trace files found in ./traces"; \
else \
echo " No traces directory or no trace files found"; \
fi; \
exit 1; \
fi; \
if [ ! -f "$(TRACE_FILE)" ]; then \
echo "Error: Trace file not found: $(TRACE_FILE)"; \
exit 1; \
fi; \
echo "Analyzing trace file: $(TRACE_FILE)"; \
echo "This will start a web server and open the trace viewer in your browser..."; \
go tool trace $(TRACE_FILE)

# ========================================
# Utilities & Miscellaneous
# ========================================

## Generate OWASP report
.PHONY: owasp-report
owasp-report: ## Generate OWASP report
Expand All @@ -143,13 +168,35 @@ owasp-report: ## Generate OWASP report
go-work: ## Generate Go work file
go work init .

## Clean all Docker resources (keeps database data)
.PHONY: clean
clean: docker-compose-down docker-clean ## Clean all Docker resources (keeps database data)
# ========================================
# Docker Compose Services
# ========================================

## Clean all Docker resources including volumes (removes database data)
.PHONY: clean-all
clean-all: docker-compose-down-volumes docker-clean ## Clean all Docker resources including volumes (removes database data)
## Start docker-compose services
.PHONY: docker-compose-up
docker-compose-up:
docker-compose up -d

## Stop docker-compose services
.PHONY: docker-compose-down
docker-compose-down:
docker-compose down

## Stop docker-compose services and remove volumes
.PHONY: docker-compose-down-volumes
docker-compose-down-volumes:
docker-compose down -v

## Remove only the docker-compose volumes (database data)
.PHONY: clean-volumes
clean-volumes:
@echo "Removing docker-compose volumes..."
@docker volume ls -q --filter name=orders | xargs -r docker volume rm
@echo "Volumes removed."

# ========================================
# Docker Image & Container Management
# ========================================

## Build the Docker image
.PHONY: docker-build
Expand Down Expand Up @@ -223,6 +270,18 @@ docker-clean-build-images:
echo "No build images to remove."; \
fi

## Clean all Docker resources (keeps database data)
.PHONY: clean
clean: docker-compose-down docker-clean ## Clean all Docker resources (keeps database data)

## Clean all Docker resources including volumes (removes database data)
.PHONY: clean-all
clean-all: docker-compose-down-volumes docker-clean ## Clean all Docker resources including volumes (removes database data)

# ========================================
# Help
# ========================================

## Display help
.PHONY: help
help:
Expand Down
Loading
Loading