🐛 fix: emit all config-loading logs in correct JSON format from the start #16

Merged
arcodange merged 5 commits from fix/json-logging-first-message into main 2026-04-12 23:28:36 +02:00
3 changed files with 199 additions and 1599 deletions
Showing only changes of commit 99b2e410f2 - Show all commits

View File

@@ -203,6 +203,31 @@ cmd_wait_job() {
}
# Comment on PR
# Create a pull request
cmd_create_pr() {
local owner="$1"
local repo="$2"
local title="$3"
local body="$4"
local head="$5"
local base="${6:-main}"
if [[ -z "$owner" || -z "$repo" || -z "$title" || -z "$head" ]]; then
echo "Usage: $0 create-pr <owner> <repo> <title> <body> <head_branch> [base_branch]" >&2
exit 1
fi
local endpoint="/repos/${owner}/${repo}/pulls"
local data
data=$(jq -n \
--arg title "$title" \
--arg body "$body" \
--arg head "$head" \
--arg base "$base" \
'{title: $title, body: $body, head: $head, base: $base}')
api_request "POST" "$endpoint" "$data"
}
cmd_comment_pr() {
local owner="$1"
local repo="$2"
@@ -215,7 +240,8 @@ cmd_comment_pr() {
fi
local endpoint="/repos/${owner}/${repo}/issues/${pr_number}/comments"
local data="{\"body\": \"${comment}\"}"
local data
data=$(jq -n --arg body "$comment" '{body: $body}')
api_request "POST" "$endpoint" "$data"
}
@@ -250,6 +276,7 @@ main() {
monitor-workflow) cmd_monitor_workflow "$@" ;;
diagnose-job) cmd_diagnose_job "$@" ;;
recent-workflows) cmd_recent_workflows "$@" ;;
create-pr) cmd_create_pr "$@" ;;
comment-pr) cmd_comment_pr "$@" ;;
pr-status) cmd_pr_status "$@" ;;
list-issues) cmd_list_issues "$@" ;;
@@ -274,6 +301,7 @@ main() {
echo " monitor-workflow <owner> <repo> <workflow_run_id> [interval_seconds]" >&2
echo " diagnose-job <owner> <repo> <job_id>" >&2
echo " recent-workflows <owner> <repo> [limit] [status_filter]" >&2
echo " create-pr <owner> <repo> <title> <body> <head_branch> [base_branch]" >&2
echo " comment-pr <owner> <repo> <pr_number> <comment>" >&2
echo " pr-status <owner> <repo> <pr_number>" >&2
echo " list-issues <owner> <repo> [state]" >&2

1339
AGENTS.md

File diff suppressed because it is too large Load Diff

429
README.md
View File

@@ -1,421 +1,98 @@
# dance-lessons-coach
[![Build Status](https://gitea.arcodange.fr/arcodange/dance-lessons-coach/actions/workflows/ci-cd.yaml/badge.svg)](https://gitea.arcodange.fr/arcodange/dance-lessons-coach/actions/workflows/ci-cd.yaml/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/arcodange/dance-lessons-coach)](https://goreportcard.com/report/github.com/arcodange/dance-lessons-coach)
[![Build Status](https://gitea.arcodange.fr/arcodange/dance-lessons-coach/actions/workflows/ci-cd.yaml/badge.svg)](https://gitea.arcodange.fr/arcodange/dance-lessons-coach/actions/workflows/ci-cd.yaml)
[![Version](https://img.shields.io/badge/version-1.4.0-blue.svg)](https://gitea.arcodange.fr/arcodange/dance-lessons-coach/releases)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![BDD Coverage](https://img.shields.io/badge/BDD_Coverage-51.1%%-red?style=flat-square)](https://gitea.arcodange.lab/arcodange/dance-lessons-coach)
[![UNIT Coverage](https://img.shields.io/badge/UNIT_Coverage-8.9%%-red?style=flat-square)](https://gitea.arcodange.lab/arcodange/dance-lessons-coach)
A Go project demonstrating idiomatic package structure, CLI implementation, and JSON API with Chi router.
=======
Go web service demonstrating idiomatic package structure, versioned JSON API, and production-ready features.
## 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
- Versioned JSON API (`/api/v1`, `/api/v2`)
- Chi router with graceful shutdown
- Zerolog structured logging (console and JSON modes)
- Viper configuration (file + env vars)
- Readiness endpoint for Kubernetes / service mesh
- OpenTelemetry / Jaeger distributed tracing
- OpenAPI / Swagger UI (embedded in binary)
- PostgreSQL user service with JWT auth
- BDD + unit tests
## Installation
## Quick Start
```bash
# 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
./scripts/build.sh # produces ./bin/server and ./bin/greet
./scripts/start-server.sh start
```
## 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:
```yaml
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
1. **Performance**: Direct container execution without compose overhead
2. **Reliability**: Service containers managed by GitHub Actions
3. **Simplicity**: Cleaner workflow definition
4. **Portability**: Works across CI platforms
5. **Caching**: Intelligent dependency-based cache rebuilding
### Workflow Steps
1. **Build Cache**: Creates Docker image with Go tools and dependencies
2. **CI Pipeline**: Runs tests, builds binaries, and generates documentation
3. **Database Tests**: Connects to PostgreSQL service container
4. **Coverage Reporting**: Updates coverage badges automatically
5. **Artifact Publishing**: Builds and pushes Docker images (main branch only)
### Environment Configuration
The pipeline automatically sets up database environment variables:
```bash
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
curl http://localhost:8080/api/health
curl http://localhost:8080/api/v1/greet/Alice
```
### Status
Stop: `./scripts/start-server.sh stop`
[![Build Status](https://gitea.arcodange.fr/api/badges/arcodange/dance-lessons-coach/status)](https://gitea.arcodange.fr/arcodange/dance-lessons-coach)
## Greet CLI
=======
-**Linting**: Code quality checks with `go fmt` and `go vet`
-**Version Management**: Automatic version detection
-**Portable**: Uses standard GitHub Actions workflow format
### Workflow File
```yaml
# .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 ./...
```bash
go run ./cmd/greet # Hello world!
go run ./cmd/greet Alice # Hello Alice!
```
### Setup Instructions
1. **Gitea**: Enable GitHub Actions compatibility in repo settings
2. **GitHub**: Push to mirror repository (workflow runs automatically)
3. **GitLab**: Convert workflow to `.gitlab-ci.yml` or use compatibility mode
**See [ADR 0016](adr/0016-ci-cd-pipeline-design.md) for complete CI/CD design and [STATUS_BADGES.md](STATUS_BADGES.md) for badge setup.**
## Configuration
Basic configuration options:
All options are available via `config.yaml` or `DLC_*` environment variables.
```bash
# Start with default configuration
./scripts/start-server.sh start
| Env var | Default | Description |
|---------|---------|-------------|
| `DLC_SERVER_PORT` | `8080` | Listening port |
| `DLC_SERVER_HOST` | `0.0.0.0` | Bind address |
| `DLC_LOGGING_JSON` | `false` | JSON log format |
| `DLC_LOGGING_OUTPUT` | stderr | Log file path |
| `DLC_SHUTDOWN_TIMEOUT` | `30s` | Graceful shutdown window |
| `DLC_API_V2_ENABLED` | `false` | Enable `/api/v2` routes |
| `DLC_CONFIG_FILE` | `./config.yaml` | Override config path |
# Custom port
export DLC_SERVER_PORT=9090
./scripts/start-server.sh start
See `config.example.yaml` for a full template.
# JSON logging
export DLC_LOGGING_JSON=true
./scripts/start-server.sh start
```
## API
**See [AGENTS.md](AGENTS.md#configuration-management) for comprehensive configuration guide including:**
- File-based configuration
- Environment variables
- Configuration priority rules
- OpenTelemetry setup
- Advanced scenarios
## Usage
### New Cobra CLI (Recommended)
```bash
# 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)
```bash
# 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):**
```bash
# 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:**
```bash
# 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!"}
```
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/health` | Liveness check |
| GET | `/api/ready` | Readiness check (503 during shutdown) |
| GET | `/api/version` | Version info (`?format=plain\|full\|json`) |
| GET | `/api/v1/greet/` | Default greeting |
| GET | `/api/v1/greet/{name}` | Named greeting |
| POST | `/api/v2/greet` | V2 greeting with validation |
| GET | `/swagger/` | Swagger UI |
## Testing
```bash
# Run all tests
go test ./...
# Run specific package tests
go test ./pkg/greet/
go test ./... # unit + integration tests
./scripts/test-graceful-shutdown.sh # lifecycle + JSON logging validation
./scripts/test-opentelemetry.sh # tracing end-to-end
```
## CI/CD
## Gitea Client
dance-lessons-coach includes a comprehensive CI/CD pipeline with multiple testing options:
AI agent helper script at `.vibe/skills/gitea-client/scripts/gitea-client.sh`.
### Local Testing (No Gitea Required)
Auth setup:
```bash
# Validate workflow structure
./scripts/cicd.sh validate
# Test workflow steps locally
./scripts/cicd.sh test-simple
echo "your_token" > ~/.gitea_token
chmod 600 ~/.gitea_token
export GITEA_API_TOKEN_FILE="$HOME/.gitea_token"
```
### Gitea Integration
```bash
# 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
```bash
# Test with docker compose (requires Gitea runner)
./scripts/cicd.sh test-docker
```
**See [adr/0016-ci-cd-pipeline-design.md](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](AGENTS.md#project-structure) 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:
```go
// @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
}
```
Get a token at https://gitea.arcodange.lab → Profile → Settings → Applications.
## Architecture
This project uses Architecture Decision Records (ADRs) to document key technical choices. See [adr/](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](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:**
1. **Create a Personal Access Token:**
- Log in to https://gitea.arcodange.lab
- Go to Profile → Settings → Applications
- Generate token with `read:repository`, `write:repository`, and `read:user` scopes
2. **Configure Authentication:**
```bash
# 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"
```
3. **Add to shell configuration:**
```bash
echo 'export GITEA_API_TOKEN_FILE="$HOME/.gitea_token"' >> ~/.bashrc
source ~/.bashrc
```
**Usage Examples:**
```bash
# 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](.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):
```bash
vibe start --agent dancelessonscoachprogrammer
```
**Product Owner Agent** (for requirements, interviews, documentation):
```bash
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](documentation/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](documentation/GITMOJI_CHEATSHEET.md)
Key decisions are documented in [adr/](adr/). See [AGENTS.md](AGENTS.md) for the full development reference (commands, config, ADR index, commit conventions).
## License