Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ dependency-reduced-pom.xml
*.swp
*.bak
*.tmp

# Persistence module — local database credentials (never commit real passwords)
persistence/liquibase.properties
persistence/.env

# Legacy: Database module references (migrated to persistence/)
database/liquibase.properties
database/.env
*.orig
*.rej

Expand Down
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
#### Health Monitoring & Observability
- **Spring Boot Actuator** health indicators for all external services:

#### Persistance to keep project lifecycle

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

## [0.0.2] - 2026-03-03
## [0.0.3] - 2026-03-03

### Changed
##### Projects Info Service
Expand Down
145 changes: 142 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# Supports building Spring Boot JAR and Native applications

# Project variables
PROJECT_NAME := devstack-api-service
VERSION := 0.0.2
PROJECT_NAME := opendevstack-api-service
VERSION := 0.0.3
JAVA_VERSION := 21
MAIN_CLASS := org.opendevstack.apiservice.core.DevstackApiServiceApplication

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

.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
.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 \
db-check-env db-validate db-status db-migrate db-rollback db-tag db-port-forward db-docker-build-db

# Default target
.DEFAULT_GOAL := help
Expand Down Expand Up @@ -270,6 +271,144 @@ all: jar docker
## Quick start for development
quick-start: jar run-jar

# =============================================================================
# Database targets (Liquibase / PostgreSQL)
#
# Required environment variables (export them or source persistence/.env):
# ODS_API_SERVICE_DB_HOST PostgreSQL hostname or IP
# ODS_API_SERVICE_DB_PORT PostgreSQL port (default: 5432)
# ODS_API_SERVICE_DB_NAME Database name (ods_api_service)
# ODS_API_SERVICE_DB_USER Application user (ods_api_service)
# ODS_API_SERVICE_DB_PASSWORD Application user password
#
# Quick start:
# cp persistence/liquibase.properties.example persistence/.env
# # edit persistence/.env with real values
# source persistence/.env && make db-migrate
#
# Port-forward variables (can be overridden on the command line):
# NAMESPACE Kubernetes/OpenShift namespace where PostgreSQL runs (REQUIRED)
# DB_K8S_SERVICE Name of the PostgreSQL Service in the cluster (default: ods-api-service-postgresql)
# DB_PF_LOCAL_PORT Local port to bind on the developer machine (default: 5432)
# DB_PF_REMOTE_PORT PostgreSQL port exposed by the Service in-cluster (default: 5432)
#
# Example:
# make db-port-forward NAMESPACE=ods-dev
# make db-port-forward NAMESPACE=ods-prod DB_K8S_SERVICE=postgresql DB_PF_LOCAL_PORT=15432
# =============================================================================

# Build the JDBC URL from individual host/port/name parts.
# ODS_API_SERVICE_DB_PORT defaults to 5432 when not set.
DB_PORT ?= $(or $(ODS_API_SERVICE_DB_PORT),5432)
DB_JDBC_URL = jdbc:postgresql://$(ODS_API_SERVICE_DB_HOST):$(DB_PORT)/$(ODS_API_SERVICE_DB_NAME)

# Kubernetes port-forward defaults (all overridable on the command line)
DB_K8S_SERVICE ?= ods-api-service-postgresql
DB_PF_LOCAL_PORT ?= 5432
DB_PF_REMOTE_PORT ?= 5432

DB_MAVEN_ARGS = -pl persistence \
-Dliquibase.url=$(DB_JDBC_URL) \
-Dliquibase.username=$(ODS_API_SERVICE_DB_USER) \
-Dliquibase.password=$(ODS_API_SERVICE_DB_PASSWORD)

## [DB] Verify required DB environment variables are set
db-check-env:
@missing=; \
for var in ODS_API_SERVICE_DB_HOST ODS_API_SERVICE_DB_NAME ODS_API_SERVICE_DB_USER ODS_API_SERVICE_DB_PASSWORD; do \
if [ -z "$$(eval echo \$$$$var)" ]; then missing="$$missing $$var"; fi; \
done; \
if [ -n "$$missing" ]; then \
echo "$(RED)Error: the following required environment variables are not set:$(NC)"; \
for v in $$missing; do echo " $$v"; done; \
echo ""; \
echo "$(YELLOW)Hint: copy persistence/liquibase.properties.example to persistence/.env,"; \
echo " fill in the values, then run: source persistence/.env$(NC)"; \
exit 1; \
fi
@echo "$(GREEN)✓ DB environment variables OK$(NC)"

## [DB] Validate the Liquibase changelog syntax (no DB connection required)
db-validate: check-maven
@echo "$(BLUE)Validating Liquibase changelog...$(NC)"
$(MAVEN_WRAPPER) -pl persistence liquibase:validate
@echo "$(GREEN)✓ Changelog validation complete$(NC)"

## [DB] Show pending changesets that have not yet been applied
db-status: db-check-env check-maven
@echo "$(BLUE)Checking pending Liquibase changesets...$(NC)"
@echo "$(YELLOW)Target: $(DB_JDBC_URL)$(NC)"
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:status

## [DB] Apply all pending changesets to the database
db-migrate: db-check-env check-maven
@echo "$(BLUE)Running Liquibase migrations...$(NC)"
@echo "$(YELLOW)Target: $(DB_JDBC_URL)$(NC)"
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:update
@echo "$(GREEN)✓ Migrations applied$(NC)"

## [DB] Roll back the last applied changeset (usage: make db-rollback)
db-rollback: db-check-env check-maven
@echo "$(YELLOW)Rolling back last changeset on: $(DB_JDBC_URL)$(NC)"
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:rollback -Dliquibase.rollbackCount=1
@echo "$(GREEN)✓ Rollback complete$(NC)"

## [DB] Tag the current database state (usage: make db-tag TAG=v1.0.0)
db-tag: db-check-env check-maven
@if [ -z "$(TAG)" ]; then \
echo "$(RED)Error: TAG is required. Usage: make db-tag TAG=v1.0.0$(NC)"; \
exit 1; \
fi
@echo "$(BLUE)Tagging database state as '$(TAG)'...$(NC)"
$(MAVEN_WRAPPER) $(DB_MAVEN_ARGS) liquibase:tag -Dliquibase.tag=$(TAG)
@echo "$(GREEN)✓ Database tagged as '$(TAG)'$(NC)"

## [DB] Port-forward the cluster PostgreSQL Service to localhost (usage: make db-port-forward NAMESPACE=<ns>)
db-port-forward:
@if [ -z "$(NAMESPACE)" ]; then \
echo "$(RED)Error: NAMESPACE is required.$(NC)"; \
echo "$(YELLOW)Usage: make db-port-forward NAMESPACE=<namespace>$(NC)"; \
echo "$(YELLOW)Optionally override DB_K8S_SERVICE (default: $(DB_K8S_SERVICE)),$(NC)"; \
echo "$(YELLOW) DB_PF_LOCAL_PORT (default: $(DB_PF_LOCAL_PORT)) or DB_PF_REMOTE_PORT (default: $(DB_PF_REMOTE_PORT)).$(NC)"; \
exit 1; \
fi
@if ! command -v kubectl >/dev/null 2>&1; then \
echo "$(RED)Error: kubectl not found in PATH$(NC)"; \
exit 1; \
fi
@echo "$(BLUE)Port-forwarding PostgreSQL service...$(NC)"
@echo "$(YELLOW) Namespace : $(NAMESPACE)$(NC)"
@echo "$(YELLOW) Service : $(DB_K8S_SERVICE)$(NC)"
@echo "$(YELLOW) Mapping : localhost:$(DB_PF_LOCAL_PORT) → $(DB_K8S_SERVICE):$(DB_PF_REMOTE_PORT)$(NC)"
@echo ""
@echo "$(YELLOW)Once forwarding is active, connect with:$(NC)"
@echo " psql -h localhost -p $(DB_PF_LOCAL_PORT) -U \$$ODS_API_SERVICE_DB_USER \$$ODS_API_SERVICE_DB_NAME"
@echo " # or run migrations against the forwarded port:"
@echo " ODS_API_SERVICE_DB_HOST=localhost ODS_API_SERVICE_DB_PORT=$(DB_PF_LOCAL_PORT) make db-migrate"
@echo ""
@echo "$(YELLOW)Press Ctrl+C to stop the tunnel$(NC)"
kubectl port-forward \
--namespace $(NAMESPACE) \
service/$(DB_K8S_SERVICE) \
$(DB_PF_LOCAL_PORT):$(DB_PF_REMOTE_PORT)

db-docker-build-db:
@echo "$(BLUE)Building Docker image for database...$(NC)"
@docker build --file ../ods-core/ods-api-service/docker/Dockerfile.database --tag $(PROJECT_NAME)-db:18 ../ods-core/ods-api-service/docker/
@echo "$(GREEN)✓ Database Docker image built: $(PROJECT_NAME)-db:$(DOCKER_TAG)$(NC)"

db-docker-run-db: db-docker-build-db
@echo "$(BLUE)Running PostgreSQL database in Docker...$(NC)"
@echo "$(YELLOW)Access the database at: localhost:5432$(NC)"
@echo "$(YELLOW)PostgreSQL credentials: user=ods_api_service, db=ods_api_service$(NC)"
@echo "$(YELLOW)Press Ctrl+C to stop$(NC)"
docker run -p 5432:5432 \
-e POSTGRES_USER=ods_api_service \
-e POSTGRES_PASSWORD=ods_api_service \
-e POSTGRES_DB=ods_api_service \
$(PROJECT_NAME)-db:18


## Clean everything including Docker images
clean-all: clean
@echo "$(BLUE)Cleaning Docker images...$(NC)"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The system will expose RESTful APIs for third-party client applications and futu
Before using the Makefile, ensure you have the following installed:

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

Expand Down Expand Up @@ -54,7 +54,7 @@ Build a traditional Spring Boot JAR file:
```bash
make jar
```
- Output: `core/target/core-0.0.2-SNAPSHOT.jar`
- Output: `core/target/core-0.0.3.jar`
- Includes all dependencies
- Standard Spring Boot startup time

Expand Down
2 changes: 1 addition & 1 deletion api-project-platform/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>api-project-platform</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion api-project-users/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>api-project-users</artifactId>
Expand Down
42 changes: 39 additions & 3 deletions application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,43 @@ logging:
org.springframework: INFO
org.springframework.security: TRACE
org.opendevstack.apiservice.externalservice: DEBUG


# ──────────────────────────────────────────────────────────────────────────────
# Persistence — PostgreSQL datasource + JPA / Hibernate
#
# Schema is managed externally via Liquibase (database module / Makefile).
# Hibernate is set to `validate` so it only checks that entities match the
# existing schema at boot — it never creates or alters tables.
#
# Required env vars (no defaults — must be explicitly set per environment):
# DB_HOST, DB_PORT, DB_NAME, DB_USERNAME, DB_PASSWORD
# ──────────────────────────────────────────────────────────────────────────────
spring:
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:devstack}
username: ${DB_USERNAME:devstack}
password: ${DB_PASSWORD:devstack}
driver-class-name: org.postgresql.Driver
hikari:
# Pool sizing — tune per environment
maximum-pool-size: ${DB_POOL_MAX_SIZE:10}
minimum-idle: ${DB_POOL_MIN_IDLE:2}
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
jpa:
hibernate:
# NEVER auto-create/alter — Liquibase owns the schema
ddl-auto: validate
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
# Log slow queries (> 500 ms) via Hibernate statistics
generate_statistics: false
# Avoid lazy-loading pitfalls: keep Session scoped to Service, not Request
open-in-view: false
show-sql: false

management:
endpoints:
web:
Expand Down Expand Up @@ -44,7 +80,7 @@ openapi:
otel:
service:
name: devstack-api-service-dev
version: 0.0.2
version: 0.0.3
exporter:
otlp:
endpoint: http://opentelemetry.example.com
Expand All @@ -55,7 +91,7 @@ otel:
metrics:
exporter: none
resource:
attributes: service.name=devstack-api-service,service.version=0.0.2,deployment.environment=development
attributes: service.name=devstack-api-service,service.version=0.0.3,deployment.environment=development
instrumentation:
jdbc:
enabled: false
Expand Down
16 changes: 15 additions & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>core</artifactId>
Expand Down Expand Up @@ -113,6 +113,20 @@
<version>${project.version}</version>
</dependency>

<!-- Persistence module: JPA entities and Spring Data repositories -->
<dependency>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>persistence</artifactId>
<version>${project.version}</version>
</dependency>

<!-- PostgreSQL JDBC driver (runtime) -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<!-- OpenTelemetry for observability -->
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion external-service-aap/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>external-service-aap</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion external-service-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2-SNAPSHOT</version>
<version>0.0.3</version>
</parent>

<artifactId>external-service-api</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion external-service-bitbucket/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>external-service-bitbucket</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion external-service-jira/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2-SNAPSHOT</version>
<version>0.0.3</version>
</parent>

<artifactId>external-service-jira</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion external-service-ocp/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>org.opendevstack.apiservice</groupId>
<artifactId>devstack-api-service</artifactId>
<version>0.0.2</version>
<version>0.0.3</version>
</parent>

<artifactId>external-service-ocp</artifactId>
Expand Down
Loading
Loading