feat: Add project foundation, documentation, and Docker setup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
228
README.md
Normal file
228
README.md
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
# Training Tracker
|
||||||
|
|
||||||
|
A mobile-friendly web application for tracking training activities with a Go backend and PostgreSQL database.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
training-tracker/
|
||||||
|
├── backend/
|
||||||
|
│ ├── cmd/server/ # Application entry point
|
||||||
|
│ ├── internal/
|
||||||
|
│ │ ├── api/ # HTTP handlers
|
||||||
|
│ │ ├── models/ # Data structures
|
||||||
|
│ │ └── storage/ # Database layer
|
||||||
|
│ ├── Dockerfile.dev # Development container
|
||||||
|
│ ├── Dockerfile.prod # Production container
|
||||||
|
│ ├── go.mod
|
||||||
|
│ └── go.sum
|
||||||
|
├── frontend/
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── css/styles.css
|
||||||
|
│ └── js/
|
||||||
|
│ ├── api.js # API client
|
||||||
|
│ └── app.js # Application logic
|
||||||
|
├── .gitea/workflows/ # CI/CD pipelines
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker and Docker Compose
|
||||||
|
- Go 1.25.6+ (for local development without Docker)
|
||||||
|
- A web server or `python3 -m http.server` (for frontend)
|
||||||
|
|
||||||
|
## Running with Docker Compose (Recommended)
|
||||||
|
|
||||||
|
Start PostgreSQL and the backend:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
This starts:
|
||||||
|
- PostgreSQL on port 5432
|
||||||
|
- Backend API on port 8080
|
||||||
|
|
||||||
|
To view logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose logs -f backend
|
||||||
|
```
|
||||||
|
|
||||||
|
To stop:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Manually
|
||||||
|
|
||||||
|
### 1. Start PostgreSQL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose up -d postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use an existing PostgreSQL instance and set environment variables.
|
||||||
|
|
||||||
|
### 2. Run the Backend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
export DB_HOST=localhost
|
||||||
|
export DB_PORT=5432
|
||||||
|
export DB_USER=postgres
|
||||||
|
export DB_PASSWORD=postgres
|
||||||
|
export DB_NAME=training_tracker
|
||||||
|
go run ./cmd/server
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Serve the Frontend
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
python3 -m http.server 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
Open http://localhost:3000 in your browser.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
The backend includes comprehensive unit and integration tests.
|
||||||
|
|
||||||
|
### Run Unit Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
go test ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Tests with Coverage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
go test -cover ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Integration Tests
|
||||||
|
|
||||||
|
Integration tests use testcontainers to spin up a PostgreSQL instance. Docker must be running.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
go test -v -tags=integration ./internal/storage/...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run All Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
go test ./... && go test -tags=integration ./internal/storage/...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `DB_HOST` | localhost | PostgreSQL host |
|
||||||
|
| `DB_PORT` | 5432 | PostgreSQL port |
|
||||||
|
| `DB_USER` | postgres | Database user |
|
||||||
|
| `DB_PASSWORD` | postgres | Database password |
|
||||||
|
| `DB_NAME` | training_tracker | Database name |
|
||||||
|
| `PORT` | 8080 | Backend server port |
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
### Exercises
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/exercises` | List all exercises |
|
||||||
|
| POST | `/api/exercises` | Create exercise |
|
||||||
|
| GET | `/api/exercises/:id` | Get exercise by ID |
|
||||||
|
| PUT | `/api/exercises/:id` | Update exercise |
|
||||||
|
| DELETE | `/api/exercises/:id` | Delete exercise |
|
||||||
|
|
||||||
|
### Training Plans
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/plans` | List all plans |
|
||||||
|
| POST | `/api/plans` | Create plan |
|
||||||
|
| GET | `/api/plans/:id` | Get plan with exercises |
|
||||||
|
| PUT | `/api/plans/:id` | Update plan |
|
||||||
|
| DELETE | `/api/plans/:id` | Delete plan |
|
||||||
|
|
||||||
|
### Sessions
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/sessions` | List all sessions |
|
||||||
|
| POST | `/api/sessions` | Create session |
|
||||||
|
| GET | `/api/sessions/:id` | Get session with entries |
|
||||||
|
| PUT | `/api/sessions/:id` | Update session |
|
||||||
|
| DELETE | `/api/sessions/:id` | Delete session |
|
||||||
|
| POST | `/api/sessions/:id/entries` | Add exercise entry |
|
||||||
|
|
||||||
|
### Health Check
|
||||||
|
|
||||||
|
| Method | Endpoint | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| GET | `/api/health` | Returns `{"status": "ok"}` |
|
||||||
|
|
||||||
|
## API Examples
|
||||||
|
|
||||||
|
### Create an Exercise
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/api/exercises \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"name": "Bench Press", "type": "strength", "muscle_group": "Chest"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create a Session
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/api/sessions \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"date": "2026-01-19T10:00:00Z", "notes": "Morning workout"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add Entry to Session
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/api/sessions/1/entries \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"exercise_id": 1, "weight": 80, "sets_completed": 3, "reps": 10}'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Mobile-first responsive design
|
||||||
|
- Exercise library (strength and cardio types)
|
||||||
|
- Training plan templates
|
||||||
|
- Session logging with:
|
||||||
|
- Strength: weight, sets, reps
|
||||||
|
- Cardio: duration, distance, heart rate
|
||||||
|
- Session history and dashboard
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
Build the production image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -f backend/Dockerfile.prod -t training-tracker-backend ./backend
|
||||||
|
```
|
||||||
|
|
||||||
|
The production image uses:
|
||||||
|
- Distroless base image
|
||||||
|
- Non-root user
|
||||||
|
- Pinned image digests for reproducibility
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
|
The project includes a Gitea Actions workflow (`.gitea/workflows/ci.yaml`) that:
|
||||||
|
1. Runs tests on pull requests
|
||||||
|
2. Builds and pushes Docker images on merge to main
|
||||||
18
backend/Dockerfile.dev
Normal file
18
backend/Dockerfile.dev
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
FROM golang:1.25.6-bookworm
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
git \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN go build -o server ./cmd/server
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
CMD ["./server"]
|
||||||
22
backend/Dockerfile.prod
Normal file
22
backend/Dockerfile.prod
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Production Dockerfile with pinned image digests
|
||||||
|
# golang:1.25.6-alpine
|
||||||
|
FROM golang@sha256:d9b2e14101f27ec8d09674cd01186798d227bb0daec90e032aeb1cd22ac0f029 AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server ./cmd/server
|
||||||
|
|
||||||
|
# gcr.io/distroless/static-debian12:nonroot
|
||||||
|
FROM gcr.io/distroless/static-debian12@sha256:6dcc833df2a475be1a3d7fc951de90ac91a2cb0be237c7578b88722571f77571
|
||||||
|
|
||||||
|
COPY --from=builder /app/server /server
|
||||||
|
|
||||||
|
USER nonroot:nonroot
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENTRYPOINT ["/server"]
|
||||||
116
backend/claude.md
Normal file
116
backend/claude.md
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
## General
|
||||||
|
- Before scaffolding any service, verify current stable versions from official sources (go.dev, rust-lang.org, nodejs.org, etc.)
|
||||||
|
- Prefer stdlib over dependencies where reasonable
|
||||||
|
- No vendoring unless explicitly requested
|
||||||
|
|
||||||
|
## Go
|
||||||
|
- Use latest stable Go version (check https://go.dev/dl/ before starting)
|
||||||
|
- Use `slog` for structured logging
|
||||||
|
- `context.Context` first param, always
|
||||||
|
- No `init()` unless unavoidable
|
||||||
|
- Errors: prefer `errors.Join` for multiple errors, `fmt.Errorf` with `%w` for wrapping
|
||||||
|
|
||||||
|
## Containers
|
||||||
|
- Multi-stage builds, distroless/scratch final images
|
||||||
|
- ubuntu based images for the development builds
|
||||||
|
- Non-root user, read-only rootfs for production builds
|
||||||
|
- prepare dockerfiles for both development and production
|
||||||
|
- Pin base image digests in prod Dockerfiles
|
||||||
|
|
||||||
|
## K8s Manifests
|
||||||
|
- Always include resource requests/limits
|
||||||
|
- Liveness/readiness probes with sane defaults
|
||||||
|
- PodDisruptionBudgets for replicated workloads
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
- Fail fast, return early
|
||||||
|
- Table-driven tests
|
||||||
|
- No obvious comments
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
- Git remote: Gitea at https://[gitea.yourdomain.com](https://gitea.home.hrajfrisbee.cz/)
|
||||||
|
- CI: Gitea Actions (workflow syntax is GitHub Actions compatible)
|
||||||
|
- Workflows go in `.gitea/workflows/`
|
||||||
|
- Use `runs-on: linux-amd64` (or whatever labels your runners have)
|
||||||
|
- Registry: gitea.home.hrajfrisbee.cz (use `${{ secrets.REGISTRY_TOKEN }}` for auth)
|
||||||
|
|
||||||
|
## Testing (Go)
|
||||||
|
|
||||||
|
### Go Test Requirements
|
||||||
|
- **MANDATORY: All new Go code must have corresponding tests**
|
||||||
|
- Use stdlib `testing` package, no testify unless already in project
|
||||||
|
- Table-driven tests as default pattern
|
||||||
|
- Test file next to source: `foo.go` → `foo_test.go`
|
||||||
|
- Name tests `Test<Function>_<scenario>` (e.g., `TestCreateUser_duplicateEmail`)
|
||||||
|
- Use `t.Parallel()` where safe
|
||||||
|
- Subtests for table entries: `t.Run(tc.name, func(t *testing.T) { ... })`
|
||||||
|
- Test behavior, not implementation
|
||||||
|
- Use `testing.Short()` to skip slow integration tests: `if testing.Short() { t.Skip() }`
|
||||||
|
|
||||||
|
### Test Structure
|
||||||
|
- Each test function should test ONE behavior
|
||||||
|
- Use descriptive test names: `TestExerciseHandler_Create_ValidInput`
|
||||||
|
- Table-driven test format:
|
||||||
|
```go
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input InputType
|
||||||
|
want ExpectedType
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{"valid input", validInput, expectedOutput, false},
|
||||||
|
{"empty name", emptyName, nil, true},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// test logic
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handler Tests (Unit)
|
||||||
|
- Mock external dependencies (repositories, services)
|
||||||
|
- Use `httptest.NewRecorder()` and `httptest.NewRequest()`
|
||||||
|
- Test: success path, validation errors, not found, internal errors
|
||||||
|
- Mock interfaces defined in `internal/api/interfaces.go`
|
||||||
|
- Mock implementations in `internal/api/mocks_test.go`
|
||||||
|
|
||||||
|
### Repository Tests (Integration)
|
||||||
|
- Use testcontainers-go for database tests
|
||||||
|
- Integration tests in `_test.go` with build tag `//go:build integration`
|
||||||
|
- Clean database state between tests using `truncateTables()`
|
||||||
|
- Test: CRUD operations, edge cases, transactions, cascades
|
||||||
|
- Test helpers in `internal/storage/testhelpers_test.go`
|
||||||
|
|
||||||
|
### What to Test
|
||||||
|
- All public functions/methods
|
||||||
|
- Happy path AND error paths
|
||||||
|
- Edge cases: empty inputs, nil values, not found
|
||||||
|
- Validation logic
|
||||||
|
- Transaction rollback scenarios
|
||||||
|
|
||||||
|
### What NOT to Test
|
||||||
|
- Simple getters/setters
|
||||||
|
- Third-party library code
|
||||||
|
- Private helper functions (test through public API)
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
```bash
|
||||||
|
# Run all unit tests (fast)
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
# Run with verbose output
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
go test -cover ./...
|
||||||
|
|
||||||
|
# Run only unit tests, skip integration
|
||||||
|
go test -short ./...
|
||||||
|
|
||||||
|
# Run integration tests (requires Docker)
|
||||||
|
go test -v -tags=integration ./internal/storage/...
|
||||||
|
|
||||||
|
# Run specific package
|
||||||
|
go test -v ./internal/api/...
|
||||||
|
```
|
||||||
67
backend/go.mod
Normal file
67
backend/go.mod
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
module training-tracker
|
||||||
|
|
||||||
|
go 1.25.6
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/lib/pq v1.10.9
|
||||||
|
github.com/testcontainers/testcontainers-go v0.40.0
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
dario.cat/mergo v1.0.2 // indirect
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
|
github.com/containerd/platforms v0.2.1 // indirect
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.2 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/distribution/reference v0.6.0 // indirect
|
||||||
|
github.com/docker/docker v28.5.1+incompatible // indirect
|
||||||
|
github.com/docker/go-connections v0.6.0 // indirect
|
||||||
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
|
github.com/ebitengine/purego v0.8.4 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect
|
||||||
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.10 // indirect
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||||
|
github.com/moby/go-archive v0.1.0 // indirect
|
||||||
|
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||||
|
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||||
|
github.com/moby/sys/user v0.4.0 // indirect
|
||||||
|
github.com/moby/sys/userns v0.1.0 // indirect
|
||||||
|
github.com/moby/term v0.5.0 // indirect
|
||||||
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
|
github.com/stretchr/testify v1.11.1 // indirect
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||||
|
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||||
|
golang.org/x/crypto v0.43.0 // indirect
|
||||||
|
golang.org/x/sys v0.38.0 // indirect
|
||||||
|
golang.org/x/text v0.32.0 // indirect
|
||||||
|
google.golang.org/grpc v1.78.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
178
backend/go.sum
Normal file
178
backend/go.sum
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||||
|
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||||
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
|
||||||
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
|
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
|
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||||
|
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||||
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
|
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
|
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
|
||||||
|
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||||
|
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||||
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||||
|
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4/go.mod h1:6Nz966r3vQYCqIzWsuEl9d7cf7mRhtDmm++sOxlnfxI=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
|
||||||
|
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||||
|
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
|
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||||
|
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
|
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
|
||||||
|
github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
|
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||||
|
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
||||||
|
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||||
|
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
|
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||||
|
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||||
|
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||||
|
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||||
|
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
||||||
|
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||||
|
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||||
|
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||||
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0 h1:s2bIayFXlbDFexo96y+htn7FzuhpXLYJNnIuglNKqOk=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.40.0/go.mod h1:h+u/2KoREGTnTl9UwrQ/g+XhasAT8E6dClclAADeXoQ=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||||
|
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||||
|
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||||
|
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||||
|
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||||
|
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||||
|
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||||
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
|
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||||
|
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||||
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
|
||||||
|
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
|
||||||
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
|
||||||
|
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=
|
||||||
|
google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||||
|
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||||
40
docker-compose.yml
Normal file
40
docker-compose.yml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
container_name: training-tracker-db
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: training_tracker
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build:
|
||||||
|
context: ./backend
|
||||||
|
dockerfile: Dockerfile.dev
|
||||||
|
container_name: training-tracker-backend
|
||||||
|
environment:
|
||||||
|
DB_HOST: postgres
|
||||||
|
DB_PORT: 5432
|
||||||
|
DB_USER: postgres
|
||||||
|
DB_PASSWORD: postgres
|
||||||
|
DB_NAME: training_tracker
|
||||||
|
PORT: 8080
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
186
plans/001-initial-implementation-plan.md
Normal file
186
plans/001-initial-implementation-plan.md
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# Training Tracker - Implementation Plan
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
A mobile-friendly web application for tracking training activities with a Golang backend and SQL/NoSQL database.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Project Foundation
|
||||||
|
|
||||||
|
### 1.1 Project Structure
|
||||||
|
```
|
||||||
|
training-tracker/
|
||||||
|
├── backend/
|
||||||
|
│ ├── cmd/
|
||||||
|
│ │ └── server/
|
||||||
|
│ │ └── main.go
|
||||||
|
│ ├── internal/
|
||||||
|
│ │ ├── api/ # HTTP handlers
|
||||||
|
│ │ ├── models/ # Data structures
|
||||||
|
│ │ ├── storage/ # Database layer
|
||||||
|
│ │ └── service/ # Business logic
|
||||||
|
│ ├── go.mod
|
||||||
|
│ └── go.sum
|
||||||
|
├── frontend/
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── css/
|
||||||
|
│ │ └── styles.css
|
||||||
|
│ ├── js/
|
||||||
|
│ │ ├── app.js
|
||||||
|
│ │ ├── api.js
|
||||||
|
│ │ └── components/
|
||||||
|
│ └── assets/
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── readme.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Database Schema Design
|
||||||
|
**Core entities:**
|
||||||
|
- **users** - User accounts (id, username, email, password_hash, created_at)
|
||||||
|
- **exercises** - Exercise definitions (id, name, type, muscle_group, description)
|
||||||
|
- **training_plans** - Training plan templates (id, user_id, name, description)
|
||||||
|
- **plan_exercises** - Exercises in a plan (id, plan_id, exercise_id, sets, reps, duration, order)
|
||||||
|
- **sessions** - Completed training sessions (id, user_id, plan_id, date, notes)
|
||||||
|
- **session_entries** - Individual exercise entries (id, session_id, exercise_id, weight, reps, duration, sets_completed)
|
||||||
|
|
||||||
|
**Choice:** PostgreSQL (can use Docker for local development)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Backend Development (Golang)
|
||||||
|
|
||||||
|
### 2.1 Initial Setup
|
||||||
|
- Initialize Go module
|
||||||
|
- Set up HTTP router (standard library `net/http` or `chi`/`gorilla/mux`)
|
||||||
|
- Configure environment variables
|
||||||
|
- Set up database connection
|
||||||
|
|
||||||
|
### 2.2 API Endpoints
|
||||||
|
```
|
||||||
|
# Auth endpoints (deferred to v2)
|
||||||
|
# POST /api/auth/register
|
||||||
|
# POST /api/auth/login
|
||||||
|
|
||||||
|
Exercises:
|
||||||
|
GET /api/exercises # List all exercises
|
||||||
|
POST /api/exercises # Create exercise
|
||||||
|
GET /api/exercises/:id # Get exercise
|
||||||
|
PUT /api/exercises/:id # Update exercise
|
||||||
|
DELETE /api/exercises/:id # Delete exercise
|
||||||
|
|
||||||
|
Training Plans:
|
||||||
|
GET /api/plans # List user's plans
|
||||||
|
POST /api/plans # Create plan
|
||||||
|
GET /api/plans/:id # Get plan with exercises
|
||||||
|
PUT /api/plans/:id # Update plan
|
||||||
|
DELETE /api/plans/:id # Delete plan
|
||||||
|
|
||||||
|
Sessions:
|
||||||
|
GET /api/sessions # List sessions (with filters)
|
||||||
|
POST /api/sessions # Create/start session
|
||||||
|
GET /api/sessions/:id # Get session details
|
||||||
|
PUT /api/sessions/:id # Update session
|
||||||
|
DELETE /api/sessions/:id # Delete session
|
||||||
|
POST /api/sessions/:id/entries # Add entry to session
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 Core Backend Tasks
|
||||||
|
1. Set up Go project structure and dependencies
|
||||||
|
2. Set up PostgreSQL via Docker
|
||||||
|
3. Implement database migrations
|
||||||
|
4. Create data models and repository layer
|
||||||
|
5. Implement REST API handlers
|
||||||
|
6. Add input validation and error handling
|
||||||
|
7. Implement CORS for frontend communication
|
||||||
|
8. (v2) Add authentication
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Frontend Development (HTML/CSS/JS)
|
||||||
|
|
||||||
|
### 3.1 Mobile-First Design
|
||||||
|
- Responsive CSS with mobile breakpoints
|
||||||
|
- Touch-friendly UI elements
|
||||||
|
- Offline-capable design (future PWA)
|
||||||
|
|
||||||
|
### 3.2 Core Views/Pages
|
||||||
|
1. **Dashboard** - Overview of recent sessions, quick actions
|
||||||
|
2. **Training Plan View** - Display exercises for current session
|
||||||
|
3. **Session Logger** - Form to enter weights/reps/duration during workout
|
||||||
|
- Strength: weight, sets, reps
|
||||||
|
- Cardio: duration, distance, heart rate (optional)
|
||||||
|
4. **History** - View past sessions and progress
|
||||||
|
5. **Exercise Library** - Browse and manage exercises
|
||||||
|
6. (v2) **Login/Register** - Authentication screens
|
||||||
|
|
||||||
|
### 3.3 Frontend Tasks
|
||||||
|
1. Create base HTML structure and navigation
|
||||||
|
2. Implement responsive CSS (flexbox/grid)
|
||||||
|
3. Build API client module (fetch wrapper)
|
||||||
|
4. Create reusable UI components
|
||||||
|
5. Implement session logging interface
|
||||||
|
6. Add form validation
|
||||||
|
7. Implement local storage for offline data entry
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Integration & Testing
|
||||||
|
|
||||||
|
### 4.1 Integration
|
||||||
|
- Connect frontend to backend API
|
||||||
|
- Test all CRUD operations
|
||||||
|
- Handle loading states and errors
|
||||||
|
- Implement authentication flow
|
||||||
|
|
||||||
|
### 4.2 Testing
|
||||||
|
- Backend: Unit tests for handlers and services
|
||||||
|
- Frontend: Manual testing on mobile devices
|
||||||
|
- API: Integration tests
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Deployment (Optional for v1)
|
||||||
|
|
||||||
|
- Docker containerization
|
||||||
|
- Docker Compose for local development
|
||||||
|
- Basic deployment documentation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Enhancements (v2+)
|
||||||
|
- Strava integration
|
||||||
|
- Whoop integration
|
||||||
|
- Progress charts and analytics
|
||||||
|
- Workout timer
|
||||||
|
- PWA with offline support
|
||||||
|
- Export data (CSV/PDF)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommended Implementation Order
|
||||||
|
|
||||||
|
1. **Backend foundation** - Go project setup, PostgreSQL via Docker, basic models
|
||||||
|
2. **Core API** - Exercises and sessions endpoints (strength + cardio support)
|
||||||
|
3. **Frontend skeleton** - HTML structure, CSS, navigation
|
||||||
|
4. **Session logging** - The core feature (enter workout data)
|
||||||
|
5. **Training plans** - Plan viewing and management
|
||||||
|
6. **Polish** - Error handling, validation, UX improvements
|
||||||
|
7. (v2) **Authentication** - User accounts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- **Database**: PostgreSQL (via Docker for local dev)
|
||||||
|
- **Authentication**: None initially (single-user mode), add in v2
|
||||||
|
- **Exercise types**: Both strength (weight/sets/reps) and cardio (duration/distance/HR)
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
After implementation, verify by:
|
||||||
|
1. Start PostgreSQL container and backend server
|
||||||
|
2. Open frontend in browser (mobile viewport)
|
||||||
|
3. Create a test exercise (e.g., "Bench Press" - strength type)
|
||||||
|
4. Create a training plan with exercises
|
||||||
|
5. Log a session with actual data entry
|
||||||
|
6. View session history
|
||||||
152
plans/testing-plan.md
Normal file
152
plans/testing-plan.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Backend Testing Plan
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Add comprehensive tests for the training-tracker backend following Go best practices and the CLAUDE.md guidelines (table-driven tests).
|
||||||
|
|
||||||
|
**Scope:** Both unit tests (handlers with mocks) AND integration tests (repositories with testcontainers)
|
||||||
|
|
||||||
|
**Plan storage:** Copy this plan to `training-tracker/plans/testing-plan.md`
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
- **No existing tests** - greenfield testing
|
||||||
|
- 3 packages to test: `api`, `storage`, `models`
|
||||||
|
- Dependencies: handlers → repositories → database
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
### 1. Unit Tests for API Handlers
|
||||||
|
|
||||||
|
Test HTTP handlers with mocked repositories.
|
||||||
|
|
||||||
|
**Files to create:**
|
||||||
|
- `internal/api/exercises_test.go`
|
||||||
|
- `internal/api/plans_test.go`
|
||||||
|
- `internal/api/sessions_test.go`
|
||||||
|
|
||||||
|
**Approach:**
|
||||||
|
- Define repository interfaces
|
||||||
|
- Create mock implementations
|
||||||
|
- Use `httptest.NewRecorder()` and `httptest.NewRequest()`
|
||||||
|
- Table-driven tests for each endpoint
|
||||||
|
|
||||||
|
**Test cases per handler:**
|
||||||
|
- List: empty result, multiple results
|
||||||
|
- GetByID: found, not found
|
||||||
|
- Create: valid input, missing required fields, invalid type
|
||||||
|
- Update: found, not found, validation errors
|
||||||
|
- Delete: found, not found
|
||||||
|
|
||||||
|
### 2. Integration Tests for Storage Layer
|
||||||
|
|
||||||
|
Test repositories against real PostgreSQL using testcontainers.
|
||||||
|
|
||||||
|
**Files to create:**
|
||||||
|
- `internal/storage/exercises_test.go`
|
||||||
|
- `internal/storage/plans_test.go`
|
||||||
|
- `internal/storage/sessions_test.go`
|
||||||
|
- `internal/storage/db_test.go`
|
||||||
|
|
||||||
|
**Approach:**
|
||||||
|
- Use `testcontainers-go` to spin up PostgreSQL
|
||||||
|
- Run migrations before tests
|
||||||
|
- Test CRUD operations end-to-end
|
||||||
|
- Test transaction rollback scenarios
|
||||||
|
|
||||||
|
**Test cases:**
|
||||||
|
- CRUD operations for each entity
|
||||||
|
- Cascading deletes
|
||||||
|
- Transaction handling in plans (create/update)
|
||||||
|
- NULL field handling
|
||||||
|
- Foreign key constraints
|
||||||
|
|
||||||
|
### 3. Test File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
backend/internal/
|
||||||
|
├── api/
|
||||||
|
│ ├── exercises_test.go
|
||||||
|
│ ├── plans_test.go
|
||||||
|
│ ├── sessions_test.go
|
||||||
|
│ └── mocks_test.go # Shared mock implementations
|
||||||
|
├── storage/
|
||||||
|
│ ├── testhelpers_test.go # Shared test database setup
|
||||||
|
│ ├── exercises_test.go
|
||||||
|
│ ├── plans_test.go
|
||||||
|
│ └── sessions_test.go
|
||||||
|
└── models/
|
||||||
|
└── (no tests needed - pure data structures)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
1. **Create plans folder** and store this plan:
|
||||||
|
- Create `training-tracker/plans/`
|
||||||
|
- Copy this plan to `training-tracker/plans/testing-plan.md`
|
||||||
|
|
||||||
|
2. **Add test dependencies** to go.mod:
|
||||||
|
- `github.com/testcontainers/testcontainers-go`
|
||||||
|
- Use standard library for assertions (no testify)
|
||||||
|
|
||||||
|
3. **Create repository interfaces** in `internal/api/`:
|
||||||
|
- `ExerciseRepository` interface
|
||||||
|
- `PlanRepository` interface
|
||||||
|
- `SessionRepository` interface
|
||||||
|
|
||||||
|
4. **Create mock implementations** for unit testing handlers
|
||||||
|
|
||||||
|
5. **Create test helpers** for integration tests:
|
||||||
|
- Shared PostgreSQL container setup
|
||||||
|
- Database cleanup between tests
|
||||||
|
|
||||||
|
6. **Write handler unit tests** (table-driven):
|
||||||
|
- All CRUD operations
|
||||||
|
- Validation error paths
|
||||||
|
- Not found scenarios
|
||||||
|
|
||||||
|
7. **Write storage integration tests** (table-driven):
|
||||||
|
- All repository methods
|
||||||
|
- Edge cases and error conditions
|
||||||
|
|
||||||
|
8. **Update CLAUDE.md** with testing instructions
|
||||||
|
|
||||||
|
## Files to Modify
|
||||||
|
|
||||||
|
- `backend/go.mod` - add test dependencies
|
||||||
|
- `backend/internal/api/router.go` - extract interfaces for testability
|
||||||
|
- `backend/CLAUDE.md` - add testing instructions
|
||||||
|
|
||||||
|
## Files to Create
|
||||||
|
|
||||||
|
- `plans/testing-plan.md` - this plan document
|
||||||
|
- `backend/internal/api/interfaces.go` - repository interfaces
|
||||||
|
- `backend/internal/api/mocks_test.go` - mock implementations
|
||||||
|
- `backend/internal/api/exercises_test.go`
|
||||||
|
- `backend/internal/api/plans_test.go`
|
||||||
|
- `backend/internal/api/sessions_test.go`
|
||||||
|
- `backend/internal/storage/testhelpers_test.go`
|
||||||
|
- `backend/internal/storage/exercises_test.go`
|
||||||
|
- `backend/internal/storage/plans_test.go`
|
||||||
|
- `backend/internal/storage/sessions_test.go`
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
# Run with verbose output
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
go test -cover ./...
|
||||||
|
|
||||||
|
# Run only unit tests (fast)
|
||||||
|
go test -short ./...
|
||||||
|
|
||||||
|
# Run specific package
|
||||||
|
go test -v ./internal/api/...
|
||||||
|
```
|
||||||
13
project.md
Normal file
13
project.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Training tracker
|
||||||
|
|
||||||
|
Will be application for tracking my activities relevant to training.
|
||||||
|
It will have:
|
||||||
|
- frontend:
|
||||||
|
- mobile friendly web application which is gonna let me view training plan for the session, will allow to enter session type, weights/resistance, repetitions, duration or other relevant attributes of the session.
|
||||||
|
- technologies to be used: html, css, javascript
|
||||||
|
- backend:
|
||||||
|
- service written in golang available over http/https allowing frontend to access/persist all the necessary information
|
||||||
|
- persistent layer will ba suitable database, either sql or nosql
|
||||||
|
- auxiliary services:
|
||||||
|
- this is something extra which does not have to be part of 1st version of the app and will be able to read data from strava or whoop
|
||||||
|
|
||||||
Reference in New Issue
Block a user