Skip to content

Commit d4e5826

Browse files
committed
feat: GoLinks initial commit and setup
0 parents  commit d4e5826

31 files changed

Lines changed: 4359 additions & 0 deletions

.air.toml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
root = "."
2+
testdata_dir = "testdata"
3+
tmp_dir = "tmp"
4+
5+
[build]
6+
args_bin = []
7+
bin = "./tmp/main"
8+
cmd = "go build -o ./tmp/main ./cmd/server/main.go"
9+
delay = 1000
10+
exclude_dir = ["assets", "tmp", "vendor", "testdata", "build", "web/static"]
11+
exclude_file = []
12+
exclude_regex = ["_test.go"]
13+
exclude_unchanged = false
14+
follow_symlink = false
15+
full_bin = ""
16+
include_dir = []
17+
include_ext = ["go", "tpl", "tmpl", "html"]
18+
include_file = []
19+
kill_delay = "0s"
20+
log = "build-errors.log"
21+
poll = false
22+
poll_interval = 0
23+
rerun = false
24+
rerun_delay = 500
25+
send_interrupt = false
26+
stop_on_root = false
27+
28+
[color]
29+
app = ""
30+
build = "yellow"
31+
main = "magenta"
32+
runner = "green"
33+
watcher = "cyan"
34+
35+
[log]
36+
main_only = false
37+
time = false
38+
39+
[misc]
40+
clean_on_exit = false
41+
42+
[screen]
43+
clear_on_rebuild = false
44+
keep_scroll = true

.cursor/rules/rules.mdc

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
---
2+
description: Golang rules
3+
globs:
4+
alwaysApply: true
5+
---
6+
You are an expert in Go, microservices architecture, and clean backend development practices. Your role is to ensure code is idiomatic, modular, testable, and aligned with modern best practices and design patterns.
7+
8+
### General Responsibilities:
9+
- Guide the development of idiomatic, maintainable, and high-performance Go code.
10+
- Enforce modular design and separation of concerns through Clean Architecture.
11+
- Promote test-driven development, robust observability, and scalable patterns across services.
12+
13+
### Architecture Patterns:
14+
- Apply **Clean Architecture** by structuring code into handlers/controllers, services/use cases, repositories/data access, and domain models.
15+
- Use **domain-driven design** principles where applicable.
16+
- Prioritize **interface-driven development** with explicit dependency injection.
17+
- Prefer **composition over inheritance**; favor small, purpose-specific interfaces.
18+
- Ensure that all public functions interact with interfaces, not concrete types, to enhance flexibility and testability.
19+
20+
### Project Structure Guidelines:
21+
- Use a consistent project layout:
22+
- cmd/: application entrypoints
23+
- internal/: core application logic (not exposed externally)
24+
- pkg/: shared utilities and packages
25+
- api/: gRPC/REST transport definitions and handlers
26+
- configs/: configuration schemas and loading
27+
- test/: test utilities, mocks, and integration tests
28+
- Group code by feature when it improves clarity and cohesion.
29+
- Keep logic decoupled from framework-specific code.
30+
31+
### Development Best Practices:
32+
- Write **short, focused functions** with a single responsibility.
33+
- Always **check and handle errors explicitly**, using wrapped errors for traceability ('fmt.Errorf("context: %w", err)').
34+
- Avoid **global state**; use constructor functions to inject dependencies.
35+
- Leverage **Go's context propagation** for request-scoped values, deadlines, and cancellations.
36+
- Use **goroutines safely**; guard shared state with channels or sync primitives.
37+
- **Defer closing resources** and handle them carefully to avoid leaks.
38+
39+
### Security and Resilience:
40+
- Apply **input validation and sanitization** rigorously, especially on inputs from external sources.
41+
- Use secure defaults for **JWT, cookies**, and configuration settings.
42+
- Isolate sensitive operations with clear **permission boundaries**.
43+
- Implement **retries, exponential backoff, and timeouts** on all external calls.
44+
- Use **circuit breakers and rate limiting** for service protection.
45+
- Consider implementing **distributed rate-limiting** to prevent abuse across services (e.g., using Redis).
46+
47+
### Testing:
48+
- Write **unit tests** using table-driven patterns and parallel execution.
49+
- **Mock external interfaces** cleanly using generated or handwritten mocks.
50+
- Separate **fast unit tests** from slower integration and E2E tests.
51+
- Ensure **test coverage** for every exported function, with behavioral checks.
52+
- Use tools like 'go test -cover' to ensure adequate test coverage.
53+
54+
### Documentation and Standards:
55+
- Document public functions and packages with **GoDoc-style comments**.
56+
- Provide concise **READMEs** for services and libraries.
57+
- Maintain a 'CONTRIBUTING.md' and 'ARCHITECTURE.md' to guide team practices.
58+
- Enforce naming consistency and formatting with 'go fmt', 'goimports', and 'golangci-lint'.
59+
60+
### Observability with OpenTelemetry:
61+
- Use **OpenTelemetry** for distributed tracing, metrics, and structured logging.
62+
- Start and propagate tracing **spans** across all service boundaries (HTTP, gRPC, DB, external APIs).
63+
- Always attach 'context.Context' to spans, logs, and metric exports.
64+
- Use **otel.Tracer** for creating spans and **otel.Meter** for collecting metrics.
65+
- Record important attributes like request parameters, user ID, and error messages in spans.
66+
- Use **log correlation** by injecting trace IDs into structured logs.
67+
- Export data to **OpenTelemetry Collector**, **Jaeger**, or **Prometheus**.
68+
69+
### Tracing and Monitoring Best Practices:
70+
- Trace all **incoming requests** and propagate context through internal and external calls.
71+
- Use **middleware** to instrument HTTP and gRPC endpoints automatically.
72+
- Annotate slow, critical, or error-prone paths with **custom spans**.
73+
- Monitor application health via key metrics: **request latency, throughput, error rate, resource usage**.
74+
- Define **SLIs** (e.g., request latency < 300ms) and track them with **Prometheus/Grafana** dashboards.
75+
- Alert on key conditions (e.g., high 5xx rates, DB errors, Redis timeouts) using a robust alerting pipeline.
76+
- Avoid excessive **cardinality** in labels and traces; keep observability overhead minimal.
77+
- Use **log levels** appropriately (info, warn, error) and emit **JSON-formatted logs** for ingestion by observability tools.
78+
- Include unique **request IDs** and trace context in all logs for correlation.
79+
80+
### Performance:
81+
- Use **benchmarks** to track performance regressions and identify bottlenecks.
82+
- Minimize **allocations** and avoid premature optimization; profile before tuning.
83+
- Instrument key areas (DB, external calls, heavy computation) to monitor runtime behavior.
84+
85+
### Concurrency and Goroutines:
86+
- Ensure safe use of **goroutines**, and guard shared state with channels or sync primitives.
87+
- Implement **goroutine cancellation** using context propagation to avoid leaks and deadlocks.
88+
89+
### Tooling and Dependencies:
90+
- Rely on **stable, minimal third-party libraries**; prefer the standard library where feasible.
91+
- Use **Go modules** for dependency management and reproducibility.
92+
- Version-lock dependencies for deterministic builds.
93+
- Integrate **linting, testing, and security checks** in CI pipelines.
94+
95+
### Key Conventions:
96+
1. Prioritize **readability, simplicity, and maintainability**.
97+
2. Design for **change**: isolate business logic and minimize framework lock-in.
98+
3. Emphasize clear **boundaries** and **dependency inversion**.
99+
4. Ensure all behavior is **observable, testable, and documented**.
100+
5. **Automate workflows** for testing, building, and deployment.

.github/workflows/ci.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
jobs:
10+
test:
11+
name: Test
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Check out code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v4
20+
with:
21+
go-version: 1.25
22+
23+
- name: Cache Go modules
24+
uses: actions/cache@v3
25+
with:
26+
path: |
27+
~/.cache/go-build
28+
~/go/pkg/mod
29+
key: ${{ runner.os }}-go-1.25-${{ hashFiles('**/go.sum') }}
30+
restore-keys: |
31+
${{ runner.os }}-go-1.25-
32+
33+
- name: Download dependencies
34+
run: go mod download
35+
36+
- name: Check formatting
37+
run: |
38+
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
39+
echo "The following files are not formatted correctly:"
40+
gofmt -s -l .
41+
echo "Please run 'go fmt ./...' or 'make fmt' to fix formatting"
42+
exit 1
43+
fi
44+
45+
- name: Run golangci-lint
46+
uses: golangci/golangci-lint-action@v3
47+
with:
48+
version: latest
49+
args: --timeout=5m
50+
51+
- name: Run tests
52+
run: go test -v -race -coverprofile=coverage.out ./...
53+
54+
- name: Show test coverage
55+
run: go tool cover -func=coverage.out

.gitignore

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Binaries for programs and plugins
2+
*.exe
3+
*.exe~
4+
*.dll
5+
*.so
6+
*.dylib
7+
8+
# Test binary, built with `go test -c`
9+
*.test
10+
11+
# Output of the go coverage tool, specifically when used with LiteIDE
12+
*.out
13+
14+
# Dependency directories (remove the comment below to include it)
15+
# vendor/
16+
17+
# Go workspace file
18+
go.work
19+
20+
# Build directory
21+
build/
22+
tmp/
23+
24+
# Database files
25+
*.db
26+
*.sqlite
27+
*.sqlite3
28+
29+
# Environment files
30+
.env
31+
.env.local
32+
.env.*.local
33+
34+
# IDE files
35+
.vscode/
36+
.idea/
37+
*.swp
38+
*.swo
39+
*~
40+
41+
# OS generated files
42+
.DS_Store
43+
.DS_Store?
44+
._*
45+
.Spotlight-V100
46+
.Trashes
47+
ehthumbs.db
48+
Thumbs.db
49+
50+
# Coverage files
51+
coverage.out
52+
coverage.html
53+
54+
# Log files
55+
*.log
56+
build-errors.log
57+
58+
# Air temporary files
59+
tmp/
60+
61+
# Docker volumes
62+
data/
63+
64+
# Node modules (if any frontend tooling is added)
65+
node_modules/
66+
67+
# Backup files
68+
*.bak
69+
*.backup
70+
71+
# Test databases
72+
test.db
73+
migrate_test.db
74+
test_fk.db
75+
76+
# GoLinks specific
77+
golinks
78+
golinks.exe
79+
80+
# Temporary files from tests
81+
*.tmp

.golangci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
run:
2+
timeout: 5m
3+
tests: true
4+
5+
issues:
6+
exclude-dirs:
7+
- vendor
8+
- tmp
9+
- build
10+
11+
linters-settings:
12+
gofmt:
13+
simplify: true
14+
15+
goimports:
16+
local-prefixes: golinks
17+
18+
lll:
19+
line-length: 140
20+
21+
linters:
22+
enable:
23+
- errcheck
24+
- gosimple
25+
- govet
26+
- ineffassign
27+
- staticcheck
28+
- typecheck
29+
- unused
30+
- gofmt
31+
- goimports
32+
- misspell
33+
- lll
34+
35+
exclude-rules:
36+
- path: _test\.go
37+
linters:
38+
- lll

Dockerfile

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Build stage
2+
FROM golang:1.21-alpine AS builder
3+
4+
# Install build dependencies
5+
RUN apk add --no-cache gcc musl-dev sqlite-dev
6+
7+
# Set working directory
8+
WORKDIR /app
9+
10+
# Copy go mod files
11+
COPY go.mod go.sum ./
12+
13+
# Download dependencies
14+
RUN go mod download
15+
16+
# Copy source code
17+
COPY . .
18+
19+
# Build the application
20+
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o golinks ./cmd/server
21+
22+
# Final stage
23+
FROM alpine:3.18
24+
25+
# Install runtime dependencies
26+
RUN apk add --no-cache ca-certificates sqlite tzdata
27+
28+
# Create non-root user
29+
RUN addgroup -g 1001 -S golinks && \
30+
adduser -u 1001 -S golinks -G golinks
31+
32+
# Set working directory
33+
WORKDIR /app
34+
35+
# Copy binary from builder stage
36+
COPY --from=builder /app/golinks .
37+
38+
# Copy web assets
39+
COPY --from=builder /app/web ./web
40+
41+
# Create data directory for SQLite database
42+
RUN mkdir -p /app/data && chown -R golinks:golinks /app
43+
44+
# Switch to non-root user
45+
USER golinks
46+
47+
# Expose port
48+
EXPOSE 8080
49+
50+
# Health check
51+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
52+
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/homepage/ || exit 1
53+
54+
# Set environment variables
55+
ENV PORT=8080
56+
ENV DATABASE_PATH=/app/data/golinks.db
57+
ENV BASE_URL=http://localhost:8080
58+
ENV ENVIRONMENT=production
59+
60+
# Run the application
61+
CMD ["./golinks"]

0 commit comments

Comments
 (0)