diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml
index 5cafda9..20513db 100644
--- a/.gitea/workflows/build.yml
+++ b/.gitea/workflows/build.yml
@@ -1,13 +1,19 @@
-name: Build and Push Docker Images Staging
+name: Build and Push Docker Images
+# Branch-driven deploys — no yaml edits to switch environment:
+# merge into `staging` -> tag :staging (staging Watchtower deploys)
+# merge into `production` -> tag :production (production Watchtower deploys)
+# `main` is the day-to-day work branch and deploys nothing.
on:
push:
branches:
+ - staging
- production
env:
GIT_HOST: git.easysoft.ro
REGISTRY_HOST: registry.easysoft.ro
+ DOCKER_BUILDKIT: "1"
API_IMAGE: apps/myai-api
CV_MATCHER_API_IMAGE: apps/myai-cv-matcher-api
RAG_API_IMAGE: apps/myai-rag-api
@@ -16,18 +22,19 @@ env:
CV_CLEANUP_JOB_IMAGE: apps/myai-cv-cleanup-job
CV_SEARCH_JOB_IMAGE: apps/myai-cv-search-job
PAGE_FETCHER_API_IMAGE: apps/myai-page-fetcher-api
- IMAGE_TAG: production
+ IMAGE_TAG: ${{ github.ref_name }} # branch name == image tag (staging | production)
jobs:
build:
runs-on: host
steps:
- - name: Checkout repository
+ - name: Checkout the pushed commit
env:
TOKEN: ${{ secrets.REPO_TOKEN }}
run: |
git clone "http://gelu:${TOKEN}@${GIT_HOST}:3000/${GITHUB_REPOSITORY}.git" .
+ git checkout "${{ github.sha }}"
- name: Login to registry
run: |
@@ -97,4 +104,9 @@ jobs:
- name: Push Page Fetcher API image
run: |
- docker push "${REGISTRY_HOST}/${PAGE_FETCHER_API_IMAGE}:${IMAGE_TAG}"
\ No newline at end of file
+ docker push "${REGISTRY_HOST}/${PAGE_FETCHER_API_IMAGE}:${IMAGE_TAG}"
+
+ - name: Reclaim disk space (keep recent build cache)
+ if: always()
+ run: |
+ docker image prune -f # dangling only (keep base images)
diff --git a/.gitignore b/.gitignore
index b4be5a0..24928ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -376,3 +376,6 @@ files/
/docker-compose/.env.production
/docker-compose/.env.staging
+
+# local infra access notes (secrets) — never commit
+ACCESS.md
diff --git a/CLAUDE.md b/CLAUDE.md
index a7786c6..0b8bc91 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -34,11 +34,15 @@ This applies to both the staging and production repos as appropriate.
- .NET 10, ASP.NET Core, Worker Service
- Entity Framework Core + SQL Server (multi-schema)
- Refit for typed HTTP clients between services
-- Serilog (JSON structured logging, Console + File + Email sinks)
+- Serilog — Compact JSON logs to stdout (+ optional email sink); see Observability
- MailKit for SMTP (used exclusively in `email-api`)
- Docker Compose for local and production deployment
- Watchtower for automatic container updates in production
+## Observability (central stack on monitoring host 10.0.0.156)
+- **Logs**: every service uses `ConfigureJsonSerilog(ServiceName, appVersion)` (startup-helpers) → Serilog **Compact JSON** to stdout, enriched `Application`/`Environment`/`AppVersion`. The host's Grafana **Alloy** agent ships stdout → **Loki**; view/query in Grafana. No file sink; optional email sink only if `SerilogEmail:*` is configured.
+- **No app metrics/traces** — these are simple/minimal services, so (unlike easyDent) they don't expose Prometheus metrics or OTLP traces. Container/host metrics still come from the host's cAdvisor/node_exporter.
+
## Project taxonomy
| Category | Naming | Contains | EF dependency |
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 7d04f04..817eda5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -23,6 +23,7 @@
+
diff --git a/Helpers/startup-helpers/StartupExtensions.cs b/Helpers/startup-helpers/StartupExtensions.cs
index c806e1b..ce55b4d 100644
--- a/Helpers/startup-helpers/StartupExtensions.cs
+++ b/Helpers/startup-helpers/StartupExtensions.cs
@@ -39,11 +39,10 @@ public static class StartupExtensions
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
- .Enrich.WithMachineName()
- .Enrich.WithEnvironmentName()
- .Enrich.WithProperty("Service", serviceName)
+ .Enrich.WithProperty("Application", serviceName)
+ .Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
.Enrich.WithProperty("AppVersion", appVersion)
- .WriteTo.Console(new Serilog.Formatting.Json.JsonFormatter());
+ .WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter());
AddEmailSinkIfConfigured(configuration, context.Configuration, serviceName);
});
@@ -57,11 +56,10 @@ public static class StartupExtensions
.ReadFrom.Configuration(builder.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
- .Enrich.WithMachineName()
- .Enrich.WithEnvironmentName()
- .Enrich.WithProperty("Service", serviceName)
+ .Enrich.WithProperty("Application", serviceName)
+ .Enrich.WithProperty("Environment", builder.Environment.EnvironmentName)
.Enrich.WithProperty("AppVersion", appVersion)
- .WriteTo.Console(new Serilog.Formatting.Json.JsonFormatter());
+ .WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter());
AddEmailSinkIfConfigured(configuration, builder.Configuration, serviceName);
});
diff --git a/Helpers/startup-helpers/startup-helpers.csproj b/Helpers/startup-helpers/startup-helpers.csproj
index 89d7a7c..0563262 100644
--- a/Helpers/startup-helpers/startup-helpers.csproj
+++ b/Helpers/startup-helpers/startup-helpers.csproj
@@ -17,6 +17,7 @@
+
diff --git a/README.md b/README.md
index e37e4b1..07b1666 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,27 @@
-# Introduction
-TODO: Give a short introduction of your project. Let this section explain the objectives or the motivation behind this project.
+# myAi
-# Getting Started
-TODO: Guide users through getting your code up and running on their own system. In this section you can talk about:
-1. Installation process
-2. Software dependencies
-3. Latest releases
-4. API references
+The **myai.ro** platform — a set of .NET microservices (CV matching, RAG, email, CV search, page
+fetching, …) behind a web frontend + API. Part of the easySoft platform.
-# Build and Test
-TODO: Describe and show how to build your code and run the tests.
+## Layout
+Multiple services (`*-api`, `*-job`) + `web`, sharing a common bootstrap in
+`startup-helpers/` (Serilog, Swagger, `.env`/Key Vault loading, middleware). See **CLAUDE.md**
+for the full service map, dependency chain, and conventions.
-# Contribute
-TODO: Explain how other users and developers can contribute to make your code better.
+## Run locally
+```bash
+docker compose up --build # or run individual services with: dotnet run --project
+```
-If you want to learn more about creating good readme files then refer the following [guidelines](https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops). You can also seek inspiration from the below readme files:
-- [ASP.NET Core](https://github.com/aspnet/Home)
-- [Visual Studio Code](https://github.com/Microsoft/vscode)
-- [Chakra Core](https://github.com/Microsoft/ChakraCore)
\ No newline at end of file
+## Deploy
+CI builds `registry.easysoft.ro/apps/myai-*:{staging,production}`; Watchtower rolls them out to
+the **staging (`10.0.0.183`)** + **production (`10.0.0.248`)** Portainer stacks. Edge Caddy serves
+**myai.ro** (prod) / **myai.easysoft.ro** (staging).
+
+## Logging
+Every service: `ConfigureJsonSerilog(name, version)` → Serilog **Compact JSON** to stdout → Grafana
+**Alloy** → **Loki**. No app metrics/traces (simple services).
+
+---
+See **CLAUDE.md** for the detailed solution guide and **ACCESS.md** (local, gitignored) for
+infrastructure access.