diff --git a/Makefile b/Makefile index defe95e..6d8722c 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,5 @@ db: db_down: docker compose down db -apply_migrations: - @cd scripts && pwsh apply_migrations.ps1 - @cd ../ - -.PHONY: dev no-reload db db_down apply_migrations +.PHONY: dev no-reload db db_down .DEFAULT_GOAL := dev diff --git a/README.md b/README.md index 1e2cc6e..69f33e0 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,9 @@ or in bash/zsh dotnet dev-certs https -ep .aspnet/https/aspnetapp.pfx -p devcertpasswd --trust ``` -Next go to the `scripts` directory and run `apply_migrations.ps1` -Next You should go back to the main directory and run `docker compose --profile hot-reload up --build --watch` -This can be done with the following snippet. +Database migrations will be automatically applied when executing docker-compose via the `migrations` service. -```powershell -cd scripts -.\apply_migrations.ps1 -cd ..\ -docker compose --profile hot-reload up --build --watch -``` +Next You should go back to the main directory and run `docker compose --profile hot-reload up --build --watch` You can now visit the site at: @@ -51,15 +44,19 @@ Directory `scripts` contains some helpful scripts which automate some parts of w ## Development The application is started using the following command (with hot-reload feature): + ```bash make ``` + or without the hot-reload feature: + ```bash make no-reload ``` If you want to run the application manually you can use the following command: + ```bash docker compose --profile hot-reload up --build --watch ``` @@ -75,6 +72,10 @@ The `--watch` parameter starts containers with the `hot-reload` feature. This en > The `hot-reload` feature for backend applications uses `dotnet watch`, which only detects changes to existing files. It will not restart the container if new files are added (dotnet watch [issue](https://github.com/dotnet/aspnetcore/issues/8321)). ### DB Migrations + When working with migrations remember to add parameter for project and startup project. For example when generating a new migration while in backend directory: -`dotnet ef migrations add -p ./src/infrastructure -s ./src/api "Example"` + +```bash +dotnet ef migrations add -p ./src/infrastructure -s ./src/api "Example" +``` diff --git a/backend/Dockerfile b/backend/Dockerfile index efa78e6..4d31524 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,17 +1,28 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +ARG DOTNET_RUNTIME=mcr.microsoft.com/dotnet/aspnet +ARG DOTNET_SDK=mcr.microsoft.com/dotnet/sdk +ARG DOTNET_VERSION=8.0 + +FROM ${DOTNET_RUNTIME}:${DOTNET_VERSION} AS base WORKDIR /app EXPOSE 80 EXPOSE 443 -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS development +FROM ${DOTNET_SDK}:${DOTNET_VERSION} AS development COPY . /src WORKDIR /src CMD ["dotnet", "watch", "--verbose", "--non-interactive", "--no-launch-profile", "--project", "src/api/"] +FROM ${DOTNET_SDK}:${DOTNET_VERSION} AS migrations +COPY . /src +WORKDIR /src +RUN dotnet tool install --global dotnet-ef +ENV PATH="$PATH:/root/.dotnet/tools" +ENTRYPOINT [ "dotnet", "ef", "database", "update", "-p", "src/infrastructure", "-s", "src/api" ] + #Todo: clean it up for multiproject build -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +FROM ${DOTNET_SDK}:${DOTNET_VERSION} AS build WORKDIR /src COPY src/api/api.csproj src/api/ RUN dotnet restore "src/api/api.csproj" diff --git a/docker-compose.yml b/docker-compose.yml index db315d9..658eb39 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,30 @@ +# Common configuration between services +x-frontend: &frontend-base + build: + context: ./frontend + ports: + - "8888:8888" + +x-backend: &backend-base + ports: + - "5001:80" + - "5000:443" + environment: + ASPNETCORE_ENVIRONMENT: "Development" + ConnectionStrings__KSummarized: "Host=db;Database=ksummarized;Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}" + ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetapp.pfx" + ASPNETCORE_Kestrel__Certificates__Default__Password: "devcertpasswd" + ASPNETCORE_URLS: "https://+:443;http://+:80" + DOTNET_USE_POLLING_FILE_WATCHER: true # dotnet watch uses a a polling file watcher. Required for running it in docker. + volumes: + - .aspnet/https:/https/:ro # read-only on the container + services: - frontend: &frontend-base + frontend: + <<: *frontend-base container_name: ks-frontend profiles: - without-hot-reload - build: - context: ./frontend - ports: - - "8888:8888" frontend-hot-reload: <<: *frontend-base @@ -24,27 +42,19 @@ services: - action: rebuild path: package.json - backend: &backend-base + backend: + <<: *backend-base container_name: ks-backend build: context: ./backend + target: final profiles: - without-hot-reload - ports: - - "5001:80" - - "5000:443" - environment: - ASPNETCORE_ENVIRONMENT: "Development" - ConnectionStrings__KSummarized: "Host=db;Database=ksummarized;Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD}" - ASPNETCORE_Kestrel__Certificates__Default__Path: "/https/aspnetapp.pfx" - ASPNETCORE_Kestrel__Certificates__Default__Password: "devcertpasswd" - ASPNETCORE_URLS: "https://+:443;http://+:80" - DOTNET_USE_POLLING_FILE_WATCHER: true # dotnet watch uses a a polling file watcher. Required for running it in docker. - volumes: - - .aspnet/https:/https/:ro # read-only on the container depends_on: db: condition: service_healthy + migrations: + condition: service_completed_successfully backend-hot-reload: <<: *backend-base @@ -54,12 +64,28 @@ services: target: development profiles: - hot-reload + depends_on: + db: + condition: service_healthy + migrations: + condition: service_completed_successfully develop: watch: - action: sync path: ./backend target: /src + migrations: + <<: *backend-base + container_name: ks-migrations + restart: no + build: + context: ./backend + target: migrations + depends_on: + db: + condition: service_healthy + db: image: postgres:14.0-alpine container_name: ks-database @@ -71,7 +97,7 @@ services: env_file: .env healthcheck: test: ["CMD-SHELL", "sh -c 'pg_isready -U ${POSTGRES_USER}'"] - interval: 10s + interval: 3s timeout: 5s retries: 3 diff --git a/scripts/README.md b/scripts/README.md index 9739734..424f38b 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -6,7 +6,6 @@ Right now there are this scripts: - `create_branch.ps1` - `clean_branches.ps1` - `create_pr.ps1` -- `apply_migrations.ps1` Two out of those (`create_branch.ps1` and `create_pr.ps1`) require user to have GitHub CLI installed and to be logged in. @@ -33,5 +32,3 @@ Two out of those (`create_branch.ps1` and `create_pr.ps1`) require user to have - `.\scripts\create_branch.ps1 -Assignee sojusan` - `clean_branches.ps1` - clears all of the local branches except for master and the current one. - -- `apply_migrations.ps1` - runs a project database in a docker container and performs migrations in the database. diff --git a/scripts/apply_migrations.ps1 b/scripts/apply_migrations.ps1 deleted file mode 100755 index 773a305..0000000 --- a/scripts/apply_migrations.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env pwsh -Write-Host "Loading Env" -get-content ../.env | foreach { - if($_.StartsWith("#") -or [string]::IsNullOrWhitespace($_)){ - return - } - $name, $value = $_.split('=') - set-content env:\$name $value -} - -Write-Host "Starting DB" -docker compose up db -d 2>&1 > $null -Write-Output "Generateing migration script" -Set-Location ../backend -mkdir migration_scripts 2>&1 > $null -dotnet ef migrations script --idempotent -o ./migration_scripts/migration.sql -p ./src/infrastructure -s ./src/api - -Write-Output "Applying.." -$passwd = "PGPASSWORD=" + $Env:POSTGRES_PASSWORD -$src = Join-Path $(Get-Location).Path migration_scripts -docker run --network host -e $passwd -v ${src}:/migrations/ --rm postgres ` - psql -h localhost -U $Env:POSTGRES_USER -d ksummarized -f /migrations/migration.sql ` - 2>&1 > $null - -Write-Output "Cleanup" -Remove-Item -Recurse -Force migration_scripts -Set-Location ../scripts -Write-Output "Migrations had been applyed!" -Write-Host "Stoping DB" -docker stop ks-database 2>&1 > $null -Write-Host "Done"