Skip to content

Commit 5bfaa69

Browse files
authored
Feature/database (#8)
1 parent 97e5ee7 commit 5bfaa69

30 files changed

Lines changed: 1162 additions & 45 deletions

File tree

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ dependency-reduced-pom.xml
5858
*.swp
5959
*.bak
6060
*.tmp
61+
62+
# Persistence module — local database credentials (never commit real passwords)
63+
persistence/liquibase.properties
64+
persistence/.env
65+
66+
# Legacy: Database module references (migrated to persistence/)
67+
database/liquibase.properties
68+
database/.env
6169
*.orig
6270
*.rej
6371

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
#### Health Monitoring & Observability
2323
- **Spring Boot Actuator** health indicators for all external services:
2424

25+
#### Persistance to keep project lifecycle
26+
2527
### Changed
2628
- Updated all external service implementations to extend `ExternalService` interface
2729
- Use of lombok.extern.slf4j.Slf4j to remove boilerplate code.
@@ -32,7 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3234
- Updated Spring Boot version
3335
- Added health indicator dependencies across external service modules
3436

35-
## [0.0.2] - 2026-03-03
37+
## [0.0.3] - 2026-03-03
3638

3739
### Changed
3840
##### Projects Info Service

Makefile

Lines changed: 142 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# Supports building Spring Boot JAR and Native applications
33

44
# Project variables
5-
PROJECT_NAME := devstack-api-service
6-
VERSION := 0.0.2
5+
PROJECT_NAME := opendevstack-api-service
6+
VERSION := 0.0.3
77
JAVA_VERSION := 21
88
MAIN_CLASS := org.opendevstack.apiservice.core.DevstackApiServiceApplication
99

@@ -44,7 +44,8 @@ YELLOW := \033[1;33m
4444
BLUE := \033[0;34m
4545
NC := \033[0m # No Color
4646

47-
.PHONY: help clean compile test package jar native docker docker-native run-jar run-native run-docker run-docker-native install verify lint format check-java check-maven check-config
47+
.PHONY: help clean compile test package jar native docker docker-native run-jar run-native run-docker run-docker-native install verify lint format check-java check-maven check-config \
48+
db-check-env db-validate db-status db-migrate db-rollback db-tag db-port-forward db-docker-build-db
4849

4950
# Default target
5051
.DEFAULT_GOAL := help
@@ -270,6 +271,144 @@ all: jar docker
270271
## Quick start for development
271272
quick-start: jar run-jar
272273

274+
# =============================================================================
275+
# Database targets (Liquibase / PostgreSQL)
276+
#
277+
# Required environment variables (export them or source persistence/.env):
278+
# ODS_API_SERVICE_DB_HOST PostgreSQL hostname or IP
279+
# ODS_API_SERVICE_DB_PORT PostgreSQL port (default: 5432)
280+
# ODS_API_SERVICE_DB_NAME Database name (ods_api_service)
281+
# ODS_API_SERVICE_DB_USER Application user (ods_api_service)
282+
# ODS_API_SERVICE_DB_PASSWORD Application user password
283+
#
284+
# Quick start:
285+
# cp persistence/liquibase.properties.example persistence/.env
286+
# # edit persistence/.env with real values
287+
# source persistence/.env && make db-migrate
288+
#
289+
# Port-forward variables (can be overridden on the command line):
290+
# NAMESPACE Kubernetes/OpenShift namespace where PostgreSQL runs (REQUIRED)
291+
# DB_K8S_SERVICE Name of the PostgreSQL Service in the cluster (default: ods-api-service-postgresql)
292+
# DB_PF_LOCAL_PORT Local port to bind on the developer machine (default: 5432)
293+
# DB_PF_REMOTE_PORT PostgreSQL port exposed by the Service in-cluster (default: 5432)
294+
#
295+
# Example:
296+
# make db-port-forward NAMESPACE=ods-dev
297+
# make db-port-forward NAMESPACE=ods-prod DB_K8S_SERVICE=postgresql DB_PF_LOCAL_PORT=15432
298+
# =============================================================================
299+
300+
# Build the JDBC URL from individual host/port/name parts.
301+
# ODS_API_SERVICE_DB_PORT defaults to 5432 when not set.
302+
DB_PORT ?= $(or $(ODS_API_SERVICE_DB_PORT),5432)
303+
DB_JDBC_URL = jdbc:postgresql://$(ODS_API_SERVICE_DB_HOST):$(DB_PORT)/$(ODS_API_SERVICE_DB_NAME)
304+
305+
# Kubernetes port-forward defaults (all overridable on the command line)
306+
DB_K8S_SERVICE ?= ods-api-service-postgresql
307+
DB_PF_LOCAL_PORT ?= 5432
308+
DB_PF_REMOTE_PORT ?= 5432
309+
310+
DB_MAVEN_ARGS = -pl persistence \
311+
-Dliquibase.url=$(DB_JDBC_URL) \
312+
-Dliquibase.username=$(ODS_API_SERVICE_DB_USER) \
313+
-Dliquibase.password=$(ODS_API_SERVICE_DB_PASSWORD)
314+
315+
## [DB] Verify required DB environment variables are set
316+
db-check-env:
317+
@missing=; \
318+
for var in ODS_API_SERVICE_DB_HOST ODS_API_SERVICE_DB_NAME ODS_API_SERVICE_DB_USER ODS_API_SERVICE_DB_PASSWORD; do \
319+
if [ -z "$$(eval echo \$$$$var)" ]; then missing="$$missing $$var"; fi; \
320+
done; \
321+
if [ -n "$$missing" ]; then \
322+
echo "$(RED)Error: the following required environment variables are not set:$(NC)"; \
323+
for v in $$missing; do echo " $$v"; done; \
324+
echo ""; \
325+
echo "$(YELLOW)Hint: copy persistence/liquibase.properties.example to persistence/.env,"; \
326+
echo " fill in the values, then run: source persistence/.env$(NC)"; \
327+
exit 1; \
328+
fi
329+
@echo "$(GREEN)✓ DB environment variables OK$(NC)"
330+
331+
## [DB] Validate the Liquibase changelog syntax (no DB connection required)
332+
db-validate: check-maven
333+
@echo "$(BLUE)Validating Liquibase changelog...$(NC)"
334+
$(MAVEN_WRAPPER) -pl persistence liquibase:validate
335+
@echo "$(GREEN)✓ Changelog validation complete$(NC)"
336+
337+
## [DB] Show pending changesets that have not yet been applied
338+
db-status: db-check-env check-maven
339+
@echo "$(BLUE)Checking pending Liquibase changesets...$(NC)"
340+
@echo "$(YELLOW)Target: $(DB_JDBC_URL)$(NC)"
341+
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:status
342+
343+
## [DB] Apply all pending changesets to the database
344+
db-migrate: db-check-env check-maven
345+
@echo "$(BLUE)Running Liquibase migrations...$(NC)"
346+
@echo "$(YELLOW)Target: $(DB_JDBC_URL)$(NC)"
347+
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:update
348+
@echo "$(GREEN)✓ Migrations applied$(NC)"
349+
350+
## [DB] Roll back the last applied changeset (usage: make db-rollback)
351+
db-rollback: db-check-env check-maven
352+
@echo "$(YELLOW)Rolling back last changeset on: $(DB_JDBC_URL)$(NC)"
353+
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:rollback -Dliquibase.rollbackCount=1
354+
@echo "$(GREEN)✓ Rollback complete$(NC)"
355+
356+
## [DB] Tag the current database state (usage: make db-tag TAG=v1.0.0)
357+
db-tag: db-check-env check-maven
358+
@if [ -z "$(TAG)" ]; then \
359+
echo "$(RED)Error: TAG is required. Usage: make db-tag TAG=v1.0.0$(NC)"; \
360+
exit 1; \
361+
fi
362+
@echo "$(BLUE)Tagging database state as '$(TAG)'...$(NC)"
363+
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:tag -Dliquibase.tag=$(TAG)
364+
@echo "$(GREEN)✓ Database tagged as '$(TAG)'$(NC)"
365+
366+
## [DB] Port-forward the cluster PostgreSQL Service to localhost (usage: make db-port-forward NAMESPACE=<ns>)
367+
db-port-forward:
368+
@if [ -z "$(NAMESPACE)" ]; then \
369+
echo "$(RED)Error: NAMESPACE is required.$(NC)"; \
370+
echo "$(YELLOW)Usage: make db-port-forward NAMESPACE=<namespace>$(NC)"; \
371+
echo "$(YELLOW)Optionally override DB_K8S_SERVICE (default: $(DB_K8S_SERVICE)),$(NC)"; \
372+
echo "$(YELLOW) DB_PF_LOCAL_PORT (default: $(DB_PF_LOCAL_PORT)) or DB_PF_REMOTE_PORT (default: $(DB_PF_REMOTE_PORT)).$(NC)"; \
373+
exit 1; \
374+
fi
375+
@if ! command -v kubectl >/dev/null 2>&1; then \
376+
echo "$(RED)Error: kubectl not found in PATH$(NC)"; \
377+
exit 1; \
378+
fi
379+
@echo "$(BLUE)Port-forwarding PostgreSQL service...$(NC)"
380+
@echo "$(YELLOW) Namespace : $(NAMESPACE)$(NC)"
381+
@echo "$(YELLOW) Service : $(DB_K8S_SERVICE)$(NC)"
382+
@echo "$(YELLOW) Mapping : localhost:$(DB_PF_LOCAL_PORT)$(DB_K8S_SERVICE):$(DB_PF_REMOTE_PORT)$(NC)"
383+
@echo ""
384+
@echo "$(YELLOW)Once forwarding is active, connect with:$(NC)"
385+
@echo " psql -h localhost -p $(DB_PF_LOCAL_PORT) -U \$$ODS_API_SERVICE_DB_USER \$$ODS_API_SERVICE_DB_NAME"
386+
@echo " # or run migrations against the forwarded port:"
387+
@echo " ODS_API_SERVICE_DB_HOST=localhost ODS_API_SERVICE_DB_PORT=$(DB_PF_LOCAL_PORT) make db-migrate"
388+
@echo ""
389+
@echo "$(YELLOW)Press Ctrl+C to stop the tunnel$(NC)"
390+
kubectl port-forward \
391+
--namespace $(NAMESPACE) \
392+
service/$(DB_K8S_SERVICE) \
393+
$(DB_PF_LOCAL_PORT):$(DB_PF_REMOTE_PORT)
394+
395+
db-docker-build-db:
396+
@echo "$(BLUE)Building Docker image for database...$(NC)"
397+
@docker build --file ../ods-core/ods-api-service/docker/Dockerfile.database --tag $(PROJECT_NAME)-db:18 ../ods-core/ods-api-service/docker/
398+
@echo "$(GREEN)✓ Database Docker image built: $(PROJECT_NAME)-db:$(DOCKER_TAG)$(NC)"
399+
400+
db-docker-run-db: db-docker-build-db
401+
@echo "$(BLUE)Running PostgreSQL database in Docker...$(NC)"
402+
@echo "$(YELLOW)Access the database at: localhost:5432$(NC)"
403+
@echo "$(YELLOW)PostgreSQL credentials: user=ods_api_service, db=ods_api_service$(NC)"
404+
@echo "$(YELLOW)Press Ctrl+C to stop$(NC)"
405+
docker run -p 5432:5432 \
406+
-e POSTGRES_USER=ods_api_service \
407+
-e POSTGRES_PASSWORD=ods_api_service \
408+
-e POSTGRES_DB=ods_api_service \
409+
$(PROJECT_NAME)-db:18
410+
411+
273412
## Clean everything including Docker images
274413
clean-all: clean
275414
@echo "$(BLUE)Cleaning Docker images...$(NC)"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The system will expose RESTful APIs for third-party client applications and futu
1919
Before using the Makefile, ensure you have the following installed:
2020

2121
### Required
22-
- **Java 17+** - The project uses Java 21
22+
- **Java 21+** - The project uses Java 21
2323
- **Maven** - Maven wrapper (`mvnw`) is included in the project
2424
- **Make** - For running Makefile commands
2525

@@ -54,7 +54,7 @@ Build a traditional Spring Boot JAR file:
5454
```bash
5555
make jar
5656
```
57-
- Output: `core/target/core-0.0.2-SNAPSHOT.jar`
57+
- Output: `core/target/core-0.0.3.jar`
5858
- Includes all dependencies
5959
- Standard Spring Boot startup time
6060

api-project-platform/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>org.opendevstack.apiservice</groupId>
88
<artifactId>devstack-api-service</artifactId>
9-
<version>0.0.2</version>
9+
<version>0.0.3</version>
1010
</parent>
1111

1212
<artifactId>api-project-platform</artifactId>

api-project-users/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>org.opendevstack.apiservice</groupId>
88
<artifactId>devstack-api-service</artifactId>
9-
<version>0.0.2</version>
9+
<version>0.0.3</version>
1010
</parent>
1111

1212
<artifactId>api-project-users</artifactId>

application.yaml

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,43 @@ logging:
33
org.springframework: INFO
44
org.springframework.security: TRACE
55
org.opendevstack.apiservice.externalservice: DEBUG
6-
6+
7+
# ──────────────────────────────────────────────────────────────────────────────
8+
# Persistence — PostgreSQL datasource + JPA / Hibernate
9+
#
10+
# Schema is managed externally via Liquibase (database module / Makefile).
11+
# Hibernate is set to `validate` so it only checks that entities match the
12+
# existing schema at boot — it never creates or alters tables.
13+
#
14+
# Required env vars (no defaults — must be explicitly set per environment):
15+
# DB_HOST, DB_PORT, DB_NAME, DB_USERNAME, DB_PASSWORD
16+
# ──────────────────────────────────────────────────────────────────────────────
17+
spring:
18+
datasource:
19+
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:devstack}
20+
username: ${DB_USERNAME:devstack}
21+
password: ${DB_PASSWORD:devstack}
22+
driver-class-name: org.postgresql.Driver
23+
hikari:
24+
# Pool sizing — tune per environment
25+
maximum-pool-size: ${DB_POOL_MAX_SIZE:10}
26+
minimum-idle: ${DB_POOL_MIN_IDLE:2}
27+
connection-timeout: 30000
28+
idle-timeout: 600000
29+
max-lifetime: 1800000
30+
jpa:
31+
hibernate:
32+
# NEVER auto-create/alter — Liquibase owns the schema
33+
ddl-auto: validate
34+
properties:
35+
hibernate:
36+
dialect: org.hibernate.dialect.PostgreSQLDialect
37+
# Log slow queries (> 500 ms) via Hibernate statistics
38+
generate_statistics: false
39+
# Avoid lazy-loading pitfalls: keep Session scoped to Service, not Request
40+
open-in-view: false
41+
show-sql: false
42+
743
management:
844
endpoints:
945
web:
@@ -44,7 +80,7 @@ openapi:
4480
otel:
4581
service:
4682
name: devstack-api-service-dev
47-
version: 0.0.2
83+
version: 0.0.3
4884
exporter:
4985
otlp:
5086
endpoint: http://opentelemetry.example.com
@@ -55,7 +91,7 @@ otel:
5591
metrics:
5692
exporter: none
5793
resource:
58-
attributes: service.name=devstack-api-service,service.version=0.0.2,deployment.environment=development
94+
attributes: service.name=devstack-api-service,service.version=0.0.3,deployment.environment=development
5995
instrumentation:
6096
jdbc:
6197
enabled: false

core/pom.xml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>org.opendevstack.apiservice</groupId>
88
<artifactId>devstack-api-service</artifactId>
9-
<version>0.0.2</version>
9+
<version>0.0.3</version>
1010
</parent>
1111

1212
<artifactId>core</artifactId>
@@ -113,6 +113,20 @@
113113
<version>${project.version}</version>
114114
</dependency>
115115

116+
<!-- Persistence module: JPA entities and Spring Data repositories -->
117+
<dependency>
118+
<groupId>org.opendevstack.apiservice</groupId>
119+
<artifactId>persistence</artifactId>
120+
<version>${project.version}</version>
121+
</dependency>
122+
123+
<!-- PostgreSQL JDBC driver (runtime) -->
124+
<dependency>
125+
<groupId>org.postgresql</groupId>
126+
<artifactId>postgresql</artifactId>
127+
<scope>runtime</scope>
128+
</dependency>
129+
116130
<!-- OpenTelemetry for observability -->
117131
<dependency>
118132
<groupId>io.opentelemetry.instrumentation</groupId>

core/src/test/java/org/opendevstack/apiservice/core/DevstackApiServiceApplicationTest.java

Lines changed: 0 additions & 20 deletions
This file was deleted.

external-service-aap/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>org.opendevstack.apiservice</groupId>
88
<artifactId>devstack-api-service</artifactId>
9-
<version>0.0.2</version>
9+
<version>0.0.3</version>
1010
</parent>
1111

1212
<artifactId>external-service-aap</artifactId>

0 commit comments

Comments
 (0)