Skip to content

Commit 64378e2

Browse files
build: initial commit
1 parent 721feda commit 64378e2

37 files changed

Lines changed: 3933 additions & 0 deletions

.dockerignore

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Git
2+
.git
3+
.gitignore
4+
5+
# IDE
6+
.idea
7+
.vscode
8+
*.swp
9+
*.swo
10+
11+
# Environment files (secrets)
12+
.env
13+
*.pem
14+
15+
# Build artifacts
16+
gitvigil
17+
*.exe
18+
*.dll
19+
*.so
20+
*.dylib
21+
22+
# Test files
23+
*_test.go
24+
coverage.out
25+
coverage.html
26+
27+
# Documentation
28+
*.md
29+
!README.md
30+
docs/
31+
32+
# Docker files (not needed in context)
33+
docker-compose*.yml
34+
Dockerfile*
35+
36+
# Misc
37+
.DS_Store
38+
Thumbs.db
39+
tmp/

.env.example

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# GitVigil Environment Configuration
2+
# Copy this file to .env and fill in your values
3+
4+
# ===================
5+
# GitHub App Settings
6+
# ===================
7+
# Get these from your GitHub App settings page
8+
GITHUB_APP_ID=your_app_id
9+
GITHUB_APP_CLIENT_ID=your_client_id
10+
GITHUB_APP_CLIENT_SECRET=your_client_secret
11+
12+
# Webhook secret (set in GitHub App settings)
13+
GITHUB_WEBHOOK_SECRET=your_webhook_secret
14+
15+
# Path to your GitHub App's private key PEM file
16+
GITHUB_PRIVATE_KEY_PATH=./your-app.private-key.pem
17+
18+
# ===================
19+
# Database Settings
20+
# ===================
21+
# PostgreSQL connection string
22+
# For Docker Compose: postgres://gitvigil:gitvigil@db:5432/gitvigil?sslmode=disable
23+
# For local dev: postgres://postgres:postgres@localhost:5432/gitvigil?sslmode=disable
24+
DATABASE_URL=postgres://gitvigil:gitvigil@localhost:5432/gitvigil?sslmode=disable
25+
26+
# Database password (used by Docker Compose)
27+
DB_PASSWORD=gitvigil
28+
29+
# ===================
30+
# Server Settings
31+
# ===================
32+
PORT=8080
33+
BASE_URL=https://your-domain.com
34+
35+
# ===================
36+
# Detection Thresholds
37+
# ===================
38+
# Hours after which a commit is flagged as suspicious (default: 24)
39+
BACKDATE_SUSPICIOUS_HOURS=24
40+
41+
# Hours after which a commit is flagged as critical (default: 72)
42+
BACKDATE_CRITICAL_HOURS=72
43+
44+
# Hours of inactivity before streak is at risk (default: 72)
45+
STREAK_INACTIVITY_HOURS=72

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.temp/*
2+
*.pem
3+
.env
4+

Dockerfile

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# =============================================================================
2+
# GitVigil Dockerfile
3+
# Multi-stage build for minimal, secure production image
4+
# =============================================================================
5+
6+
# -----------------------------------------------------------------------------
7+
# Build Stage
8+
# -----------------------------------------------------------------------------
9+
FROM golang:1.23-alpine AS builder
10+
11+
# Install build dependencies
12+
RUN apk add --no-cache git ca-certificates tzdata
13+
14+
# Create non-root user for runtime
15+
RUN adduser -D -g '' appuser
16+
17+
WORKDIR /app
18+
19+
# Download dependencies first (better caching)
20+
COPY go.mod go.sum ./
21+
RUN go mod download
22+
23+
# Copy source code
24+
COPY . .
25+
26+
# Build the binary
27+
# - CGO_ENABLED=0: Static binary, no C dependencies
28+
# - -ldflags="-s -w": Strip debug info for smaller binary
29+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
30+
-ldflags="-s -w" \
31+
-o /gitvigil \
32+
./cmd/main.go
33+
34+
# -----------------------------------------------------------------------------
35+
# Runtime Stage
36+
# -----------------------------------------------------------------------------
37+
FROM alpine:3.19
38+
39+
# Install runtime dependencies
40+
RUN apk --no-cache add ca-certificates tzdata
41+
42+
# Import user from builder
43+
COPY --from=builder /etc/passwd /etc/passwd
44+
COPY --from=builder /etc/group /etc/group
45+
46+
WORKDIR /app
47+
48+
# Copy binary from builder
49+
COPY --from=builder /gitvigil .
50+
51+
# Copy migrations (embedded in binary, but keep for reference)
52+
COPY --from=builder /app/internal/database/migrations ./internal/database/migrations
53+
54+
# Use non-root user
55+
USER appuser
56+
57+
# Expose default port
58+
EXPOSE 8080
59+
60+
# Health check
61+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
62+
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
63+
64+
# Run the application
65+
ENTRYPOINT ["/app/gitvigil"]

Makefile

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# =============================================================================
2+
# GitVigil Makefile
3+
# =============================================================================
4+
5+
.PHONY: all build run test fmt vet clean dev \
6+
docker-build docker-up docker-down docker-logs docker-clean \
7+
help
8+
9+
# Go parameters
10+
BINARY_NAME := gitvigil
11+
MAIN_PATH := ./cmd/main.go
12+
GO := go
13+
14+
# Docker parameters
15+
DOCKER_IMAGE := gitvigil
16+
DOCKER_TAG := latest
17+
18+
# =============================================================================
19+
# Development
20+
# =============================================================================
21+
22+
## build: Build the binary
23+
build:
24+
@echo "Building $(BINARY_NAME)..."
25+
@$(GO) build -o $(BINARY_NAME) $(MAIN_PATH)
26+
@echo "Done!"
27+
28+
## run: Run the application locally
29+
run:
30+
@$(GO) run $(MAIN_PATH)
31+
32+
## test: Run all tests
33+
test:
34+
@echo "Running tests..."
35+
@$(GO) test -v ./...
36+
37+
## test-coverage: Run tests with coverage
38+
test-coverage:
39+
@echo "Running tests with coverage..."
40+
@$(GO) test -coverprofile=coverage.out ./...
41+
@$(GO) tool cover -html=coverage.out -o coverage.html
42+
@echo "Coverage report: coverage.html"
43+
44+
## fmt: Format code
45+
fmt:
46+
@echo "Formatting code..."
47+
@$(GO) fmt ./...
48+
49+
## vet: Run go vet
50+
vet:
51+
@echo "Running go vet..."
52+
@$(GO) vet ./...
53+
54+
## lint: Run linter (requires golangci-lint)
55+
lint:
56+
@echo "Running linter..."
57+
@golangci-lint run ./...
58+
59+
## clean: Clean build artifacts
60+
clean:
61+
@echo "Cleaning..."
62+
@rm -f $(BINARY_NAME)
63+
@rm -f coverage.out coverage.html
64+
@$(GO) clean
65+
@echo "Done!"
66+
67+
## dev: Format, vet, and build
68+
dev: fmt vet build
69+
70+
## tidy: Tidy go modules
71+
tidy:
72+
@$(GO) mod tidy
73+
74+
# =============================================================================
75+
# Docker
76+
# =============================================================================
77+
78+
## docker-build: Build Docker image
79+
docker-build:
80+
@echo "Building Docker image..."
81+
@docker build -t $(DOCKER_IMAGE):$(DOCKER_TAG) .
82+
@echo "Done!"
83+
84+
## docker-up: Start services with Docker Compose
85+
docker-up:
86+
@echo "Starting services..."
87+
@docker compose up -d
88+
@echo "Services started. Access at http://localhost:8080"
89+
90+
## docker-down: Stop Docker Compose services
91+
docker-down:
92+
@echo "Stopping services..."
93+
@docker compose down
94+
95+
## docker-logs: View application logs
96+
docker-logs:
97+
@docker compose logs -f app
98+
99+
## docker-logs-db: View database logs
100+
docker-logs-db:
101+
@docker compose logs -f db
102+
103+
## docker-restart: Restart the application
104+
docker-restart:
105+
@docker compose restart app
106+
107+
## docker-clean: Stop services and remove volumes
108+
docker-clean:
109+
@echo "Stopping services and removing volumes..."
110+
@docker compose down -v
111+
@echo "Done!"
112+
113+
## docker-shell: Open shell in app container
114+
docker-shell:
115+
@docker compose exec app sh
116+
117+
## docker-db-shell: Open psql in database container
118+
docker-db-shell:
119+
@docker compose exec db psql -U gitvigil -d gitvigil
120+
121+
# =============================================================================
122+
# Database
123+
# =============================================================================
124+
125+
## db-migrate: Run database migrations (local)
126+
db-migrate:
127+
@echo "Running migrations..."
128+
@$(GO) run $(MAIN_PATH) migrate
129+
130+
# =============================================================================
131+
# Help
132+
# =============================================================================
133+
134+
## help: Show this help message
135+
help:
136+
@echo "GitVigil - Hackathon Monitoring Service"
137+
@echo ""
138+
@echo "Usage: make [target]"
139+
@echo ""
140+
@echo "Development:"
141+
@sed -n 's/^## //p' $(MAKEFILE_LIST) | grep -E '^[a-z]' | grep -v 'docker-' | column -t -s ':'
142+
@echo ""
143+
@echo "Docker:"
144+
@sed -n 's/^## //p' $(MAKEFILE_LIST) | grep -E '^docker-' | column -t -s ':'
145+
146+
# Default target
147+
all: dev

cmd/main.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"os"
6+
"os/signal"
7+
"syscall"
8+
9+
"github.com/harshpatel5940/gitvigil/internal/config"
10+
"github.com/harshpatel5940/gitvigil/internal/database"
11+
"github.com/harshpatel5940/gitvigil/internal/github"
12+
"github.com/harshpatel5940/gitvigil/internal/server"
13+
"github.com/rs/zerolog"
14+
)
15+
16+
func main() {
17+
// Setup logger
18+
logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr}).
19+
With().
20+
Timestamp().
21+
Caller().
22+
Logger()
23+
24+
// Load configuration
25+
cfg, err := config.Load()
26+
if err != nil {
27+
logger.Fatal().Err(err).Msg("failed to load configuration")
28+
}
29+
30+
logger.Info().
31+
Int64("app_id", cfg.AppID).
32+
Str("port", cfg.Port).
33+
Msg("configuration loaded")
34+
35+
// Setup context with signal handling
36+
ctx, cancel := context.WithCancel(context.Background())
37+
defer cancel()
38+
39+
sigCh := make(chan os.Signal, 1)
40+
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
41+
go func() {
42+
sig := <-sigCh
43+
logger.Info().Str("signal", sig.String()).Msg("received shutdown signal")
44+
cancel()
45+
}()
46+
47+
// Connect to database
48+
db, err := database.New(ctx, cfg.DatabaseURL)
49+
if err != nil {
50+
logger.Fatal().Err(err).Msg("failed to connect to database")
51+
}
52+
defer db.Close()
53+
logger.Info().Msg("connected to database")
54+
55+
// Run migrations
56+
if err := database.RunMigrations(cfg.DatabaseURL); err != nil {
57+
logger.Fatal().Err(err).Msg("failed to run migrations")
58+
}
59+
logger.Info().Msg("migrations completed")
60+
61+
// Create GitHub App client
62+
gh, err := github.NewAppClient(cfg.AppID, cfg.PrivateKey)
63+
if err != nil {
64+
logger.Fatal().Err(err).Msg("failed to create GitHub App client")
65+
}
66+
logger.Info().Int64("app_id", gh.AppID()).Msg("GitHub App client created")
67+
68+
// Create and start server
69+
srv := server.New(cfg, db, gh, logger)
70+
71+
if err := srv.Start(ctx); err != nil {
72+
logger.Fatal().Err(err).Msg("server error")
73+
}
74+
75+
logger.Info().Msg("server stopped gracefully")
76+
}

0 commit comments

Comments
 (0)