Skip to content

SeifMohmmed/DevHabit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

111 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

.NET PostgreSQL Docker OpenAPI OpenAPI

DevHabit API

Table of Contents

  1. Overview
  2. Technologies
  3. Features
  4. Getting Started
  5. Environment Setup
  6. Testing
  7. API Documentation

🎯 Overview

DevHabit API is a versioned RESTful web service built with .NET 9 that helps users track personal habits and routines. It provides secure JWT-based authentication, background job processing, GitHub integration, and structured observability through OpenTelemetry. The system use PostgreSQL, Docker, and best practices in validation, testing, and deployment. It supports local development, CI/CD pipelines, and containerized production environments.

This project was built using the latest ASP.NET Core features and best practices.

πŸ”§ Technologies

✨ Features

🧭 API Design

  • Filtering, sorting, pagination, and data shaping on resource collections
  • Content negotiation and HATEOAS support
  • API versioning with media type support
  • Typed HTTP clients via Refit
  • Interactive API docs with Swagger and Scalar

βš™οΈ Infrastructure & Integration

  • PostgreSQL with EF Core and naming conventions
  • Background jobs with Quartz
  • GitHub integration for external data or automation
  • File-based data import (CSV support)

πŸ” Security

  • JWT-based authentication and authorization
  • CORS policy configuration
  • Secure storage of GitHub api keys via encryption

πŸ“ˆ Observability & Resilience

  • OpenTelemetry-based distributed tracing
  • Health checks support
  • HTTP resiliency patterns via Polly (.NET Resilience)
  • Azure Monitor (optional integration)
  • Logging with .Net Aspire or Seq

πŸ§ͺ Testing Stack

  • Unit testing with xUnit and NSubstitute
  • Integration testing with Testcontainers and PostgreSQL
  • HTTP mocking via WireMock.Net
  • Code coverage with Coverlet

πŸ“¦ Deployment & DevOps

  • Local development support with Docker Compose
  • Centralized package versioning with MSBuild
  • Dockerized production image support

πŸš€ Getting Started

πŸ“‹ Prerequisites

Make sure you have .NET CLI installed on your system. You can check if it's available by running:

dotnet --version

This should print the installed version of the .NET CLI. If it's not installed, download it from the official .NET site.

To verify which SDK versions are installed:

dotnet --list-sdks

Important

The minimum .NET SDK version required is 9.0.0

Additionally, the project uses Docker for running supporting services (e.g., PostgreSQL, pgAdmin, Seq). You’ll need:

  • Docker: Recommended to install Docker Desktop.
  • Docker Compose: Typically included with Docker Desktop.

To check that Docker is installed and running:

docker --version
docker compose version

If these commands fail or return errors, refer to the Docker installation guide.


πŸ“₯ Installation

To get started, clone the repository and set up the environment configuration:

  1. Clone the repository:
git clone https://github.com/jaimejaramilloperez/dev-habit.git
  1. Navigate to the project directory:
cd dev-habit
  1. Generate and trust the HTTPS development certificate:
dotnet dev-certs https -ep ./src/DevHabit.Api/aspnetapp.pfx -p Test1234!
dotnet dev-certs https --trust
  1. Copy the environment template and configure it:
cp .env.template .env
# Edit the .env file as needed

After installation, you're ready to run the app either locally or using Docker. See the Local Development or Docker sections for details.

πŸ’» Environment SetUp

Set up your environment to run the DevHabit API either locally or with Docker, depending on your workflow.

Note

The configuration values shown (e.g., passwords, ports, keys, connection strings) are provided for demonstration purposes only. You are free to modify them as needed β€” especially for production environments.

Observability Notice:

This project supports distributed tracing and telemetry via either .NET Aspire Dashboard or Seq.

Depending on which one you choose, you must configure the following environment variables:

  • OTEL_EXPORTER_OTLP_ENDPOINT
  • OTEL_EXPORTER_OTLP_PROTOCOL

For .NET Aspire:

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:18889
OTEL_EXPORTER_OTLP_PROTOCOL=grpc

For Seq:

OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5341/ingest/otlp
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

Tip

If the API runs inside a Docker container, localhost refers to the container itself. In that case, replace localhost with the service name defined in your Docker network (e.g., devhabit.seq or devhabit.aspire-dashboard).

You can switch between them by updating your .env or Docker environment files.


πŸ§‘β€πŸ’» Local Development

You can run the API locally using the .NET CLI and supporting services (PostgreSQL, pgAdmin, Seq) via Docker Compose.

  1. Configure user secrets:

Sensitive values should be stored securely using user secrets:

{
  "ConnectionStrings:Database": "Server=localhost;Port=5432;Database=devhabit;Username=devhabit;Password=123456;",
  "Jwt:Key": "HTycXOjdDRfrtNYzQQbkx2L7ncCEe2989cWH6yrTFdSPRmFFe4K9qmbnjHJBRGHfaeRKvDEWzaS",
  "Encryption:Key": "Ubf/RatKuzJ4p8Fc9nr9LKZFV5L8CjIZZCqcFlYZeEo="
}
  1. Update appsettings.Development.json
{
  "ConnectionStrings": {
    "Database": "your-database-connection-string-here"
  },
  "Jwt": {
    "Key": "your-secret-key-here-that-should-also-be-fairly-long",
    "Issuer": "dev-habit.api",
    "Audience": "dev-habit.app",
    "ExpirationInMinutes": 30,
    "RefreshTokenExpirationInDays": 7
  },
  "Encryption": {
    "Key": "your-secret-key-here-that-should-also-be-exactly-32-bytes-or-44-characters-in-base64-long"
  },
  "Cors": {
    "AllowedOrigins": [
      "http://localhost:3000"
    ]
  },
  "Jobs": {
    "ScanIntervalInMinutes": 50
  },
  "GitHub": {
    "BaseUrl": "https://api.github.com"
  },
  "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:18889",
  "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Information"
    }
  }
}
  1. Configure environment variables (.env file):
# postgresql
POSTGRES_PORT="5432"
POSTGRES_DB="devhabit"
POSTGRES_USER="spartan"
POSTGRES_PASSWORD="123456"

# pgadmin
PGADMIN_EMAIL="user@mail.com"
PGADMIN_PASSWORD="123456"

# seq
SEQ_PASSWORD="12345678"
  1. Start docker services:
docker compose up -d
  1. Run the API:
dotnet run --project src/DevHabit.Api
# or with HTTPS
dotnet run --launch-profile https --project src/DevHabit.Api

🐳 Docker for Development

This mode runs both the application and services in Docker containers using a development image.

  1. Create or adjust .env.docker-debug:
# docker
DOCKER_REGISTRY=""
DOCKER_IMAGE_TAG="dev"
DOCKER_BUILD_TARGET="dev"
DOCKER_ASPNETCORE_BUILD_CONFIGURATION="Debug"

# app
ENVIRONMENT="Development"
HTTP_PORT="5000"
HTTPS_PORT="5001"
CERTIFICATE_PATH="/https/aspnetapp.pfx"
CERTIFICATE_PASSWORD="Test1234!"
ENCRYPTION_KEY="Ubf/RatKuzJ4p8Fc9nr9LKZFV5L8CjIZZCqcFlYZeEo="
OTEL_EXPORTER_OTLP_ENDPOINT="http://devhabit.aspire-dashboard:18889"
OTEL_EXPORTER_OTLP_PROTOCOL="grpc"

# postgresql
POSTGRES_SERVER="devhabit.postgres"
POSTGRES_PORT="5432"
POSTGRES_DB="devhabit"
POSTGRES_USER="devhabit"
POSTGRES_PASSWORD="123456"

# pgadmin
PGADMIN_EMAIL="user@mail.com"
PGADMIN_PASSWORD="123456"

# seq
SEQ_PASSWORD="12345678"
  1. Start the containers:
docker compose -f ./docker-compose.debug.yml --env-file .env.docker-debug up -d

🐞 Debugging in container

Important

Debugging inside containers requires the vsdbg debugger. If it’s not already installed, refer to the official setup guide for instructions on how to install it manually.

If you're using Visual Studio Code, you can debug the application running inside a container in two ways:

  1. Containers: .NET Launch

This option builds and runs the container in debug mode and launches the debugger automatically.

Make sure you have a .env.docker-debug-image file with the following configuration:

ASPNETCORE_HTTP_PORTS=5000
ASPNETCORE_HTTPS_PORTS=5001
ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
ASPNETCORE_Kestrel__Certificates__Default__Password=Test1234!
ConnectionStrings__Database=Server=devhabit.postgres;Port=5432;Database=devhabit;Username=devhabit;Password=123456;
OTEL_EXPORTER_OTLP_ENDPOINT=http://devhabit.aspire-dashboard:18889
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
  1. Containers .NET Attach (Preview)

This simpler option attaches the debugger to a running container β€” no extra configuration required beyond starting the containers as shown above in the step 2 of docker for development.

Warning

This feature is still in preview and may exhibit overall slower performance.


πŸ“¦ Docker for Production

To build and run the API in production mode using a minimal Docker image:

  1. Create or adjust .env.docker-prod:
DOTNET_USE_POLLING_FILE_WATCHER="1"
ASPNETCORE_ENVIRONMENT="Production"
ASPNETCORE_HTTP_PORTS=5000

ConnectionStrings__Database=Server=devhabit.postgres;Port=5432;Database=devhabit;Username=devhabit;Password=123456;

Jwt__Key="your-secret-key-here-that-should-also-be-fairly-long"
Jwt__Issuer="dev-habit.api"
Jwt__Audience="dev-habit.app"
Jwt__ExpirationInMinutes=30
Jwt__RefreshTokenExpirationInDays=7

Encryption__Key="Ubf/RatKuzJ4p8Fc9nr9LKZFV5L8CjIZZCqcFlYZeEo="
Cors__AllowedOrigins__0=""
Jobs__ScanIntervalInMinutes=50
GitHub__BaseUrl="https://api.github.com"

# Required
APPLICATIONINSIGHTS_CONNECTION_STRING=<your-azure-application-insights-connection-string>
  1. Build the image:
docker buildx build \
  --platform linux/amd64 \
  -f src/DevHabit.Api/Dockerfile \
  --target prod \
  -t devhabit.api:latest .
  1. Start the containers:
docker compose up -d
  1. Run the container:
docker container run \
  -d \
  -p 5000:5000 \
  --env-file .env.docker-prod \
  --network dev-habit_default \
  --name devhabit.api \
  devhabit.api:latest

πŸ§ͺ Testing

This project includes unit, integration and functional testing.

Note

Tests are located in the test/ directory.

Testing Technologies:

  • xUnit: Test framework.
  • NSubstitute: Mocking.
  • Testcontainers: Integration testing with ephemeral PostgreSQL instances.
  • WireMock.Net: Mock external APIs.
  • coverlet: Code coverage.
  • Microsoft.AspNetCore.Mvc.Testing: End-to-end and functional tests.

Running all tests

dotnet test

Code coverage

To generate a code coverage report with HTML output, you’ll need the dotnet reportgenerator tool. You can install it globally using:

dotnet tool install -g dotnet-reportgenerator-globaltool

A helper script is available at ./scripts/coverage.sh to automate the process.

Before running the script, make sure it has execution permissions:

chmod +x ./scripts/coverage.sh

Then run it with optional arguments:

./scripts/coverage.sh [output_dir] [verbosity]
  • output_dir: Directory where the report will be saved (default: coverage)
  • verbosity: Verbosity level for ReportGenerator (default: Error)

Once executed, the HTML report will be available at:

<output_dir>/index.html

Tip

If you're on Windows, you can use the PowerShell version of the script: .\scripts\coverage.ps1

πŸ“˜ Api Documentation

DevHabit API provides interactive documentation via Swagger and Scalar, with support for versioned endpoints and JWT authentication.

Once the API is running:

  • OpenAPI spec (JSON): https://localhost:5001/swagger/1.0/swagger.json
  • Swagger UI: https://localhost:5001/swagger
  • Scalar UI: https://localhost:5001/scalar

Note

Replace 5001 with your actual HTTPS port if different.

About

Production-style RESTful API built with ASP.NET Core 9, PostgreSQL, JWT authentication, Docker, background jobs, integration testing (Testcontainers), and OpenTelemetry-based observability.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors