diff --git a/.githooks/commit-msg b/.githooks/commit-msg index 3fac2ad..3869ee0 100755 --- a/.githooks/commit-msg +++ b/.githooks/commit-msg @@ -2,22 +2,95 @@ # Validates commit messages against the Conventional Commits spec. # Activate with: git config core.hooksPath .githooks +set -e + MSG=$(cat "$1") -# Strip comments and trailing whitespace -SUBJECT=$(echo "$MSG" | sed '/^#/d' | head -1 | sed 's/[[:space:]]*$//') +# Strip git comments (lines starting with #) to get the actual message +SUBJECT=$(echo "$MSG" | grep -v '^#' | head -1) + +# Remove trailing whitespace +SUBJECT=$(echo "$SUBJECT" | sed 's/[[:space:]]*$//') + +# Validate commit message format: type(scope): subject +# Types: feat, fix, docs, style, refactor, perf, test, chore, ci, revert +# Scope is optional +# Subject must be lowercase, start with lowercase, no period at end +# Max length: 100 characters for full header, 72 for subject line + +TYPE_PATTERN='feat|fix|docs|style|refactor|perf|test|chore|ci|revert' +SCOPE_PATTERN='[a-z0-9\-]*' -PATTERN='^(feat|fix|refactor|test|docs|chore|perf|ci)(\(.+\))?(!)?: .{1,72}$' +# Full pattern: type(scope): subject +# Where scope is optional +if echo "$SUBJECT" | grep -qE "^(${TYPE_PATTERN})(\(${SCOPE_PATTERN}\))?: .+\$"; then + # Check length + LENGTH=$(echo "$SUBJECT" | wc -c) + if [ "$LENGTH" -gt 101 ]; then + echo "" + echo " ✗ Commit message rejected — header exceeds 100 characters." + echo "" + echo " Length: $LENGTH (max: 100)" + echo " Your message: $SUBJECT" + echo "" + exit 1 + fi -if ! echo "$SUBJECT" | grep -qE "$PATTERN"; then + # Check subject line (after ": ") is not empty and doesn't end with period + SUBJECT_TEXT=$(echo "$SUBJECT" | sed 's/^[^:]*: //') + if [ -z "$SUBJECT_TEXT" ]; then + echo "" + echo " ✗ Commit message rejected — missing description after colon." + echo "" + exit 1 + fi + + if echo "$SUBJECT_TEXT" | grep -q '\.$'; then + echo "" + echo " ✗ Commit message rejected — subject should not end with a period." + echo "" + echo " Your message: $SUBJECT" + echo "" + exit 1 + fi + + # Check first letter after colon+space is lowercase + FIRST_CHAR=$(echo "$SUBJECT_TEXT" | sed 's/^.//') + if ! echo "$SUBJECT_TEXT" | grep -qE '^[a-z]'; then + echo "" + echo " ✗ Commit message rejected — subject must start with lowercase letter." + echo "" + echo " Your message: $SUBJECT" + echo "" + exit 1 + fi + + exit 0 +else echo "" - echo " Commit message rejected — does not follow Conventional Commits." + echo " ✗ Commit message rejected — does not follow Conventional Commits." echo "" - echo " Format : (): " + echo " Format: (): " echo " Example: feat(auth): add refresh token rotation" echo "" - echo " Allowed types: feat | fix | refactor | test | docs | chore | perf | ci" - echo " Subject must be lowercase and under 72 characters." + echo " Allowed types:" + echo " • feat — new feature" + echo " • fix — bug fix" + echo " • docs — documentation" + echo " • style — code style (formatting, semicolons, etc)" + echo " • refactor — code refactoring without feature change" + echo " • perf — performance improvement" + echo " • test — test changes" + echo " • chore — dependency or tooling change" + echo " • ci — CI/CD changes" + echo " • revert — revert a previous commit" + echo "" + echo " Rules:" + echo " • Type and scope are lowercase" + echo " • Scope is optional" + echo " • Subject starts with lowercase" + echo " • No period at end" + echo " • Max 100 characters" echo "" echo " Your message: $SUBJECT" echo "" diff --git a/.githooks/pre-push b/.githooks/pre-push index 3f9840e..8bebf8b 100755 --- a/.githooks/pre-push +++ b/.githooks/pre-push @@ -5,10 +5,10 @@ # Uncomment and adapt the checks below to match your project's tooling. # Remove checks that don't apply. Keep this hook fast — slow hooks get bypassed. -# echo "Running tests before push..." -# your-test-command || exit 1 +echo "Running tests before push..." +make test || exit 1 -# echo "Running build check..." -# your-build-command || exit 1 +echo "Running build check..." +make build || exit 1 exit 0 diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index a1ec744..12e9e40 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -3,6 +3,8 @@ name: Commitlint on: pull_request: branches: [main] + push: + branches: [main] jobs: commitlint: @@ -13,8 +15,10 @@ jobs: with: fetch-depth: 0 - - name: Check commit messages + - name: Validate commit messages uses: wagoid/commitlint-github-action@v6 with: + configFile: .commitlintrc.json failOnWarnings: false helpURL: https://www.conventionalcommits.org + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3cc6135..b9fcd19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,74 +72,149 @@ Open a **Feature Request** issue with: Features that align with the project's scope and architecture are more likely to be accepted. -### Activating the commit-msg hook +### Activating git hooks -A shell-based hook validates commit messages locally against the Conventional Commits spec. Activate it once after cloning — no runtime or dependencies required: +Git hooks validate commit messages locally and prevent commits that don't follow our conventions. Activate them once after cloning: +**Using Make (recommended):** +```bash +make hooks +``` + +**Or manually:** ```bash git config core.hooksPath .githooks +chmod +x .githooks/commit-msg ``` -Commit messages are also validated in CI on every PR via GitHub Actions. +Commit messages are validated: +- **Locally** — before commit (via `.githooks/commit-msg` hook) +- **In CI** — on every PR (via GitHub Actions with commitlint) + +**View commit rules anytime:** +```bash +make commit-lint +``` ### Submitting Code Changes -1. Create a branch from `main`: +1. **Create a branch** from `main`: ```bash git checkout main git pull upstream main git checkout -b feat/your-feature-name ``` -2. Make your changes following the [code style](#code-style) guidelines -3. Write or update tests -4. Run the validation suite locally (see [Development Setup](docs/getting-started/README.md)) -5. Commit following [commit conventions](#commit-conventions) -6. Push and open a Pull Request + +2. **Make your changes** following the [code style](#code-style) guidelines + +3. **Write or update tests** as needed + +4. **Run validation locally**: + ```bash + make validate + ``` + This runs: format → vet → lint → tests (with nice colored output) + +5. **Commit following [commit conventions](#commit-conventions)**: + ```bash + git commit -m "feat(scope): your message" + ``` + Your commit message will be validated automatically by the local hook. + +6. **Push and open a Pull Request**: + ```bash + git push origin feat/your-feature-name + ``` + +**Before submitting the PR, verify:** +- [ ] All validations pass (`make validate`) +- [ ] Commits follow Conventional Commits (`make commit-lint` to review rules) +- [ ] Tests pass (`make test`) +- [ ] Code is formatted (`make fmt`) +- [ ] Documentation is updated if needed --- ## Commit Conventions -We follow **Conventional Commits**. Each commit message should be: +We follow **Conventional Commits** format. Messages are validated both locally (via git hook) and in CI. + +### Format ``` -(): +(): [optional body] [optional footer] ``` -**Types:** +### Types | Type | When to use | |------------|---------------------------------------| | `feat` | New feature or behavior | | `fix` | Bug fix | +| `docs` | Documentation only | +| `style` | Code style (formatting, semicolons) | | `refactor` | Code change with no behavior change | +| `perf` | Performance improvement | | `test` | Adding or updating tests | -| `docs` | Documentation only | | `chore` | Tooling, dependencies, config | -| `perf` | Performance improvement | | `ci` | CI/CD changes | +| `revert` | Revert a previous commit | + +**Scope** (optional): the module or area affected, e.g. `auth`, `api`, `generators`, `docker`. -**Scope** (optional): the module or area affected, e.g. `auth`, `api`, `ui`, `docker`. +### Examples -**Examples:** +✅ **Good examples:** ``` -feat(auth): add refresh token revocation on logout -fix(api): return 409 when resource already exists -refactor(core): extract validation to separate utility -test(auth): add unit tests for login use case -docs(setup): add environment variable reference -chore(deps): upgrade dependencies +feat: add user authentication +feat(api): add rate limiting middleware +fix(generators): handle empty project spec +docs(readme): update installation steps +refactor(survey): extract validation logic +test: add test for spec validation +chore: update dependencies +ci: add commitlint to GitHub Actions ``` -**Rules:** +❌ **Bad examples (will be rejected):** +``` +Add user auth # Missing type +FEAT: add auth # Type not lowercase +feat: Add auth. # Description starts with uppercase, ends with period +feat(api): this is a very long commit message that exceeds the 100 character limit # Too long +``` + +### Rules + +- **Type is required** and must be lowercase +- **Scope is optional** (lowercase) and indicates what part changed +- **Description is required**, starts with lowercase, no period at end +- **Max 100 characters** for the full header (subject line) - Use the **imperative mood** ("add" not "adds" or "added") -- Keep the first line under **72 characters** - Reference issues in the footer: `Closes #42`, `Fixes #17` +### Local Validation + +Your commits are validated automatically before creation. If the message is invalid, the commit is rejected with a helpful error message. + +**To see validation rules:** +```bash +make commit-lint +``` + +**If a commit is rejected, fix and try again:** +```bash +git commit --amend -m "feat(scope): corrected message" +``` + +### CI Validation + +Commits are also validated in GitHub Actions using commitlint with the `.commitlintrc.json` configuration. This ensures consistency across all contributions. + --- ## Pull Request Process diff --git a/README.md b/README.md index 0ee4722..4a58eac 100644 --- a/README.md +++ b/README.md @@ -65,25 +65,34 @@ See [docs/getting-started](docs/getting-started/README.md) for the full setup gu ## Development +We use a **Makefile** for convenient command execution with clean, colored output: + ```bash -# Build the CLI binary -go build -o scaffold ./cmd/scaffold +# See all available commands +make help -# Run the CLI directly (interactive questionnaire) -go run ./cmd/scaffold new +# Build and run the CLI +make scaffold -# Run tests -go test ./... +# Run validation suite (fmt → vet → lint → test) +make validate -# Run tests with coverage -go test -v -coverprofile=coverage.out ./... -go tool cover -html=coverage.out +# Individual commands +make build # Build to bin/scaffold +make test # Run tests +make fmt # Format code +make lint # Lint code +make clean # Remove build artifacts +``` -# Format code -go fmt ./... +**Or use raw Go commands:** -# Lint code -golangci-lint run ./... +```bash +go build -o scaffold ./cmd/scaffold # Build +go run ./cmd/scaffold # Run +go test ./... # Test +go fmt ./... # Format +golangci-lint run ./... # Lint ``` --- diff --git a/docs/developer-guide/faq.md b/docs/developer-guide/faq.md index 8df389a..aaa5e4f 100644 --- a/docs/developer-guide/faq.md +++ b/docs/developer-guide/faq.md @@ -29,11 +29,29 @@ See [Architecture Documentation](../../.claude/ressources/Architecture.md) for d ## Development +**Q: What's the easiest way to build and run?** +Use the Makefile: +```bash +make scaffold # Build and run with colored output +make run # Run without building +make build # Just build to bin/scaffold +``` + +See all available commands: +```bash +make help +``` + **Q: How do I run a specific test?** ```bash go test -v ./internal/generators -run TestAPIGenerator ``` +Or use the test target: +```bash +make test +``` + **Q: How do I debug a generator?** Add print statements or use a debugger like Delve: ```bash @@ -47,7 +65,18 @@ dlv debug ./cmd/scaffold - Check if your system's temp directory has enough space **Q: The build fails with module not found errors.** -Pull the latest `main` and run `go mod download` — a dependency may have been updated. +Pull the latest `main` and run: +```bash +go mod download +``` + +**Q: How do I validate all my changes before submitting a PR?** +Run the full validation suite: +```bash +make validate +``` + +This runs: formatting → vet → lint → tests (all with nice colored output) **Q: How do I add a new generator?** See [Adding a Generator](#adding-a-generator) below. @@ -91,12 +120,29 @@ Yes for new features and bug fixes. Documentation-only PRs are exempt. Maintainers merge PRs once they have one approving review and all CI checks are green. **Q: What's the PR submission checklist?** -- [ ] Tests pass: `go test ./...` -- [ ] Code is formatted: `go fmt ./...` -- [ ] Linter passes: `golangci-lint run ./...` +Run this before submitting: +```bash +make validate +``` + +This checks: +- [ ] Code is formatted +- [ ] Vet passes (suspicious constructs) +- [ ] Linter passes (style violations) +- [ ] Tests pass + +Then verify: - [ ] Documentation is updated - [ ] Commit messages follow conventions (see [Code Style](guidelines/code-style.md)) +**Manual commands (if needed):** +```bash +go fmt ./... # Format +go vet ./... # Vet check +golangci-lint run ./... # Lint +go test ./... # Tests +``` + --- Still stuck? Open a [Discussion](../../../discussions). diff --git a/docs/developer-guide/guidelines/code-style.md b/docs/developer-guide/guidelines/code-style.md index f1e0999..73a5de1 100644 --- a/docs/developer-guide/guidelines/code-style.md +++ b/docs/developer-guide/guidelines/code-style.md @@ -6,21 +6,28 @@ This document defines the code style and formatting conventions for Scaffold CLI ## Tooling -We use standard Go tooling to enforce code quality: +We use standard Go tooling to enforce code quality. **Use the Makefile for easy access:** ```bash -# Format code (auto-fixes formatting) -go fmt ./... - -# Lint code (requires golangci-lint) -golangci-lint run ./... +# Run ALL checks in sequence (recommended) +make validate + +# Individual checks: +make fmt # Format code +make vet # Vet check +make lint # Lint code +make test # Run tests with race detector +``` -# Vet code for suspicious constructs -go vet ./... +**Or use raw Go commands:** -# Check for code coverage -go test -coverprofile=coverage.out ./... -go tool cover -html=coverage.out +```bash +go fmt ./... # Format code +go vet ./... # Vet for suspicious constructs +golangci-lint run ./... # Lint code +go test -race ./... # Run tests with race detector +go test -coverprofile=coverage.out ./... # Check coverage +go tool cover -html=coverage.out # View coverage report ``` All checks must pass before a PR can be merged. The CI pipeline enforces this automatically with: @@ -185,36 +192,46 @@ import ( ## Running the Full Validation Suite -Before pushing or submitting a PR, run the complete validation suite: +**Recommended: Use the Makefile** -```bash -# 1. Format code -go fmt ./... +Before pushing or submitting a PR, run: -# 2. Import organization -goimports -w ./... +```bash +make validate +``` -# 3. Vet for suspicious constructs -go vet ./... +This executes in sequence with pretty colored output: +1. ✓ Formats code +2. ✓ Vet checks +3. ✓ Linting +4. ✓ Tests with race detector -# 4. Lint -golangci-lint run ./... +**Or run individual checks:** -# 5. Run tests with coverage and race detector -go test -race -coverprofile=coverage.out ./... +```bash +make fmt # Step 1 +make vet # Step 2 +make lint # Step 3 +make test # Step 4 +make build # Step 5 +``` -# 6. Check coverage -go tool cover -func=coverage.out +**Raw Go commands (if needed):** -# 7. Build -go build -o scaffold ./cmd/scaffold +```bash +# Complete validation +go fmt ./... && \ +go vet ./... && \ +golangci-lint run ./... && \ +go test -race -coverprofile=coverage.out ./... && \ +go build -o bin/scaffold ./cmd/scaffold && \ +echo "✓ All checks passed!" ``` -**All checks must pass before pushing.** Quick version: +**Check code coverage:** ```bash -go fmt ./... && goimports -w ./... && go vet ./... && \ -golangci-lint run ./... && go test -race ./... && \ -go build -o scaffold ./cmd/scaffold && \ -echo "✓ All checks passed!" +go test -coverprofile=coverage.out ./... +go tool cover -html=coverage.out # Opens in browser +go tool cover -func=coverage.out # Shows percentages ``` diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index 241959d..90f7479 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -22,12 +22,14 @@ This guide walks you through setting up Scaffold CLI for local development. cd scaffold-cli ``` -2. **Activate the commit-msg hook** (one-time, after cloning) +2. **Activate git hooks** (one-time, after cloning) ```bash - git config core.hooksPath .githooks + make hooks ``` + This activates commit message linting. Your commits will now be validated locally before being created. + 3. **Download dependencies** ```bash @@ -44,6 +46,55 @@ This guide walks you through setting up Scaffold CLI for local development. --- +## Commit Message Convention + +We follow **Conventional Commits** format. Commit messages are validated automatically. + +### Format + +``` +(): +``` + +### Examples + +```bash +git commit -m "feat: add new generator" +git commit -m "fix(api): handle empty responses" +git commit -m "docs(readme): update installation steps" +git commit -m "refactor(generators): extract common logic" +``` + +### Types + +- `feat` — new feature +- `fix` — bug fix +- `docs` — documentation +- `style` — code style (formatting, etc) +- `refactor` — refactoring +- `perf` — performance +- `test` — tests +- `chore` — dependencies/tooling +- `ci` — CI/CD +- `revert` — revert commit + +**Rules:** +- Type is required (lowercase) +- Scope is optional (lowercase) +- Description starts with lowercase +- No period at end +- Max 100 characters + +View commit rules anytime: + +```bash +make commit-lint +``` + +For details, see [CONTRIBUTING.md](../../CONTRIBUTING.md). + +--- + ## Project Structure Here's what you'll work with: @@ -67,28 +118,47 @@ For details, see the [Architecture Documentation](../../.claude/ressources/Archi ## Common Commands +We use a `Makefile` for convenient command execution. All commands produce clean, colored output: + ```bash -# Build the CLI binary -go build -o scaffold ./cmd/scaffold +# Show available commands +make help -# Run the interactive CLI -go run ./cmd/scaffold new +# Build and run the interactive CLI +make scaffold -# Run all tests -go test ./... +# Build the binary into bin/scaffold +make build -# Run tests with coverage -go test -v -coverprofile=coverage.out ./... -go tool cover -html=coverage.out +# Run CLI directly (without building) +make run -# Format all Go code -go fmt ./... +# Format code +make fmt + +# Lint code +make lint + +# Run tests with race detector +make test -# Lint code (requires golangci-lint) -golangci-lint run ./... +# Run full validation (fmt → vet → lint → test) +make validate -# Run linter and tests together -go fmt ./... && golangci-lint run ./... && go test ./... +# Clean up build artifacts +make clean + +# Install development tools (golangci-lint, goimports) +make install-tools +``` + +**Or use raw Go commands:** + +```bash +go build -o scaffold ./cmd/scaffold +go run ./cmd/scaffold +go test ./... +go fmt ./... ``` --- diff --git a/makefile b/makefile new file mode 100644 index 0000000..acb77c9 --- /dev/null +++ b/makefile @@ -0,0 +1,172 @@ +.PHONY: help fmt lint build scaffold test clean vet run install-tools validate commit-lint hooks + +# Colors +RED := \033[0;31m +GREEN := \033[0;32m +YELLOW := \033[0;33m +BLUE := \033[0;34m +CYAN := \033[0;36m +BOLD := \033[1m +RESET := \033[0m + +# Variables +BINARY_NAME=scaffold +BIN_DIR=bin +GO=go +GOFLAGS=-v + +# Helper functions +define print_header + @echo "$(CYAN)╔════════════════════════════════════════════════════════════╗$(RESET)" + @echo "$(CYAN)║ $(BOLD)$(1)$(RESET)$(CYAN)$(2)║$(RESET)" + @echo "$(CYAN)╚════════════════════════════════════════════════════════════╝$(RESET)" +endef + +define print_success + @echo "$(GREEN)✓ $(1)$(RESET)" +endef + +define print_info + @echo "$(BLUE)→ $(1)$(RESET)" +endef + +define print_warning + @echo "$(YELLOW)⚠ $(1)$(RESET)" +endef + +help: ## Display this help screen + @echo "" + @echo "$(BOLD)$(CYAN)Scaffold CLI - Make Targets$(RESET)" + @echo "$(CYAN)════════════════════════════════════════════$(RESET)" + @echo "" + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " $(CYAN)%-18s$(RESET) %s\n", $$1, $$2}' + @echo "" + @echo "$(YELLOW)Examples:$(RESET)" + @echo " make scaffold # Build and run the CLI" + @echo " make validate # Run all checks (fmt → vet → lint → test)" + @echo " make clean # Remove build artifacts" + @echo "" + +fmt: ## Format Go code + $(call print_header,"FMT"," ") + $(call print_info,"Formatting code...") + @$(GO) fmt ./... + $(call print_success,"Code formatted") + @echo "" + +lint: ## Lint Go code with golangci-lint + $(call print_header,"LINT"," ") + $(call print_info,"Running linter...") + @golangci-lint run ./... || (echo "$(RED)✗ Linting failed$(RESET)"; exit 1) + $(call print_success,"Linting passed") + @echo "" + +vet: ## Run go vet to check for suspicious constructs + $(call print_header,"VET"," ") + $(call print_info,"Checking for suspicious constructs...") + @$(GO) vet ./... || (echo "$(RED)✗ Vet check failed$(RESET)"; exit 1) + $(call print_success,"Vet check passed") + @echo "" + +test: ## Run all tests with race detector + $(call print_header,"TEST"," ") + $(call print_info,"Running tests...") + @$(GO) test -race -v ./... || (echo "$(RED)✗ Tests failed$(RESET)"; exit 1) + $(call print_success,"All tests passed") + @echo "" + +build: fmt vet ## Build the scaffold binary into bin/ directory + $(call print_header,"BUILD"," ") + $(call print_info,"Building $(BINARY_NAME)...") + @mkdir -p $(BIN_DIR) + @$(GO) build $(GOFLAGS) -o $(BIN_DIR)/$(BINARY_NAME) ./cmd/scaffold 2>&1 | grep -v "^$(BIN_DIR)" || true + $(call print_success,"Binary built: $(BIN_DIR)/$(BINARY_NAME)") + @echo "" + +scaffold: build ## Build and run the scaffold CLI + $(call print_header,"SCAFFOLD"," ") + $(call print_info,"Starting Scaffold CLI...") + @echo "" + @$(BIN_DIR)/$(BINARY_NAME) + @echo "" + +run: ## Run scaffold directly (without building) + $(call print_header,"RUN"," ") + $(call print_info,"Running Scaffold CLI...") + @echo "" + @$(GO) run ./cmd/scaffold + @echo "" + +clean: ## Remove build artifacts + $(call print_header,"CLEAN"," ") + $(call print_info,"Removing build artifacts...") + @rm -rf $(BIN_DIR) + @$(GO) clean + $(call print_success,"Clean complete") + @echo "" + +hooks: ## Activate git hooks for commit linting + $(call print_header,"SETUP HOOKS"," ") + $(call print_info,"Activating git hooks...") + @git config core.hooksPath .githooks + @chmod +x .githooks/commit-msg .githooks/pre-push + $(call print_success,"Git hooks activated") + @echo "$(BLUE)→ Commit messages will now be validated locally$(RESET)" + @echo "" + +install-tools: ## Install required development tools + $(call print_header,"INSTALL-TOOLS"," ") + $(call print_info,"Installing development tools...") + @echo " • Installing golangci-lint..." + @$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest > /dev/null 2>&1 + @echo " • Installing goimports..." + @$(GO) install golang.org/x/tools/cmd/goimports@latest > /dev/null 2>&1 + $(call print_success,"Tools installed") + @echo "" + +commit-lint: ## Validate commit messages (shows format rules) + $(call print_header,"COMMIT LINT"," ") + @echo "" + @echo "$(BOLD)Conventional Commits Format$(RESET)" + @echo "$(BLUE)────────────────────────────────────────────────$(RESET)" + @echo "" + @echo " $(CYAN)(): $(RESET)" + @echo "" + @echo "$(YELLOW)Allowed types:$(RESET)" + @echo " • feat — new feature" + @echo " • fix — bug fix" + @echo " • docs — documentation" + @echo " • style — code style (formatting, semicolons, etc)" + @echo " • refactor — code refactoring without feature change" + @echo " • perf — performance improvement" + @echo " • test — test changes" + @echo " • chore — dependency or tooling change" + @echo " • ci — CI/CD changes" + @echo " • revert — revert a previous commit" + @echo "" + @echo "$(YELLOW)Rules:$(RESET)" + @echo " • Type and scope are lowercase" + @echo " • Scope is optional" + @echo " • Description starts with lowercase" + @echo " • No period at end" + @echo " • Max 100 characters" + @echo "" + @echo "$(YELLOW)Examples:$(RESET)" + @echo " feat: add user authentication" + @echo " fix(api): handle null responses" + @echo " docs(readme): update setup instructions" + @echo " refactor(generators): extract common logic" + @echo "" + +validate: fmt vet lint test ## Run full validation suite + @echo "" + $(call print_header,"VALIDATION PASSED"," ") + @echo "$(GREEN)" + @echo " ✓ Code formatted" + @echo " ✓ Vet checks passed" + @echo " ✓ Linting passed" + @echo " ✓ Tests passed" + @echo "$(RESET)" + @echo "" + +.DEFAULT_GOAL := help