Files
gh-geoffjay-claude-plugins-…/commands/scaffold.md
2025-11-29 18:28:04 +08:00

9.0 KiB

name, description
name description
golang-development:scaffold Scaffold new Go projects with modern structure, Go modules, testing setup, CI/CD pipelines, and best practices

Golang Development Scaffold Command

Create a new Go project with a production-ready structure, modern tooling, and best practices built-in.

Usage

/golang-development:scaffold <project-name> [options]

Arguments

  • $1 - Project name (required, will be used for module name)
  • $2 - Project type: service, cli, library, or microservice (optional, defaults to service)
  • $3 - Additional options as JSON (optional)

Examples

# Create a basic HTTP service
/golang-development:scaffold my-api service

# Create a CLI application
/golang-development:scaffold my-tool cli

# Create a library
/golang-development:scaffold my-lib library

# Create a microservice with full features
/golang-development:scaffold user-service microservice '{"with_grpc": true, "with_db": true}'

Project Structures

Service (HTTP API)

my-api/
├── cmd/
│   └── server/
│       └── main.go
├── internal/
│   ├── handler/
│   │   └── health.go
│   ├── middleware/
│   │   └── logging.go
│   └── service/
│       └── user.go
├── pkg/
│   └── response/
│       └── response.go
├── api/
│   └── openapi.yaml
├── scripts/
│   └── build.sh
├── deployments/
│   ├── Dockerfile
│   └── k8s/
├── go.mod
├── go.sum
├── .gitignore
├── .golangci.yml
├── Makefile
└── README.md

CLI Application

my-tool/
├── cmd/
│   └── my-tool/
│       └── main.go
├── internal/
│   ├── command/
│   │   ├── root.go
│   │   └── serve.go
│   └── config/
│       └── config.go
├── go.mod
├── go.sum
├── .gitignore
├── .golangci.yml
├── Makefile
└── README.md

Library

my-lib/
├── example_test.go
├── lib.go
├── lib_test.go
├── go.mod
├── go.sum
├── .gitignore
├── .golangci.yml
├── LICENSE
└── README.md

Microservice (Full Features)

user-service/
├── cmd/
│   └── server/
│       └── main.go
├── internal/
│   ├── domain/
│   │   └── user.go
│   ├── handler/
│   │   ├── http/
│   │   └── grpc/
│   ├── repository/
│   │   └── postgres/
│   ├── service/
│   │   └── user_service.go
│   └── infrastructure/
│       ├── database/
│       ├── cache/
│       └── messaging/
├── api/
│   ├── http/
│   │   └── openapi.yaml
│   └── grpc/
│       └── user.proto
├── pkg/
│   ├── logger/
│   ├── metrics/
│   └── tracing/
├── migrations/
│   └── 001_create_users.sql
├── deployments/
│   ├── Dockerfile
│   ├── docker-compose.yml
│   └── k8s/
├── scripts/
├── go.mod
├── go.sum
├── .gitignore
├── .golangci.yml
├── Makefile
└── README.md

Generated Files

main.go (Service)

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"

    "{{.ModuleName}}/internal/handler"
    "{{.ModuleName}}/internal/middleware"
)

func main() {
    // Setup router
    mux := http.NewServeMux()

    // Middleware
    handler := middleware.Logging(
        middleware.Recovery(mux),
    )

    // Routes
    mux.HandleFunc("/health", handler.Health)
    mux.HandleFunc("/ready", handler.Ready)

    // Server configuration
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    server := &http.Server{
        Addr:         fmt.Sprintf(":%s", port),
        Handler:      handler,
        ReadTimeout:  15 * time.Second,
        WriteTimeout: 15 * time.Second,
        IdleTimeout:  60 * time.Second,
    }

    // Start server
    go func() {
        log.Printf("Server starting on port %s", port)
        if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("Server error: %v", err)
        }
    }()

    // Graceful shutdown
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    log.Println("Shutting down server...")
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    if err := server.Shutdown(ctx); err != nil {
        log.Fatalf("Server forced to shutdown: %v", err)
    }

    log.Println("Server exited")
}

Makefile

.PHONY: build test lint run clean

# Variables
APP_NAME := {{.ProjectName}}
VERSION := $(shell git describe --tags --always --dirty)
BUILD_TIME := $(shell date -u '+%Y-%m-%d_%H:%M:%S')
LDFLAGS := -ldflags "-X main.Version=$(VERSION) -X main.BuildTime=$(BUILD_TIME)"

# Build
build:
	go build $(LDFLAGS) -o bin/$(APP_NAME) ./cmd/server

# Test
test:
	go test -v -race -coverprofile=coverage.out ./...

# Coverage
coverage:
	go tool cover -html=coverage.out

# Lint
lint:
	golangci-lint run

# Run
run:
	go run ./cmd/server

# Clean
clean:
	rm -rf bin/
	rm -f coverage.out

# Install tools
tools:
	go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

# Docker
docker-build:
	docker build -t $(APP_NAME):$(VERSION) .

docker-run:
	docker run -p 8080:8080 $(APP_NAME):$(VERSION)

Dockerfile

# Build stage
FROM golang:1.21-alpine AS builder

WORKDIR /app

# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/server

# Runtime stage
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Copy binary from builder
COPY --from=builder /app/main .

EXPOSE 8080

CMD ["./main"]

.golangci.yml

linters:
  enable:
    - errcheck
    - gosimple
    - govet
    - ineffassign
    - staticcheck
    - unused
    - gofmt
    - goimports
    - misspell
    - gocritic
    - gosec
    - revive

linters-settings:
  errcheck:
    check-blank: true
  govet:
    check-shadowing: true
  gofmt:
    simplify: true

issues:
  exclude-use-default: false
  max-issues-per-linter: 0
  max-same-issues: 0

GitHub Actions CI (.github/workflows/ci.yml)

name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: Install dependencies
      run: go mod download

    - name: Run tests
      run: go test -v -race -coverprofile=coverage.out ./...

    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        files: ./coverage.out

  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: golangci-lint
      uses: golangci/golangci-lint-action@v3
      with:
        version: latest

  build:
    runs-on: ubuntu-latest
    needs: [test, lint]
    steps:
    - uses: actions/checkout@v3

    - name: Set up Go
      uses: actions/setup-go@v4
      with:
        go-version: '1.21'

    - name: Build
      run: go build -v ./cmd/server

Configuration Options

The command accepts a JSON configuration object:

{
  "with_grpc": true,
  "with_db": true,
  "with_redis": true,
  "with_kafka": true,
  "with_docker": true,
  "with_k8s": true,
  "with_ci": true,
  "db_driver": "postgres",
  "module_path": "github.com/user/project"
}

Implementation Steps

  1. Parse arguments and configuration
  2. Create project directory structure
  3. Initialize Go module
  4. Generate main.go and core files
  5. Create Makefile and build scripts
  6. Add Dockerfile and Docker Compose
  7. Generate CI/CD configuration
  8. Create README with usage instructions
  9. Initialize git repository
  10. Run go mod tidy

Features Included

  • Modern Project Structure: Clean architecture with separation of concerns
  • HTTP Server: Production-ready with graceful shutdown
  • Middleware: Logging, recovery, CORS, authentication templates
  • Health Checks: Health and readiness endpoints
  • Testing: Test structure and examples
  • Linting: golangci-lint configuration
  • CI/CD: GitHub Actions workflow
  • Docker: Multi-stage Dockerfile
  • Kubernetes: Basic manifests (if requested)
  • Documentation: Comprehensive README

Post-Scaffold Steps

After scaffolding, the command will suggest:

cd {{.ProjectName}}
go mod tidy
make test
make run

When to Use

Use this command to:

  • Start new Go projects quickly
  • Ensure consistent project structure
  • Set up best practices from the start
  • Include modern tooling and CI/CD
  • Scaffold microservices or APIs
  • Create CLI tools with proper structure