Read-only mirror of https://github.com/swisstopo/swissgeol-boreholes-suite — Bundesamt für Landestopografie. Issues & pull requests at the source. Catalog: https://www.opensource.admin.ch/en/softwares/eod5b9 https://www.opensource.admin.ch/en/softwares/eod5b9
  • C# 67.9%
  • TypeScript 30.9%
  • JavaScript 1%
  • Shell 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-15 12:03:37 +02:00
.github Bump actions/download-artifact from 8.0.1 to 8.0.2 (#3079) 2026-10-15 12:03:37 +02:00
.vscode Switch type aware linting to oxlint 2026-09-24 13:29:01 +02:00
charts Mark version 2.2.57 as released 2026-10-08 14:11:07 +00:00
config Update create user script 2026-05-20 08:51:34 +02:00
db Fix default sorting 2024-08-13 16:39:19 +02:00
environments Bump INT to version 2.2.57 2026-10-08 08:59:10 +00:00
src Bump i18next-http-backend from 3.0.6 to 4.0.2 in /src/client (#3074) 2026-10-15 09:45:50 +02:00
tests Check extern-sync duplicates in all workgroups 2026-10-01 13:30:14 +02:00
.dockerignore
.editorconfig Update to .NET 10 2026-09-03 10:15:58 +02:00
.gitattributes
.gitignore Port lens to ts (#2883) 2026-06-18 11:52:53 +02:00
BDMS.sln Upgrade Magick 2026-03-27 10:45:41 +01:00
BDMS.slnLaunch Fix indentation in BDMS.slnLaunch 2025-04-28 11:13:22 +02:00
CHANGELOG.md Mark version 2.2.57 as released 2026-10-08 14:11:07 +00:00
ct.yaml Add chart lint workflow 2026-01-29 18:42:02 +01:00
docker-compose.ci.yml Remove api-legacy from compose and CI 2026-06-24 09:13:40 +02:00
docker-compose.dcproj
docker-compose.yml Pin pgsty/minio image by digest 2026-09-29 09:29:39 +02:00
get-changelog.sh
launchSettings.json Remove api-legacy from compose and CI 2026-06-24 09:13:40 +02:00
LICENSE
publiccode.yml Remove softwareVersion from publiccode.yml 2026-03-31 08:12:20 +02:00
README.md Update readme to show new deployment steps accurately 2026-10-06 11:00:44 +02:00
VERSION Rename workflow and file 2026-08-03 10:18:19 +02:00

.github/workflows/ci.yml Release Latest Release License

boreholes.swissgeol.ch

Webapplikation zur einfachen strukturierten und harmonisierten Erfassung von geologischen Bohrdaten.

Einrichten der Entwicklungsumgebung

Folgende Komponenten müssen auf dem Entwicklungsrechner installiert sein:

✔️ Git
✔️ Docker
✔️ Visual Studio 2022
✔️ Node.js 22 LTS
✔️ Optional, um die Onlinehilfe zu erstellen: MkDocs

Entwicklung mit Visual Studio 2022

Es wird eine lokale Installation von Node.js benötigt. Diese kann mit Visual Studio 2022 oder mit nvm installiert werden, um mehrere Node Version zu verwalten. Anschliessend kann mit nvm use die im Projekt verwendete Node Version aktiviert werden.

Das Projekt kann mit dem Launch Profile Boreholes gestartet werden. Dieses startet API und Client lokal (nicht als Container) und im Hintergrund via docker-compose die übrigen Dienste (db, minio, oidc-server, pgadmin, dataextraction, ocr). Mit dem Profil BoreholesWithoutClient wird nur die API lokal gestartet, ohne den Client.

Entwicklung mit Docker

Mit docker-compose up kann eine funktionierende Infrastruktur hochgefahren werden. Sie unterstützt Hot-Reload und lädt den Code aus dem lokalen Verzeichnis. Unter Windows mit Docker-Desktop kann die Synchronisierung in den mounted volumes zu Performance-Problemen führen.

Folgende Dienste/Anwendungen sind anschliessend wie folgt verfügbar

🔖 Dienst/Anwendung 🔗Adresse 🧞Benutzername 🔐Passwort
Boreholes of Switzerland localhost:3000 admin swissforages
pgAdmin localhost:3001 n/a n/a
.NET REST API (v2)1 localhost:5000 localhost:3000/api/v2 n/a n/a
OIDC Server localhost:4011 admin swissforages

Vitest Unit Tests

Die client seitigen Unit Tests werden mit Vitest ausgeführt. Testdateien folgen dem Muster *.test.ts / *.test.tsx. Die Tests können mit folgenden Befehlen ausgeführt werden:

Befehl Beschreibung
npm run test:unit Einmaliger Testlauf aller Unit Tests
npm run test:unit:watch Startet Vitest im Watch-Modus für die Entwicklung

Um einen einzelnen Test auszuführen, kann npx vitest run <Pfad/zur/Testdatei> verwendet werden.

Cypress Tests

Die Cypress Tests können mit npm run cy oder npm run test gestartet werden. Sie werden zudem automatisch in der CI/CD Pipeline ausgeführt. Das Projekt ist mit Cypress Cloud konfiguriert, wodurch unter anderem die parallele Ausführung der End-to-End (E2E) Tests ermöglicht wird. Testergebnisse und Aufzeichnungen sind ebenfalls direkt in Cypress Cloud einsehbar, was die Identifikation und Behebung möglicher Fehler und Probleme erleichtert. Um die detaillierten Testergebnisse einzusehen und die E2E-Tests des Projekts zu debuggen, kann die Cypress Dashboard-Seite besucht werden.

Authentifizierung & Architektur

Die Applikation nutzt das OpenID Connect (OIDC) Protokoll für die Authentifizierung und Teile der Autorisierung. Die Authentifizierung erfolgt über den OIDC Server, welcher in der Entwicklungsumgebung durch soluto/oidc-server-mock auf Basis von IdentityServer4 simuliert wird. Die Applikation nutzt den Authorization Code Flow mit PKCE für die Authentifizierung. Für den Zugriff auf die API wird der identity_token verwendet, welcher die Benutzerinformationen enthält. Die Grundsätzliche Autorisierung erfolgt über die Gruppenzugehörigkeit des Benutzers, welche im identity_token enthalten ist. Die Autorisierung auf API-Ebene erfolgt über die in der Datenbank definierten Workgroups & Administratoren-Rechte.

OpenID Connect (OIDC) Konfiguration

Die Applikation benötigt für die Authentifizierung und Autorisierung eine gültige OIDC-Konfiguration. Diese Konfiguration wird ausschliesslich in BDMS.Api benötigt. Sie wird über /api/v2/settings dem Client zur Verfügung gestellt. Die Werte werden durch den OIDC Server vergeben. Die folgenden Konfigurationen müssen gesetzt werden:

Parameter Beschreibung
Auth:Authority Die URL des OpenID Connect Servers. Es ist vorausgesetzt, dass der Server ein gültiges OpenID Connect Discovery Dokument zur Verfügung stellt.
Auth:Audience Der Wert des aud Claims, welcher in den identity_token des OIDC Servers enthalten ist. Die Audience wird als client_id verwendet beim Authentifizieren auf dem OIDC Endpunkt.
Auth:Scopes Die benötigten Scopes, welche beim Authentifizieren auf dem OIDC Endpunkt angefragt werden. Default: openid profile
Auth:GroupClaimType Der Name des Claims, welcher die Gruppenzugehörigkeit des Benutzers enthält. Default: cognito:groups
Auth:AuthorizedGroupName Der Name der Gruppe, welche autorisiert ist, um auf die API zuzugreifen.
Auth:AnonymousModeEnabled Gibt an, ob die OIDC-Konfiguration ignoriert und die Authentifizierung abgestellt werden soll. Ist für den Betrieb im anonymen Modus (read-only) erforderlich.

Anonymer Modus (read-only)

Die Applikation kann auch im anonymen Modus betrieben werden, um die Bohrdaten öffentlich zugänglich zu machen. In diesem Modus ist die Applikation nur im read-only Modus verfügbar. Die Konfiguration erfolgt über OIDC-Konfiguration (siehe oben). Die Applikation wird im anonymen Modus gestartet, wenn Auth:AnonymousModeEnabled auf true gesetzt ist.

Release- und Deployment-Prozess

Umgebung Auslöser Quelle der App-Version
DEV Merge in main (automatisch) Version aus dem Publish-Lauf
INT Release als Pre-release markieren, die erstellte PR mergen, Deploy Int starten environments/int/version.values.yaml
PROD Release als Latest markieren, die erstellte PR mergen, Helm Chart Action abwarten, Deploy Prod starten app.version in charts/*/values.yaml

Publish und DEV

Jede Änderung, die in den main-Branch gemerged wird, löst automatisch den Publish-Workflow aus. Dieser vergibt eine neue Versionsnummer, baut die Docker-Images mit derselben Version, taggt sie zusätzlich mit :edge, erstellt ein neues GitHub-Release und deployt die Version auf DEV.

Das Release wird bewusst weder als Pre-release noch als Latest markiert. Diese beiden Promotions sind die Auslöser für die weiteren Umgebungen (siehe unten).

INT-Deployment

  1. Im GitHub Release-Bereich das Release öffnen und als „Set as a pre-release" markieren.
  2. Der Workflow Bump INT version erstellt einen PR. Dieser setzt app.version in environments/int/version.values.yaml auf die neue Version.
  3. Den PR reviewen und mergen.
  4. Den Workflow Deploy Int manuell starten.

Alle INT-Releases (App, extern-sync, view-sync) lesen die Version aus version.values.yaml. So laufen sie immer mit derselben Version.

Wenn kein PR entsteht, den Workflow Bump INT version manuell mit der Version starten (z.B. 2.2.50).

PROD-Release

  1. Im GitHub Release-Bereich das Release als „Set as the latest release" markieren.
  2. Der Workflow Release startet automatisch. Er:
    • taggt die Docker-Images zusätzlich mit :latest und :v<major>.
    • übernimmt den Eintrag aus CHANGELOG.md in die Release Notes.
    • erstellt einen PR Mark version … as released. Dieser aktualisiert CHANGELOG.md, app.version und die Chart-Versionen in charts/*/.
  3. Den PR reviewen und mergen. Der Workflow Release Helm Charts publiziert danach die neuen Charts.
  4. Warten, bis Release Helm Charts erfolgreich ist. Sonst deployt der nächste Schritt das alte Chart.
  5. Den Workflow Deploy Prod manuell starten. Ohne Angabe nimmt er die neueste Chart-Version.

Hotfix-Release erstellen

Ein Hotfix-Release wird erstellt, indem vom letzten Release-Git-Tag ein neuer Branch angelegt wird. Dort werden die nötigen Korrekturen gemacht und anschliessend manuell ein neues GitHub Release erstellt, das dann wiederum als „Set as the latest release" markiert werden kann.

Docker-Image-Tags

Tag Beschreibung
:edge Neuester Stand aus main (letzter Publish-Lauf)
:v<version> Bestimmte Version, z.B. :v2.1.1427
:v<major> Stabile Major-Version, z.B. :v2 (wird beim PROD-Release aktualisiert)
:latest Aktuelle produktive Version (PROD-Release)

Helm Chart Versionen

app.version in charts/*/values.yaml ist die Version für PROD. Der PROD-Release-PR aktualisiert sie (siehe oben).

Für dataextraction.version und ocr.version den Workflow Bump service version manuell starten. Er erstellt einen PR, der die Version in charts/swissgeol-boreholes/values.yaml und docker-compose.yml setzt.

Developer best practices

UI/UX

  • Das UI-Design ist in Figma definiert. Unter Pages/Screens sind die definitiven Designs zu finden.
  • Standardmässig werden die Lucid Icons verwendet. Custom-Icons können aus Figma kopiert und als SVG eingebunden werden. Um die Icons farblich stylen zu können, müssen fill und stroke wie folgt angepasst werden fill="currentColor" stroke="currentColor".
  • Wo möglich sollten UI-Komponenten der swissgeol-ui-core und swissgeol-ui-core-react Libraries verwendet werden.
  • Sind keine Komponenten in den Swissgeol UI Libraries vorhanden, muss geklärt werden, ob die Komponente in der Swissgeol UI Library ergänzt werden soll. Je nach Entscheid wird die neue Komponente entwickelt oder MUI als UI Library verwendet. Allgemeine Styles werden im AppTheme.ts definiert und diese Styles werden, wo immer möglich, verwendet. MUI Styled Components im gleichen File mit der Komponente definieren, sobald die Styles mehrfach gebraucht werden. Übergreifende Styled Components werden in styledComponents.ts definiert. Für Abstände (margins, paddings, gaps etc.) sollten möglichst MUI Spacings verwendet werden.

Typescript

  • Neue Komponenten werden in Typescript geschrieben.
  • Es werden bevorzugt Interfaces statt Types verwendet.
  • API-Typen werden aus der OpenAPI-Spezifikation generiert (siehe Abschnitt OpenAPI Codegen unten). Das generierte File types.gen.ts darf nicht manuell bearbeitet werden.
  • Verbleibende hand-geschriebene Interfaces für API Calls werden in den entsprechenden domänenspezifischen Files (z.B. stratigraphy.ts) definiert oder – für das Legacy API – in ReduxStateInterfaces.ts.
  • Existieren mehrere Interfaces für eine Komponente, werden sie in einem separaten File neben der Komponente abgelegt.
  • Das Interface für die React props der Komponente kann im selben File mit der Komponente definiert werden.

Translation

  • Texte werden mit dem useTranslation hook von react-i18next übersetzt. Das withTranslation HOC wird nicht mehr verwendet.
  • Neue Übersetzungskeys alphabetisch sortiert und in CamelCase in den common.json Files unter public/locale erfassen.

API

  • Neue Endpoints werden immer im .NET API erstellt. Das Python Legacy API wird nicht erweitert.
  • Redux wird nicht mehr erweitert. Datenabfragen werden mit dem Javascript Fetch API (siehe fetchApiV2.ts) oder wo sinnvoll mit useQuery von tanstack-query gemacht.
  • Wenn Abfragen aus dem Redux Store in neuen Komponenten gebraucht werden, sollten die React hooks useSelector und useDispatch verwendet werden.

OpenAPI Codegen

Die TypeScript-Typen für das .NET REST API v2 werden automatisch aus der OpenAPI-Spezifikation generiert.

Workflow bei API-Änderungen:

  1. .NET API lokal starten (z.B. via docker-compose up oder Visual Studio)
  2. OpenAPI-Spec aktualisieren und Typen neu generieren:
    cd src/client
    npm run openapi        # holt swagger.json vom laufenden Server und generiert types.gen.ts
    # oder einzeln:
    npm run openapi:fetch  # nur swagger.json aktualisieren
    npm run openapi:gen    # nur Typen aus bestehendem swagger.json generieren
    
  3. Generiertes File src/client/src/api/generated/types.gen.ts via Git committen.

Konfiguration: src/client/openapi-ts.config.ts

⚠️ types.gen.ts wird durch das Tool überschrieben – nie manuell bearbeiten.

Error Handling

Erwartbare Fehler

Inkorrekte User-Inputs, Formvalidation etc. werden direkt in der Komponente abgefangen und dem User als Inline-Message oder Alert angezeigt.

Unerwartete Fehler

Server Error, Render-Fehler etc. werden durch Error Boundaries abgefangen. Sie dienen als Fallback und sollten im normalen Ablauf der Anwendung nicht sichtbar sein. Wichtig: Error Boundaries im korrekten Scope platzieren (z.B. global, Übersichtsseite, Detailseite, Settings), damit möglichst viel der Applikation weiter funktioniert, wenn ein Fehler auftritt. Bei Bedarf können zusätzliche feingranularere Error Boundaries ergänzt werden.

Error Handling in Fetch-Requests

Für neue Fetch-Requests sollte immer fetchApiV2WithApiError (bzw. uploadWithApiError) verwendet werden.

  • Fetch-Requests mit TanStack Query (siehe queryClient-Konfiguration in App.tsx).:

    • GET-Requests Keine Daten im Cache: Die nächste Error Boundary wird gerendert.
    • GET-Requests Daten im Cache vorhanden: Es werden veraltete Daten angezeigt und der Nutzer erhält einen Hinweis (Alert), dass die Daten nicht aktuell sein könnten.
    • ADD/UPDATE/DELETE-Requests: Die bisherigen Daten werden weiterhin angezeigt, Nutzer erhält einen Hinweis (Alert), dass die die Aktion nicht erfolgreich war.
    • Individuelle Reaktion auf Fehler: Bei Fehlern vom Typ ApiError wird kein Standardalert angezeigt (siehe queryClient-Konfiguration in App.tsx). Der isError-State bzw. der onError-Handler der Query/Mutation kann verwendet werden, um je nach Bedarf eine Fallback-Komponente zu rendern oder einen Alert anzuzeigen. ApiError werden entweder direkt clientseitig von der Fetch-Funktion geworfen (siehe Beispiele in file.ts ) oder sie werden für Problem-Responses mit type:"userError" geworfen (siehe handleFetchError in fetchApiV2.ts und StratigraphyV2Controller.cs).
  • Fetch-Requests, die nicht von TanStack Query gemanagt werden (legacy):

    • Wird fetchApiV2WithApiError verwendet, muss der Fetch-Request in einem try-catch-Block ausgeführt und Fehler explizit behandelt werden.
    • Wird fetchApiV2Legacy verwendet, erscheint im Fehlerfall ein Standard-Browser-Alert.

Helm Charts

Die Helm Charts für das Deployment der Applikation befinden sich im Ordner charts/. Weitere Informationen zur Installation und Konfiguration finden sich in den jeweiligen Chart READMEs:


  1. Authentifizierung via Authorization Header mit Bearer-Token (identity_token) von OIDC Server. Login-Konfigurationen können in config/oidc-mock-users.json getätigt werden. ↩︎