Three related issues fixed together:
1. Readiness context was never cancelled during shutdown
server.Run() had a type assertion for a Cancel() method that no standard
context.Context implements, so readiness stayed "ready" through the entire
shutdown window. Added CancelableContext to pkg/server — a thin wrapper that
exposes Cancel() — and switched cmd/server/main.go to use it. Test servers
and CLI continue passing context.Background() unchanged.
2. "Server exited" log was never emitted
The test script expected it; main.go had no log after server.Run() returned.
Added log.Trace().Msg("Server exited") after the Run() call.
3. Double-SIGTERM caused non-JSON "signal: terminated" in server.log
test-graceful-shutdown.sh sent SIGTERM, then called $SERVER_CMD stop which
sent a second SIGTERM. After signal.NotifyContext is cancelled, the second
signal hits the default handler and Go prints "signal: terminated" to stderr,
breaking the all-JSON-lines assertion. Fixed by waiting for the PID to exit
ourselves instead of re-invoking the stop script.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dance-lessons-coach
A Go project demonstrating idiomatic package structure, CLI implementation, and JSON API with Chi router.
Features
- Greet function with default behavior
- Command-line interface
- JSON API with versioned endpoints
- Chi router integration
- Zerolog for high-performance logging
- Viper for configuration management
- Graceful shutdown with context
- Readiness endpoint for Kubernetes/service mesh integration
- OpenTelemetry integration with Jaeger support
- OpenAPI/Swagger documentation
- Unit tests
- Go 1.26.1 compatible
Installation
# Clone the repository
git clone https://gitea.arcodange.lab/arcodange/dance-lessons-coach.git
cd dance-lessons-coach
# Build all binaries
./scripts/build.sh
# Use the new Cobra CLI
./bin/dance-lessons-coach --help
# Or use the legacy greet CLI
go run ./cmd/greet
CI/CD Pipeline
dance-lessons-coach features an optimized CI/CD pipeline using GitHub Actions with container/services architecture:
Key Features
- ✅ Container-based execution: All steps run in pre-built Docker cache images
- ✅ Service-based PostgreSQL: Automatic database service provisioning
- ✅ Smart caching: Dependency-aware cache invalidation
- ✅ Multi-platform: Compatible with Gitea, GitHub, and GitLab
- ✅ Fast execution: No Docker Compose overhead
- ✅ Reliable testing: Full database connectivity with proper environment setup
Architecture
The pipeline uses GitHub Actions' native container and services directives instead of Docker Compose:
jobs:
ci-pipeline:
container:
image: gitea.arcodange.lab/arcodange/dance-lessons-coach-build-cache:${{ needs.build-cache.outputs.deps_hash }}
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: dance_lessons_coach_bdd_test
Benefits
- Performance: Direct container execution without compose overhead
- Reliability: Service containers managed by GitHub Actions
- Simplicity: Cleaner workflow definition
- Portability: Works across CI platforms
- Caching: Intelligent dependency-based cache rebuilding
Workflow Steps
- Build Cache: Creates Docker image with Go tools and dependencies
- CI Pipeline: Runs tests, builds binaries, and generates documentation
- Database Tests: Connects to PostgreSQL service container
- Coverage Reporting: Updates coverage badges automatically
- Artifact Publishing: Builds and pushes Docker images (main branch only)
Environment Configuration
The pipeline automatically sets up database environment variables:
echo "DLC_DATABASE_HOST=postgres" >> $GITHUB_ENV
echo "DLC_DATABASE_PORT=5432" >> $GITHUB_ENV
echo "DLC_DATABASE_USER=postgres" >> $GITHUB_ENV
echo "DLC_DATABASE_PASSWORD=postgres" >> $GITHUB_ENV
echo "DLC_DATABASE_NAME=dance_lessons_coach_bdd_test" >> $GITHUB_ENV
echo "DLC_DATABASE_SSL_MODE=disable" >> $GITHUB_ENV
Status
=======
- ✅ Linting: Code quality checks with
go fmtandgo vet - ✅ Version Management: Automatic version detection
- ✅ Portable: Uses standard GitHub Actions workflow format
Workflow File
# .github/workflows/main.yml
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: '1.26.1'
- run: go build ./...
- run: go test ./... -cover
lint-format:
runs-on: ubuntu-latest
steps:
- run: go fmt ./...
- run: go vet ./...
Setup Instructions
- Gitea: Enable GitHub Actions compatibility in repo settings
- GitHub: Push to mirror repository (workflow runs automatically)
- GitLab: Convert workflow to
.gitlab-ci.ymlor use compatibility mode
See ADR 0016 for complete CI/CD design and STATUS_BADGES.md for badge setup.
Configuration
Basic configuration options:
# Start with default configuration
./scripts/start-server.sh start
# Custom port
export DLC_SERVER_PORT=9090
./scripts/start-server.sh start
# JSON logging
export DLC_LOGGING_JSON=true
./scripts/start-server.sh start
See AGENTS.md for comprehensive configuration guide including:
- File-based configuration
- Environment variables
- Configuration priority rules
- OpenTelemetry setup
- Advanced scenarios
Usage
New Cobra CLI (Recommended)
# Show help
./bin/dance-lessons-coach --help
# Show version
./bin/dance-lessons-coach version
# Greet someone
./bin/dance-lessons-coach greet John
# Start server
./bin/dance-lessons-coach server
Legacy CLI (Deprecated)
# Default greeting
go run ./cmd/greet
# Output: Hello world!
# Custom greeting
go run ./cmd/greet John
# Output: Hello John!
Web Server
Using the server control script (recommended):
# Start the server
./scripts/start-server.sh start
# Test API endpoints
./scripts/start-server.sh test
# Access OpenAPI documentation
# Swagger UI: http://localhost:8080/swagger/
# OpenAPI spec: http://localhost:8080/swagger/doc.json
# Stop the server
./scripts/start-server.sh stop
Manual server management:
# Start the server
go run ./cmd/server
# Test API endpoints
curl http://localhost:8080/api/health
# Output: {"status":"healthy"}
curl http://localhost:8080/api/ready
# Output: {"ready":true}
curl http://localhost:8080/api/v1/greet
# Output: {"message":"Hello world!"}
curl http://localhost:8080/api/v1/greet/John
# Output: {"message":"Hello John!"}
Testing
# Run all tests
go test ./...
# Run specific package tests
go test ./pkg/greet/
CI/CD
dance-lessons-coach includes a comprehensive CI/CD pipeline with multiple testing options:
Local Testing (No Gitea Required)
# Validate workflow structure
./scripts/cicd.sh validate
# Test workflow steps locally
./scripts/cicd.sh test-simple
Gitea Integration
# Test local setup with Gitea configuration
./scripts/cicd.sh test-local
# Check pipeline status on Gitea
./scripts/cicd.sh check-status
Full CI/CD Testing
# Test with docker compose (requires Gitea runner)
./scripts/cicd.sh test-docker
See adr/0016-ci-cd-pipeline-design.md for complete CI/CD architecture.
Project Structure
dance-lessons-coach/
├── adr/ # Architecture Decision Records
├── cmd/ # Entry points (greet CLI, server)
├── pkg/ # Core packages (config, greet, server, telemetry)
│ └── server/docs/ # Generated OpenAPI documentation (gitignored)
├── config.yaml # Configuration file
├── scripts/ # Management scripts
└── go.mod # Go module definition
See AGENTS.md for detailed structure and component explanations.
## Development
### Generate OpenAPI Documentation
The project uses [swaggo/swag](https://github.com/swaggo/swag) to generate OpenAPI/Swagger documentation from code annotations:
```bash
# Generate documentation
go generate ./pkg/server/
# This creates:
# - pkg/server/docs/docs.go (swagger template)
# - pkg/server/docs/swagger.json (OpenAPI spec)
# - pkg/server/docs/swagger.yaml (YAML version)
Note: pkg/server/docs/ is gitignored. Documentation is embedded in the binary at build time.
Documentation Annotations
Add swagger annotations to handlers and models:
// @Summary Get personalized greeting
// @Description Returns a greeting with the specified name
// @Tags greet
// @Accept json
// @Produce json
// @Param name path string true "Name to greet"
// @Success 200 {object} GreetResponse "Successful response"
// @Failure 400 {object} ErrorResponse "Invalid name parameter"
// @Router /v1/greet/{name} [get]
func (h *apiV1GreetHandler) handleGreetPath(w http.ResponseWriter, r *http.Request) {
// handler implementation
}
Architecture
This project uses Architecture Decision Records (ADRs) to document key technical choices. See adr/ for complete documentation including decisions on Go 1.26.1, Chi router, Zerolog, OpenTelemetry, interface-based design, graceful shutdown, configuration management, testing strategies, and OpenAPI documentation.
Adding new decisions? See adr/README.md for guidelines.
Gitea Integration
dance-lessons-coach includes AI agent skills for Gitea integration to monitor CI/CD jobs and interact with pull requests.
Gitea Client Skill Setup
The Gitea client skill enables AI agents to:
- Monitor CI/CD job status
- Fetch job logs for debugging
- Comment on pull requests
- Track PR status
Setup Instructions:
-
Create a Personal Access Token:
- Log in to https://gitea.arcodange.lab
- Go to Profile → Settings → Applications
- Generate token with
read:repository,write:repository, andread:userscopes
-
Configure Authentication:
# Option 1: Environment variable export GITEA_API_TOKEN="your_token" # Option 2: Token file (recommended) echo "your_token" > ~/.gitea_token chmod 600 ~/.gitea_token export GITEA_API_TOKEN_FILE="$HOME/.gitea_token" -
Add to shell configuration:
echo 'export GITEA_API_TOKEN_FILE="$HOME/.gitea_token"' >> ~/.bashrc source ~/.bashrc
Usage Examples:
# List recent jobs
.vibe/skills/gitea-client/scripts/gitea-client.sh list-jobs owner repo workflow_id 5
# Wait for job completion
.vibe/skills/gitea-client/scripts/gitea-client.sh wait-job owner repo job_id 300
# Comment on PR
.vibe/skills/gitea-client/scripts/gitea-client.sh comment-pr owner repo 42 "Build completed!"
Documentation: See .vibe/skills/gitea-client/README.md for complete setup and usage guide.
🤖 AI Agent Usage
Quick Launch Commands
Programmer Agent (for code implementation, testing, CI/CD):
vibe start --agent dancelessonscoachprogrammer
Product Owner Agent (for requirements, interviews, documentation):
vibe start --agent dancelessonscoach-product-owner
Full Documentation
For complete agent usage guide including:
- Agent selection guidance
- Common workflow examples
- Configuration reference
- Best practices
- Troubleshooting tips
See: AGENT_USAGE_GUIDE.md
Gitmoji Cheatsheet
Quick reference for commit messages:
- 📝
:memo:docs - Documentation - ✨
:sparkles:feat - New feature - 🐛
:bug:fix - Bug fix - ♻️
:recycle:refactor - Code refactoring - 🔧
:wrench:chore - Build/config changes
Full cheatsheet: GITMOJI_CHEATSHEET.md
License
MIT