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

457 lines
9.0 KiB
Markdown

---
name: golang-development:scaffold
description: 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
```bash
/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
```bash
# 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)
```go
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
```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
```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
```yaml
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)
```yaml
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:
```json
{
"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:
```bash
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