2026-09-20 18:35:27 +01:00
|
|
|
DESTDIR=
|
|
|
|
|
DOTNET_FRAMEWORK=net10.0
|
2026-08-30 23:55:09 +01:00
|
|
|
APP_PROJECT_NAMES=Org Blogs Api
|
2026-02-28 14:22:33 +00:00
|
|
|
SLNDIR=..
|
2026-09-20 18:35:27 +01:00
|
|
|
APP_INSTALL_ENV=preprod
|
2026-09-21 10:37:39 +01:00
|
|
|
APP_INSTALL_PREFIX=preprod-
|
|
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
include .$(APP_INSTALL_ENV).env
|
2026-02-28 14:22:33 +00:00
|
|
|
|
2026-09-21 12:49:38 +01:00
|
|
|
reinstall: copy-binaries
|
|
|
|
|
@for project in $(APP_PROJECT_NAMES); do \
|
2026-09-21 14:58:40 +01:00
|
|
|
echo "🚀 Starting $(APP_INSTALL_PREFIX)yavsc$${project}" ; \
|
2026-09-21 12:49:38 +01:00
|
|
|
sudo systemctl start $(APP_INSTALL_PREFIX)yavsc$${project} ; done
|
|
|
|
|
@echo "💯 backend started"
|
|
|
|
|
|
|
|
|
|
reinstall-prod:
|
2026-10-03 22:47:47 +01:00
|
|
|
make reinstall APP_INSTALL_PREFIX= APP_INSTALL_ENV=production
|
2026-02-28 14:22:33 +00:00
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
generated/$(APP_INSTALL_PREFIX)yavscOrg.service:
|
|
|
|
|
generated/$(APP_INSTALL_PREFIX)yavscBlogs.service:
|
|
|
|
|
generated/$(APP_INSTALL_PREFIX)yavscApi.service:
|
2026-06-06 21:10:48 +01:00
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
generated/$(APP_INSTALL_PREFIX)yavsc%.service: generated/ template.service $(SLNDIR)/.env
|
2026-06-06 21:10:48 +01:00
|
|
|
@cat template.service | APP_NAME="$*" \
|
2026-08-30 23:55:09 +01:00
|
|
|
DESTDIR="$(DESTDIR)" \
|
2026-06-14 18:26:40 +01:00
|
|
|
HTTP_HOST="$(HTTP_HOST)" \
|
2026-09-25 13:27:00 +01:00
|
|
|
HTTP_PORT="$($*_PORT)" \
|
2026-09-20 18:35:27 +01:00
|
|
|
APPDIR="$(APPDIR)" \
|
|
|
|
|
APP_SYSLOG_ID="$(APP_INSTALL_PREFIX)yavsc$*" \
|
2026-06-06 21:10:48 +01:00
|
|
|
POSTGRES_HOST="$(POSTGRES_HOST)" \
|
|
|
|
|
POSTGRES_PORT="$(POSTGRES_PORT)" \
|
|
|
|
|
POSTGRES_DB="$(POSTGRES_DB)" \
|
|
|
|
|
POSTGRES_USER="$(POSTGRES_USER)" \
|
|
|
|
|
POSTGRES_PASSWORD="$(POSTGRES_PASSWORD)" \
|
|
|
|
|
ANTHROPIC_API_KEY="$(ANTHROPIC_API_KEY)" \
|
|
|
|
|
ANTHROPIC_MAX_TOKENS="$(ANTHROPIC_MAX_TOKENS)" \
|
2026-06-19 19:50:04 +01:00
|
|
|
ASPNETCORE_Smtp__Host="$(ASPNETCORE_Smtp__Host)" \
|
|
|
|
|
ASPNETCORE_Smtp__Port="$(ASPNETCORE_Smtp__Port)" \
|
|
|
|
|
ASPNETCORE_Smtp__SenderName=$(ASPNETCORE_Smtp__SenderName) \
|
|
|
|
|
ASPNETCORE_Smtp__SenderEmail="$(ASPNETCORE_Smtp__SenderEmail)" \
|
|
|
|
|
ASPNETCORE_Smtp__UserName="$(ASPNETCORE_Smtp__UserName)" \
|
|
|
|
|
ASPNETCORE_Smtp__Password="$(ASPNETCORE_Smtp__Password)" \
|
2026-06-06 21:10:48 +01:00
|
|
|
envsubst > $@
|
|
|
|
|
@echo Created service file: $@
|
|
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
generate-service-units: generated/$(APP_INSTALL_PREFIX)yavscOrg.service generated/$(APP_INSTALL_PREFIX)yavscBlogs.service generated/$(APP_INSTALL_PREFIX)yavscApi.service
|
|
|
|
|
|
2026-09-25 13:27:00 +01:00
|
|
|
# --- Vhosts nginx (générés par envsubst, à l'image des unités systemd) ---
|
|
|
|
|
# make generate-nginx -> generated/nginx/preprod-yavsc{Org,Blogs,Api}
|
|
|
|
|
# make generate-nginx APP_INSTALL_ENV=production APP_INSTALL_PREFIX= -> prod (yavsc/api/blogs.pschneider.fr)
|
|
|
|
|
#
|
Génération contrib : vhosts nginx h3 edge + appsettings (jq) + QUIC logiciel Kestrel
Vhosts nginx (contrib/template.vhost + Makefile, envsubst allowlist) :
HTTP/3 edge per contrib/quic.md — listen 443 quic reuseport (Org only),
http2/http3 on, Alt-Svc, ssl_protocols TLSv1.3. Cibles generate-nginx /
generate-nginx-prod -> generated/nginx/ (gitignoré). Allowlist préserve
les variables nginx intrinsèques ($host, $scheme, ...).
Appsettings (contrib/template.appsettings-{org,api,blogs}.json + Makefile) :
génération via jq (et non envsubst) car le mot de passe SMTP contient un qui cassait le JSON. Substitue $DOMAIN (DOMAIN_ROOT) partout et injecte
$SMTP_PASSWORD depuis env (échappement JSON, secret non exposé en cmd).
Cible generate-appsettings -> generated/appsettings/.
QUIC logiciel : Kestrel:Endpoints:Https:Protocols = Http1AndHttp2AndHttp3
sur les 3 templates appsettings (capacité, non joignable derrière nginx).
Fix bonus : générateur systemd HTTP_PORT"$($*_PORT)" (était
"$*_$(HTTP_PORT)" -> port vide localhost:Org_).
Runbook contrib/README.nginx.md. Prérequis host : nginx http_v3_module,
UDP 443, libmsquic (Kestrel h3).
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-25 13:31:56 +01:00
|
|
|
# HTTP/3 (QUIC) termine au edge nginx (plan contrib/quic.md). Requiert nginx
|
|
|
|
|
# avec http_v3_module + UDP 443 ouvert. reuseport sur Org uniquement
|
|
|
|
|
# (QUIC_OPTS). Les vhosts générés vont dans generated/nginx/ (gitignoré).
|
2026-09-25 13:27:00 +01:00
|
|
|
NGINX_TEMPLATE := template.vhost
|
|
|
|
|
NGINX_OUT_DIR := generated/nginx
|
|
|
|
|
NGINX_HOSTS := Org Blogs Api
|
|
|
|
|
DOMAIN_ROOT ?= pschneider.fr
|
|
|
|
|
# Schéma backend Kestrel : https en prod (Kestrel écoute HTTPS, cert Let's
|
|
|
|
|
# Encrypt), http en preprod (Kestrel écoute HTTP simple, cf. .preprod.env).
|
|
|
|
|
BACKEND_SCHEME ?= $(if $(filter production,$(APP_INSTALL_ENV)),https,http)
|
|
|
|
|
# sous-domaine par hôte : Org -> yavsc, Api -> api, Blogs -> blogs
|
|
|
|
|
nginx_subdomain = $(if $(filter Org,$1),yavsc,$(if $(filter Api,$1),api,$(if $(filter Blogs,$1),blogs,$1)))
|
|
|
|
|
# domaine complet : <prefix><subdomain>.<DOMAIN_ROOT>
|
|
|
|
|
# prod Org -> yavsc.pschneider.fr
|
|
|
|
|
# preprod Org -> preprod-yavsc.pschneider.fr
|
|
|
|
|
nginx_domain = $(APP_INSTALL_PREFIX)$(call nginx_subdomain,$1).$(DOMAIN_ROOT)
|
|
|
|
|
|
2026-09-25 18:32:44 +01:00
|
|
|
# QUIC_OPTS : "reuseport" n'est légal qu'une seule fois par addr:port
|
|
|
|
|
# (443/udp). preprod et prod partagent aujourd'hui la même IP, donc on ne
|
|
|
|
|
# l'active qu'en production, sur Org uniquement. En preprod, QUIC_OPTS est
|
|
|
|
|
# vide sur tous les vhosts (sinon nginx refuse la config : duplicate
|
|
|
|
|
# reuseport sur le même socket 443/udp entre preprod-Org et prod-Org).
|
2026-09-25 13:27:00 +01:00
|
|
|
$(NGINX_OUT_DIR)/$(APP_INSTALL_PREFIX)yavsc%: $(NGINX_OUT_DIR) $(NGINX_TEMPLATE) .$(APP_INSTALL_ENV).env
|
|
|
|
|
@cat $(NGINX_TEMPLATE) \
|
|
|
|
|
| DOMAIN="$(call nginx_domain,$*)" \
|
|
|
|
|
BACKEND_SCHEME="$(BACKEND_SCHEME)" \
|
|
|
|
|
HTTP_HOST="$(HTTP_HOST)" \
|
|
|
|
|
BACKEND_PORT="$($*_PORT)" \
|
2026-09-25 18:32:44 +01:00
|
|
|
QUIC_OPTS="$(if $(filter production,$(APP_INSTALL_ENV)),$(if $(filter Org,$*), reuseport,),)" \
|
2026-09-25 13:27:00 +01:00
|
|
|
envsubst '$$DOMAIN $$BACKEND_SCHEME $$HTTP_HOST $$BACKEND_PORT $$QUIC_OPTS' > $@
|
|
|
|
|
@echo Created nginx vhost: $@
|
|
|
|
|
|
|
|
|
|
generate-nginx: $(addprefix $(NGINX_OUT_DIR)/$(APP_INSTALL_PREFIX)yavsc,$(NGINX_HOSTS))
|
|
|
|
|
|
|
|
|
|
generate-nginx-prod:
|
|
|
|
|
make generate-nginx APP_INSTALL_ENV=production APP_INSTALL_PREFIX=
|
|
|
|
|
|
|
|
|
|
$(NGINX_OUT_DIR):
|
|
|
|
|
@mkdir -p $@
|
|
|
|
|
|
Génération contrib : vhosts nginx h3 edge + appsettings (jq) + QUIC logiciel Kestrel
Vhosts nginx (contrib/template.vhost + Makefile, envsubst allowlist) :
HTTP/3 edge per contrib/quic.md — listen 443 quic reuseport (Org only),
http2/http3 on, Alt-Svc, ssl_protocols TLSv1.3. Cibles generate-nginx /
generate-nginx-prod -> generated/nginx/ (gitignoré). Allowlist préserve
les variables nginx intrinsèques ($host, $scheme, ...).
Appsettings (contrib/template.appsettings-{org,api,blogs}.json + Makefile) :
génération via jq (et non envsubst) car le mot de passe SMTP contient un qui cassait le JSON. Substitue $DOMAIN (DOMAIN_ROOT) partout et injecte
$SMTP_PASSWORD depuis env (échappement JSON, secret non exposé en cmd).
Cible generate-appsettings -> generated/appsettings/.
QUIC logiciel : Kestrel:Endpoints:Https:Protocols = Http1AndHttp2AndHttp3
sur les 3 templates appsettings (capacité, non joignable derrière nginx).
Fix bonus : générateur systemd HTTP_PORT"$($*_PORT)" (était
"$*_$(HTTP_PORT)" -> port vide localhost:Org_).
Runbook contrib/README.nginx.md. Prérequis host : nginx http_v3_module,
UDP 443, libmsquic (Kestrel h3).
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-25 13:31:56 +01:00
|
|
|
# --- appsettings (générés depuis template.appsettings-*.json) ---
|
|
|
|
|
# make generate-appsettings -> generated/appsettings/appsettings-{org,api,blogs}.json
|
|
|
|
|
#
|
|
|
|
|
# Substitue $DOMAIN (racine du domaine, cf. DOMAIN_ROOT) dans toutes les
|
|
|
|
|
# chaînes, et $SMTP_PASSWORD (secret du .env) dans Smtp.Password.
|
|
|
|
|
# On utilise jq (et non envsubst) car envsubst n'échappe pas le JSON : un
|
|
|
|
|
# secret contenant \ ou " casserait le JSON (le mot de passe SMTP actuel
|
|
|
|
|
# contient un \). jq lit le secret depuis l'environnement (export) ->
|
|
|
|
|
# échappement JSON correct, aucun shell-quoting ni exposition en ligne de cmd.
|
|
|
|
|
# Les templates actuels sont issus de la preprod (préfixe preprod-, ports
|
|
|
|
|
# 88-93) ; pour la prod il faudra un template prod (ports 82-87, sans préfixe).
|
|
|
|
|
export ASPNETCORE_Smtp__Password
|
|
|
|
|
APPSETTINGS_OUT_DIR := generated/appsettings
|
|
|
|
|
APPSETTINGS_HOSTS := org api blogs
|
|
|
|
|
|
|
|
|
|
$(APPSETTINGS_OUT_DIR)/appsettings-%.json: $(APPSETTINGS_OUT_DIR) template.appsettings-%.json .$(APP_INSTALL_ENV).env
|
|
|
|
|
@jq --arg domain "$(DOMAIN_ROOT)" \
|
|
|
|
|
'walk(if type=="string" then gsub("\\$$DOMAIN"; $$domain) else . end) | if has("Smtp") then .Smtp.Password = env["ASPNETCORE_Smtp__Password"] else . end' \
|
|
|
|
|
template.appsettings-$*.json > $@
|
|
|
|
|
@echo Created appsettings: $@
|
|
|
|
|
|
|
|
|
|
generate-appsettings: $(addprefix $(APPSETTINGS_OUT_DIR)/appsettings-,$(addsuffix .json,$(APPSETTINGS_HOSTS)))
|
|
|
|
|
|
|
|
|
|
$(APPSETTINGS_OUT_DIR):
|
|
|
|
|
@mkdir -p $@
|
|
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
install-service-%: /etc/systemd/system/$(APP_INSTALL_PREFIX)yavsc%.service
|
|
|
|
|
sudo systemctl daemon-reload
|
|
|
|
|
sudo systemctl enable $(APP_INSTALL_PREFIX)yavsc$*
|
2026-06-06 21:10:48 +01:00
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
install-services: install-service-Org install-service-Blogs install-service-Api
|
2026-06-06 21:10:48 +01:00
|
|
|
|
2026-08-30 23:55:09 +01:00
|
|
|
copy-binaries: build_publish_Org build_publish_Blogs build_publish_Api stop-services
|
2026-06-19 16:18:39 +01:00
|
|
|
@for project in $(APP_PROJECT_NAMES); \
|
|
|
|
|
do LCAPI=$$(echo $${project}|tr [:upper:] [:lower:]) ; \
|
|
|
|
|
echo "$${project} -> $${LCAPI}" ; \
|
|
|
|
|
BINDIR="$(SLNDIR)/src/Yavsc.$${project}/bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish" ; \
|
|
|
|
|
echo BINDIR: $${BINDIR} ; \
|
2026-06-19 21:13:17 +01:00
|
|
|
rm -f $${BINDIR}/appsettings-$${LCAPI}-dist.json ; \
|
|
|
|
|
mv -f $${BINDIR}/appsettings-$${LCAPI}.json \
|
2026-06-19 16:18:39 +01:00
|
|
|
$${BINDIR}/appsettings-$${LCAPI}-dist.json ; \
|
2026-06-19 21:13:17 +01:00
|
|
|
rm -f $${BINDIR}/appsettings-$${LCAPI}.json ; \
|
|
|
|
|
sync ; \
|
|
|
|
|
ls $${BINDIR}/appsettings* 2>&1 ; \
|
2026-09-20 18:35:27 +01:00
|
|
|
sudo cp -a $${BINDIR}/* $(DESTDIR)$(APPDIR) ; \
|
2026-06-06 21:10:48 +01:00
|
|
|
done
|
2026-09-20 18:35:27 +01:00
|
|
|
@sudo chown -R $(USER_AND_GROUP) $(DESTDIR)$(APPDIR)
|
|
|
|
|
@sync
|
|
|
|
|
|
|
|
|
|
$(DESTDIR)/etc/systemd/system/$(APP_INSTALL_PREFIX)yavsc%.service: generated/$(APP_INSTALL_PREFIX)yavsc%.service
|
2026-02-28 14:22:33 +00:00
|
|
|
sudo cp $^ $@
|
2026-06-06 21:10:48 +01:00
|
|
|
sudo chown root:root $@
|
2026-02-28 14:22:33 +00:00
|
|
|
|
2026-06-19 21:13:17 +01:00
|
|
|
build_publish_%: clean_publish_dir_%
|
2026-06-19 16:18:39 +01:00
|
|
|
@ASPNETCORE_ENV=$(CONFIGURATION) dotnet publish $(SLNDIR)/src/Yavsc.$*/Yavsc.$*.csproj
|
2026-06-13 20:57:30 +01:00
|
|
|
|
2026-06-19 21:13:17 +01:00
|
|
|
clean_publish_dir_%:
|
|
|
|
|
@rm -rf $(SLNDIR)/src/Yavsc.$*/bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish
|
|
|
|
|
|
2026-09-20 18:35:27 +01:00
|
|
|
install: copy-binaries copy-services
|
2026-06-19 16:18:39 +01:00
|
|
|
@sudo systemctl daemon-reload
|
|
|
|
|
@for project in $(APP_PROJECT_NAMES); \
|
2026-06-06 21:10:48 +01:00
|
|
|
do \
|
2026-09-21 14:58:40 +01:00
|
|
|
echo "🖒 enable $(APP_INSTALL_PREFIX)yavsc$${project}" ; \
|
|
|
|
|
sudo systemctl enable $(APP_INSTALL_PREFIX)yavsc$${project} ; \
|
|
|
|
|
echo "🚀 start $(APP_INSTALL_PREFIX)yavsc$${project}" ; \
|
|
|
|
|
sudo systemctl start $(APP_INSTALL_PREFIX)yavsc$${project} ; \
|
2026-06-06 21:10:48 +01:00
|
|
|
done
|
feat(postit): circles+ACL UI, blog fixture→SQLite, seed default user
Bundled end-of-branch commit on feat/postit-acl-members.
PostIt UI for circles + per-post ACL
- Reorganise PostIt.Tests into Auth/ and Blogs/ subfolders
(Bearer/OIDC scope tests vs. blog API fakes live where they
belong) and introduces PostItHeadlessCollection so the
Avalonia.Headless tests share a single xUnit collection
instead of contending with the EF-Core test host.
- Adds BlogAclApiTests (a brand-new behavioural layer over
POST /api/v1/blogacl) and the fakes it relies on
(BlogApiTestFakes, BlogPostAuthorDtoTests, AddCircleMember
DialogTests); pulls UserId-through-OIDC-sub path into
BearerScopeTests / FakeAuthorizingBrowser /
OidcStubAuthority.
- App.axaml.cs gets a small PushPageAsync touch-up the new
tests rely on.
- Drops UnitTest1.cs (xUnit scaffold, never used).
Yavsc.Blogs.Tests — SQLite instead of InMemory
- Bumps Yavsc.Blogs.Tests.csproj on
Microsoft.EntityFrameworkCore.Sqlite and rewrites
BlogsWebServerFixture to hold a single shared
SqliteConnection (Cache=Shared) for the fixture lifetime,
with a sync Dispose close to dodge async teardown hangs.
Reason: the EF Core InMemory provider silently ignores FKs,
which masked the kind of bug we are about to pin in the
ACL tests. SQLite enforces them, so any future INSERT that
forgets to seed its parent rows fails loudly here instead
of passing the test and breaking prod.
- PublishEndpointTests and BlogApiSmokeTests get a one-line
tweak to follow the new connection lifecycle.
Foreign-key fallout: seed the default user in the fixture
- Adds BlogsWebServerFixture.SeedUser(userName). Now that
SQLite enforces BlogPost.AuthorId → AspNetUsers.Id, every
test that POST/PUT/DELETE a BlogPost and sends AuthorId=
'tester' in the payload needs an AspNetUsers row to satisfy
the FK or it returns 500 with SQLite Error 19.
- BlogApiTests wraps the existing ResetDatabase with a
ResetAndSeedDefaultUser helper for the six mutating tests;
the four GET-only and ModelState-only tests keep the bare
ResetDatabase.
- Side benefit: every test in Yavsc.Blogs.Tests now finishes
cleanly instead of hanging at teardown — previously a stuck
test held the shared SqliteConnection open and the next
tests waited indefinitely.
Verified: dotnet test src/Yavsc.Blogs.Tests passes 25/25
green from a clean run, no fixture teardown hang.
2026-08-20 23:59:21 +01:00
|
|
|
|
2026-06-14 18:26:40 +01:00
|
|
|
stop-services:
|
2026-06-19 16:18:39 +01:00
|
|
|
@for project in $(APP_PROJECT_NAMES); \
|
2026-06-06 21:10:48 +01:00
|
|
|
do \
|
2026-09-21 14:58:40 +01:00
|
|
|
echo "🔥 Stopping $(APP_INSTALL_PREFIX)yavsc$${project}" ; \
|
2026-09-21 12:49:38 +01:00
|
|
|
sudo systemctl stop $(APP_INSTALL_PREFIX)yavsc$${project} ; \
|
2026-02-28 14:22:33 +00:00
|
|
|
done
|
2026-06-13 20:57:30 +01:00
|
|
|
|
|
|
|
|
$(SLNDIR)/src/Yavsc.Org/bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish: build_publish
|
|
|
|
|
$(SLNDIR)/src/Yavsc.Blogs/bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish: build_publish
|
2026-08-30 23:55:09 +01:00
|
|
|
$(SLNDIR)/src/Yavsc.Api/bin/$(CONFIGURATION)/$(DOTNET_FRAMEWORK)/publish: build_publish
|
2026-06-13 20:57:30 +01:00
|
|
|
|
feat(postit): circles+ACL UI, blog fixture→SQLite, seed default user
Bundled end-of-branch commit on feat/postit-acl-members.
PostIt UI for circles + per-post ACL
- Reorganise PostIt.Tests into Auth/ and Blogs/ subfolders
(Bearer/OIDC scope tests vs. blog API fakes live where they
belong) and introduces PostItHeadlessCollection so the
Avalonia.Headless tests share a single xUnit collection
instead of contending with the EF-Core test host.
- Adds BlogAclApiTests (a brand-new behavioural layer over
POST /api/v1/blogacl) and the fakes it relies on
(BlogApiTestFakes, BlogPostAuthorDtoTests, AddCircleMember
DialogTests); pulls UserId-through-OIDC-sub path into
BearerScopeTests / FakeAuthorizingBrowser /
OidcStubAuthority.
- App.axaml.cs gets a small PushPageAsync touch-up the new
tests rely on.
- Drops UnitTest1.cs (xUnit scaffold, never used).
Yavsc.Blogs.Tests — SQLite instead of InMemory
- Bumps Yavsc.Blogs.Tests.csproj on
Microsoft.EntityFrameworkCore.Sqlite and rewrites
BlogsWebServerFixture to hold a single shared
SqliteConnection (Cache=Shared) for the fixture lifetime,
with a sync Dispose close to dodge async teardown hangs.
Reason: the EF Core InMemory provider silently ignores FKs,
which masked the kind of bug we are about to pin in the
ACL tests. SQLite enforces them, so any future INSERT that
forgets to seed its parent rows fails loudly here instead
of passing the test and breaking prod.
- PublishEndpointTests and BlogApiSmokeTests get a one-line
tweak to follow the new connection lifecycle.
Foreign-key fallout: seed the default user in the fixture
- Adds BlogsWebServerFixture.SeedUser(userName). Now that
SQLite enforces BlogPost.AuthorId → AspNetUsers.Id, every
test that POST/PUT/DELETE a BlogPost and sends AuthorId=
'tester' in the payload needs an AspNetUsers row to satisfy
the FK or it returns 500 with SQLite Error 19.
- BlogApiTests wraps the existing ResetDatabase with a
ResetAndSeedDefaultUser helper for the six mutating tests;
the four GET-only and ModelState-only tests keep the bare
ResetDatabase.
- Side benefit: every test in Yavsc.Blogs.Tests now finishes
cleanly instead of hanging at teardown — previously a stuck
test held the shared SqliteConnection open and the next
tests waited indefinitely.
Verified: dotnet test src/Yavsc.Blogs.Tests passes 25/25
green from a clean run, no fixture teardown hang.
2026-08-20 23:59:21 +01:00
|
|
|
showConfig:
|
2026-02-28 14:22:33 +00:00
|
|
|
@echo CONFIGURATION: $(CONFIGURATION)
|
2026-09-20 18:35:27 +01:00
|
|
|
@echo APPDIR: $(APPDIR)
|
2026-02-28 14:22:33 +00:00
|
|
|
|
2026-09-13 18:54:27 +01:00
|
|
|
showApiLogs:
|
|
|
|
|
@sudo journalctl -u yavscApi.service -S "2 min ago" | tee yavscApi.log
|
|
|
|
|
|
|
|
|
|
showOrgLogs:
|
|
|
|
|
@sudo journalctl -u yavscOrg.service -S "2 min ago" | tee yavscOrg.log
|
|
|
|
|
|
|
|
|
|
showBlogsLogs:
|
|
|
|
|
@sudo journalctl -u yavscBlogs.service -S "2 min ago" | tee yavscBlogs.log
|
|
|
|
|
|
2026-06-06 21:10:48 +01:00
|
|
|
clean:
|
2026-06-19 16:18:39 +01:00
|
|
|
@rm -rf generated
|
2026-06-06 21:10:48 +01:00
|
|
|
|
2026-09-21 12:49:38 +01:00
|
|
|
generated/:
|
|
|
|
|
@mkdir -p $@
|