From df52b9046b341dff9a78ce280d53d82b00658690 Mon Sep 17 00:00:00 2001 From: John Melati Date: Tue, 14 Jan 2025 15:55:12 +0100 Subject: [PATCH 01/16] implement db singleton pattern --- modules/logger/build.gradle.kts | 2 - .../com/sphereon/oid/fed/logger/Logger.kt | 8 ++-- .../database/PlatformSqlDriver.jvm.kt | 37 +++++++++++++++---- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/modules/logger/build.gradle.kts b/modules/logger/build.gradle.kts index 16b4281b..ca6d7e9b 100644 --- a/modules/logger/build.gradle.kts +++ b/modules/logger/build.gradle.kts @@ -1,6 +1,5 @@ plugins { alias(libs.plugins.kotlinMultiplatform) - kotlin("plugin.serialization") version "2.1.0" } group = "com.sphereon.oid.fed.logger" @@ -22,7 +21,6 @@ kotlin { dependencies { implementation(libs.kermit.logging) implementation(libs.kotlinx.datetime) - implementation(libs.kotlinx.serialization.core) } } diff --git a/modules/logger/src/commonMain/kotlin/com/sphereon/oid/fed/logger/Logger.kt b/modules/logger/src/commonMain/kotlin/com/sphereon/oid/fed/logger/Logger.kt index 6581ecf1..eaa031f1 100644 --- a/modules/logger/src/commonMain/kotlin/com/sphereon/oid/fed/logger/Logger.kt +++ b/modules/logger/src/commonMain/kotlin/com/sphereon/oid/fed/logger/Logger.kt @@ -51,10 +51,10 @@ class Logger internal constructor(private val tag: String = "") { append("[$tag] ") } append(message) - if (!metadata.isEmpty()) { - append("\nContext: ") - metadata.entries.forEach { (key, value) -> - append("\n $key: ${value}") + if (metadata.isNotEmpty()) { + append("\nContext:") + metadata.forEach { (key, value) -> + append("\n $key: $value") } } throwable?.let { t -> diff --git a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt index 3825a035..e97b7a71 100644 --- a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt +++ b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt @@ -5,19 +5,40 @@ import app.cash.sqldelight.driver.jdbc.asJdbcDriver import com.sphereon.oid.fed.common.Constants import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource +import java.util.concurrent.atomic.AtomicReference actual class PlatformSqlDriver { - actual fun createPostgresDriver(url: String, username: String, password: String): SqlDriver { - val config = HikariConfig() - config.jdbcUrl = url - config.username = username - config.password = password + companion object { + private val dataSourceRef = AtomicReference(null) + + private fun createDataSource(url: String, username: String, password: String): HikariDataSource { + val config = HikariConfig() + config.jdbcUrl = url + config.username = username + config.password = password + config.maximumPoolSize = 20 + config.minimumIdle = 20 + config.connectionTimeout = 30000 + config.idleTimeout = 600000 + config.maxLifetime = 1800000 + + config.addDataSourceProperty("cachePrepStmts", "true") + config.addDataSourceProperty("prepStmtCacheSize", "250") + config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048") + config.addDataSourceProperty("useServerPrepStmts", "true") + config.poolName = "HikariPool-OpenID-Federation" - val dataSource = HikariDataSource(config) - return dataSource.asJdbcDriver() + return HikariDataSource(config) + } + } + + actual fun createPostgresDriver(url: String, username: String, password: String): SqlDriver { + return dataSourceRef.updateAndGet { current -> + current ?: createDataSource(url, username, password) + }!!.asJdbcDriver() } actual fun createSqliteDriver(path: String): SqlDriver { throw UnsupportedOperationException(Constants.SQLITE_IS_NOT_SUPPORTED_IN_JVM) } -} +} \ No newline at end of file From 25cfc8c12faa7909cb7cfa7a9b077d6676495d2a Mon Sep 17 00:00:00 2001 From: John Melati Date: Tue, 14 Jan 2025 16:57:50 +0100 Subject: [PATCH 02/16] fix: remove db initialization from the springboot servers --- .../server/admin/config/MonitoringConfig.kt | 41 ++++++++++++------- .../src/main/resources/application.properties | 8 ++-- .../src/main/resources/application.properties | 4 -- .../database/PlatformSqlDriver.jvm.kt | 22 +++++++++- 4 files changed, 50 insertions(+), 25 deletions(-) diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/config/MonitoringConfig.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/config/MonitoringConfig.kt index 47c917c0..7ae7ff04 100644 --- a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/config/MonitoringConfig.kt +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/config/MonitoringConfig.kt @@ -2,6 +2,7 @@ package com.sphereon.oid.fed.server.admin.config import com.sphereon.oid.fed.logger.Logger import com.sphereon.oid.fed.logger.Logger.Severity +import com.sphereon.oid.fed.persistence.database.PlatformSqlDriver import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Configuration import org.springframework.scheduling.annotation.Scheduled @@ -34,29 +35,41 @@ class MonitoringConfig { val severity = if (memoryUsagePercent >= memoryWarningThresholdPercent) Severity.Warn else Severity.Info + val dbMetrics = PlatformSqlDriver.Companion.getConnectionMetrics() + val message = buildString { append("System Health: ") append("Uptime=${uptime.toHours()}h${uptime.toMinutesPart()}m, ") append("Memory=${usedMemory / 1024 / 1024}MB/${totalMemory / 1024 / 1024}MB($memoryUsagePercent%), ") append("Processors=${runtime.availableProcessors()}, ") append("Heap=${memoryMBean.heapMemoryUsage.used / 1024 / 1024}MB, ") - append("Threads=${threadMBean.threadCount}(Peak:${threadMBean.peakThreadCount}, Daemon:${threadMBean.daemonThreadCount})") + append("Threads=${threadMBean.threadCount}(Peak:${threadMBean.peakThreadCount}, Daemon:${threadMBean.daemonThreadCount}), ") + append("DB Connections: Active=${dbMetrics["Active Connections"] ?: "N/A"}, ") + append("Idle=${dbMetrics["Idle Connections"] ?: "N/A"}, ") + append("Total=${dbMetrics["Total Connections"] ?: "N/A"}") + } + + val contextMap = mutableMapOf( + "uptime_hours" to uptime.toHours().toString(), + "uptime_minutes" to uptime.toMinutesPart().toString(), + "memory_used_mb" to (usedMemory / 1024 / 1024).toString(), + "memory_total_mb" to (totalMemory / 1024 / 1024).toString(), + "memory_usage_percent" to memoryUsagePercent.toString(), + "processors" to runtime.availableProcessors().toString(), + "heap_used_mb" to (memoryMBean.heapMemoryUsage.used / 1024 / 1024).toString(), + "thread_count" to threadMBean.threadCount.toString(), + "thread_peak" to threadMBean.peakThreadCount.toString(), + "thread_daemon" to threadMBean.daemonThreadCount.toString() + ) + + // Add DB metrics to context + dbMetrics.forEach { (key, value) -> + contextMap["db_${key.lowercase().replace(' ', '_')}"] = value.toString() } logger.info( message = message, - context = mapOf( - "uptime_hours" to uptime.toHours().toString(), - "uptime_minutes" to uptime.toMinutesPart().toString(), - "memory_used_mb" to (usedMemory / 1024 / 1024).toString(), - "memory_total_mb" to (totalMemory / 1024 / 1024).toString(), - "memory_usage_percent" to memoryUsagePercent.toString(), - "processors" to runtime.availableProcessors().toString(), - "heap_used_mb" to (memoryMBean.heapMemoryUsage.used / 1024 / 1024).toString(), - "thread_count" to threadMBean.threadCount.toString(), - "thread_peak" to threadMBean.peakThreadCount.toString(), - "thread_daemon" to threadMBean.daemonThreadCount.toString() - ) + context = contextMap ) if (severity == Severity.Warn) { @@ -78,4 +91,4 @@ class MonitoringConfig { } } } -} +} \ No newline at end of file diff --git a/modules/admin-server/src/main/resources/application.properties b/modules/admin-server/src/main/resources/application.properties index 8824e118..31699055 100644 --- a/modules/admin-server/src/main/resources/application.properties +++ b/modules/admin-server/src/main/resources/application.properties @@ -2,10 +2,8 @@ spring.config.import=optional:file:../../.env[.properties] spring.application.name=OpenID Federation Admin Server # Development Mode Configuration app.dev-mode=${DEV_MODE:false} -spring.datasource.url=${DATASOURCE_URL} -spring.datasource.username=${DATASOURCE_USER} -spring.datasource.password=${DATASOURCE_PASSWORD} -spring.datasource.driver-class-name=org.postgresql.Driver +# Disable Spring Boot's auto-configuration of DataSource +spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration # Mapping /actuator/health to /status management.endpoints.web.base-path=/ management.endpoints.web.path-mapping.health=status @@ -16,4 +14,4 @@ monitoring.load.warning-threshold=0.8 monitoring.health.interval=60000 monitoring.load.interval=300000 # Federation Configuration -sphereon.federation.root-identifier=${ROOT_IDENTIFIER:http://localhost:8080} +sphereon.federation.root-identifier=${ROOT_IDENTIFIER:http://localhost:8080} \ No newline at end of file diff --git a/modules/federation-server/src/main/resources/application.properties b/modules/federation-server/src/main/resources/application.properties index 4bf9cbc5..2c49eeee 100644 --- a/modules/federation-server/src/main/resources/application.properties +++ b/modules/federation-server/src/main/resources/application.properties @@ -1,9 +1,5 @@ spring.config.import=optional:file:../../.env[.properties] spring.application.name=OpenID Federation Server -spring.datasource.url=${DATASOURCE_URL} -spring.datasource.username=${DATASOURCE_USER} -spring.datasource.password=${DATASOURCE_PASSWORD} - # Mapping /actuator/health to /status management.endpoints.web.base-path=/ management.endpoints.web.path-mapping.health=status diff --git a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt index e97b7a71..0d0899d8 100644 --- a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt +++ b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt @@ -16,8 +16,8 @@ actual class PlatformSqlDriver { config.jdbcUrl = url config.username = username config.password = password - config.maximumPoolSize = 20 - config.minimumIdle = 20 + config.maximumPoolSize = 10 + config.minimumIdle = 5 config.connectionTimeout = 30000 config.idleTimeout = 600000 config.maxLifetime = 1800000 @@ -30,6 +30,24 @@ actual class PlatformSqlDriver { return HikariDataSource(config) } + + fun getConnectionMetrics(): Map { + val ds = dataSourceRef.get() ?: return emptyMap() + return try { + mapOf( + "Active Connections" to ds.hikariPoolMXBean.activeConnections, + "Idle Connections" to ds.hikariPoolMXBean.idleConnections, + "Total Connections" to ds.hikariPoolMXBean.totalConnections, + "Threads Awaiting Connection" to ds.hikariPoolMXBean.threadsAwaitingConnection + ) + } catch (e: Exception) { + println("Error getting metrics: ${e.message}") + e.printStackTrace() + emptyMap() + } + } + + } actual fun createPostgresDriver(url: String, username: String, password: String): SqlDriver { From c165bed4c35a844c93bf67e7729f177a747d6978 Mon Sep 17 00:00:00 2001 From: John Melati Date: Tue, 14 Jan 2025 17:05:08 +0100 Subject: [PATCH 03/16] disable datasource autoconfigure in federation server --- .../federation-server/src/main/resources/application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/federation-server/src/main/resources/application.properties b/modules/federation-server/src/main/resources/application.properties index 2c49eeee..fc7c1502 100644 --- a/modules/federation-server/src/main/resources/application.properties +++ b/modules/federation-server/src/main/resources/application.properties @@ -4,3 +4,4 @@ spring.application.name=OpenID Federation Server management.endpoints.web.base-path=/ management.endpoints.web.path-mapping.health=status server.port=8080 +spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration From 7b407b9b6a8f48c8bcc1de3703272331f883e633 Mon Sep 17 00:00:00 2001 From: John Melati Date: Wed, 15 Jan 2025 22:09:50 +0100 Subject: [PATCH 04/16] feat: publish to dockerhub --- .docker/admin-server/Dockerfile | 15 +- .docker/federation-server/Dockerfile | 15 +- .github/workflows/ci.yml | 170 +++++++++++++++--- .gitignore | 4 + README.md | 25 ++- build.gradle.kts | 128 ++++++++++++- docker-compose.yaml | 85 +++++++-- gradlew | 0 logs/.gitkeep | 0 logs/admin-server/.gitkeep | 0 logs/admin-server/federation-2025-01-15.log | 73 ++++++++ logs/federation-server/.gitkeep | 0 .../oid/fed/server/admin/Application.kt | 2 +- .../handlers/logger/FileLoggerHandler.kt | 59 +++++- .../admin/middlewares/LoggerMiddleware.kt | 2 +- modules/local-kms/build.gradle.kts | 21 +-- .../database/PlatformSqlDriver.jvm.kt | 4 +- .../services/config/AccountServiceConfig.kt | 3 +- .../services/config/AccountServiceConfig.kt | 8 - .../src/jvmMain/resources/application.yml | 3 - 20 files changed, 534 insertions(+), 83 deletions(-) mode change 100644 => 100755 gradlew create mode 100644 logs/.gitkeep create mode 100644 logs/admin-server/.gitkeep create mode 100644 logs/admin-server/federation-2025-01-15.log create mode 100644 logs/federation-server/.gitkeep delete mode 100644 modules/services/src/jvmMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt delete mode 100644 modules/services/src/jvmMain/resources/application.yml diff --git a/.docker/admin-server/Dockerfile b/.docker/admin-server/Dockerfile index 45c78c0b..7b73ec5a 100644 --- a/.docker/admin-server/Dockerfile +++ b/.docker/admin-server/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:21-jdk as builder +FROM openjdk:21-jdk AS builder RUN microdnf install findutils WORKDIR /app @@ -9,10 +9,17 @@ RUN chmod +x ./gradlew RUN ./gradlew :modules:admin-server:bootJar -x test -x allTests -x jsBrowserTest -FROM openjdk:21-jdk as runner +FROM openjdk:21-jdk AS runner +RUN microdnf install curl WORKDIR /app -COPY --from=builder /app/modules/admin-server/build/libs/admin-server-0.1.2-SNAPSHOT.jar ./admin-server-0.1.2.jar +COPY --from=builder /app/modules/admin-server/build/libs/admin-server-*.jar ./admin-server.jar +HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8080/status || exit 1 -ENTRYPOINT ["java", "-jar", "admin-server-0.1.2.jar"] +# Create non-root user +RUN useradd -r -u 1002 -g root admin-server +USER admin-server + +ENTRYPOINT ["java"] +CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "admin-server.jar"] \ No newline at end of file diff --git a/.docker/federation-server/Dockerfile b/.docker/federation-server/Dockerfile index f8143688..cc05c460 100644 --- a/.docker/federation-server/Dockerfile +++ b/.docker/federation-server/Dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:21-jdk as builder +FROM openjdk:21-jdk AS builder RUN microdnf install findutils WORKDIR /app @@ -9,10 +9,17 @@ RUN chmod +x ./gradlew RUN ./gradlew :modules:federation-server:bootJar -x test -x allTests -x jsBrowserTest -FROM openjdk:21-jdk as runner +FROM openjdk:21-jdk AS runner +RUN microdnf install curl WORKDIR /app -COPY --from=builder /app/modules/federation-server/build/libs/federation-server-0.1.2-SNAPSHOT.jar ./federation-server-0.1.2.jar +COPY --from=builder /app/modules/federation-server/build/libs/federation-server-*.jar ./federation-server.jar +HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8080/status || exit 1 -ENTRYPOINT ["java", "-jar", "federation-server-0.1.2.jar"] +# Create non-root user +RUN useradd -r -u 1001 -g root federation-server +USER federation-server + +ENTRYPOINT ["java"] +CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "federation-server.jar"] \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 444dc8cd..3a038b43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,13 @@ name: Run CI + on: push: workflow_dispatch: jobs: gradle: + outputs: + success: ${{ steps.build.outcome == 'success' }} strategy: matrix: # Removed windows, because build failing with docker network. "bridge" network driver is not supported for Windows containers @@ -18,20 +21,6 @@ jobs: distribution: temurin java-version: 21 - - name: Run database - run: docker compose -f docker-compose.yaml up db -d - env: - DATASOURCE_USER: ${{ secrets.DATASOURCE_USER }} - DATASOURCE_PASSWORD: ${{ secrets.DATASOURCE_PASSWORD }} - DATASOURCE_URL: ${{ secrets.DATASOURCE_URL }} - - - name: Run local KMS database - run: docker compose -f docker-compose.yaml up local-kms-db -d - env: - DATASOURCE_USER: ${{ secrets.LOCAL_KMS_DATASOURCE_USER }} - DATASOURCE_PASSWORD: ${{ secrets.LOCAL_KMS_DATASOURCE_PASSWORD }} - DATASOURCE_URL: ${{ secrets.LOCAL_KMS_DATASOURCE_URL }} - - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 @@ -39,13 +28,8 @@ jobs: if: runner.os != 'Windows' run: chmod +x ./gradlew - - name: Execute Gradle build - run: | - ./gradlew build - ./gradlew :modules:openapi:jsPublicPackageJson - ./gradlew :modules:openid-federation-common:jsPublicPackageJson - ./gradlew publishJsPackageToNpmjsRegistry - ./gradlew publishAllPublicationsToSphereon-opensourceRepository + - name: Execute build + id: build env: APP_KEY: ${{ secrets.APP_KEY }} DATASOURCE_USER: ${{ secrets.DATASOURCE_USER }} @@ -58,3 +42,147 @@ jobs: NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} KMS_PROVIDER: local + run: | + ./gradlew build + ./gradlew :modules:openapi:jsPublicPackageJson + ./gradlew :modules:openid-federation-common:jsPublicPackageJson + ./gradlew publishJsPackageToNpmjsRegistry + ./gradlew publishAllPublicationsToSphereon-opensourceRepository + + auto-tag: + needs: gradle + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version_info.outputs.new_version }} + if: github.event_name == 'repository_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || (github.event_name == 'push' && needs.gradle.outputs.success == 'true') + permissions: + contents: write + actions: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Get version info + id: get_version_info + run: | + git config --local user.email "${GITHUB_ACTOR}@users.noreply.github.com" + git config --local user.name "${GITHUB_ACTOR}" + EVENT_NAME="${{ github.event_name }}" + if [[ "$EVENT_NAME" == "pull_request" ]]; then + BRANCH_NAME="${{ github.event.pull_request.head.ref }}" + else + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + fi + if [[ $BRANCH_NAME == "develop" ]]; then + PREFIX="dev" + elif [[ $BRANCH_NAME == "main" ]]; then + PREFIX="main" + elif [[ $BRANCH_NAME == feature/* ]]; then + PREFIX="feat" + elif [[ $BRANCH_NAME == hotfix/* ]]; then + PREFIX="fix" + elif [[ $BRANCH_NAME == release/* ]]; then + PREFIX="rel" + else + PREFIX="build" + fi + GRADLE_VERSION=$(grep 'version = ' build.gradle.kts | sed 's/.*version = "\(.*\)".*/\1/') + GRADLE_VERSION=${GRADLE_VERSION%-SNAPSHOT} + COMMIT_SHA=$(git rev-parse --short HEAD) + PR_NUMBER=${{ github.event.pull_request.number }} + if [[ -n $PR_NUMBER ]]; then + NEW_VERSION="v${GRADLE_VERSION}-${PREFIX}.pr${PR_NUMBER}.${COMMIT_SHA}" + else + NEW_VERSION="v${GRADLE_VERSION}-${PREFIX}.${COMMIT_SHA}" + fi + echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT + git tag -a ${NEW_VERSION} -m "Release ${NEW_VERSION}" + git push origin ${NEW_VERSION} + + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + docker-publish: + needs: [gradle, auto-tag] + if: needs.gradle.outputs.success == 'true' + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + contents: read + packages: write + steps: + - name: Debug Event + run: | + echo "Event name: ${{ github.event_name }}" + echo "Ref type: ${{ github.ref_type }}" + echo "Ref: ${{ github.ref }}" + echo "SHA: ${{ github.sha }}" + echo "Base ref: ${{ github.base_ref }}" + echo "Head ref: ${{ github.head_ref }}" + echo "Workflow ref: ${{ github.workflow_ref }}" + + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract metadata (federation-server) + id: meta-federation + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + type=raw,value=${{ needs.auto-tag.outputs.version }} + + - name: Build and push federation-server + uses: docker/build-push-action@v5 + with: + context: . + file: ./.docker/federation-server/Dockerfile + push: true + tags: ${{ steps.meta-federation.outputs.tags }} + labels: ${{ steps.meta-federation.outputs.labels }} + cache-from: | + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server:latest + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest + cache-to: | + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server:latest,mode=max + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest,mode=max + + - name: Extract metadata (admin-server) + id: meta-admin + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-admin-server + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + type=raw,value=${{ needs.auto-tag.outputs.version }} + + - name: Build and push admin-server + uses: docker/build-push-action@v5 + with: + context: . + file: ./.docker/admin-server/Dockerfile + push: true + tags: ${{ steps.meta-admin.outputs.tags }} + labels: ${{ steps.meta-admin.outputs.labels }} + cache-from: | + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-admin-server:latest + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest + cache-to: | + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-admin-server:latest,mode=max + type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest,mode=max \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3da44e6b..1db6fbed 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,7 @@ kotlin-js-store/ .env.local /.docker/keycloak-dev/ /modules/admin-server/logs/ +/logs/* +!logs/.gitkeep +!logs/admin-server/.gitkeep +!logs/federation-server/.gitkeep \ No newline at end of file diff --git a/README.md b/README.md index 14909c2b..ad8fad68 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,17 @@ Sphereon
OpenID Federation Monorepo
+
+
+ +[![Snyk Security](https://snyk.io/test/github/Sphereon-Opensource/OpenID-Federation/badge.svg)](https://snyk.io/test/github/Sphereon-Opensource/OpenID-Federation) +[![Docker Pulls](https://img.shields.io/docker/pulls/sphereon/openid-federation-server.svg)](https://hub.docker.com/r/sphereon/openid-federation-server) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) + +
+ # Background OpenID Federation is a framework designed to facilitate the secure and interoperable interaction of entities within a @@ -255,7 +264,8 @@ To create a new tenant account, follow these steps: } ``` -Note: All subsequent requests will use the `X-Account-Username` header to specify the account context. If not provided, it defaults to the root account. +Note: All subsequent requests will use the `X-Account-Username` header to specify the account context. If not provided, +it defaults to the root account. ## Step 5: Delete a Tenant Account @@ -267,6 +277,7 @@ To delete a tenant account, follow these steps: DELETE http://localhost:8081/accounts X-Account-Username: {username} # root account cannot be deleted ``` + ## Step 6: Create and Manage Keys ### Create a New Key Pair @@ -346,6 +357,7 @@ To assign metadata to your entity, follow these steps: DELETE http://localhost:8081/metadata/{id} X-Account-Username: {username} # Optional, defaults to root ``` + --- ## Step 8: Create and Manage Subordinates @@ -384,6 +396,7 @@ To assign metadata to your entity, follow these steps: DELETE http://localhost:8081/subordinates/{id} X-Account-Username: {username} # Optional, defaults to root ``` + --- ## Step 9: Manage Subordinate Metadata @@ -423,7 +436,9 @@ To assign metadata to your entity, follow these steps: DELETE http://localhost:8081/subordinates/{subordinateId}/metadata/{id} X-Account-Username: {username} # Optional, defaults to root ``` + --- + ## Step 10: Manage Subordinate JWKS ### Add a JWKS for a Subordinate @@ -464,6 +479,7 @@ To assign metadata to your entity, follow these steps: ``` --- + ## Step 11: Get Subordinate Statement Object 1. Send a `GET` request to retrieve the statement for a subordinate: @@ -514,13 +530,15 @@ To assign metadata to your entity, follow these steps: X-Account-Username: {username} # Optional, defaults to root ``` -2. Optionally, include a `dryRun` parameter in the request body to test the statement publication without making changes: +2. Optionally, include a `dryRun` parameter in the request body to test the statement publication without making + changes: ```json { "dryRun": true } ``` + # Trust Marks ## Trust Mark Workflow @@ -624,10 +642,11 @@ GET http://localhost:8080/trust-mark-issuer/trust-mark-status "sub": "https://example.com/holder" } ``` + # API Reference For the complete API documentation, please -visit [the API Reference](https://github.com/Sphereon-Opensource/OpenID-Federation/) +visit [the API Reference](https://app.swaggerhub.com/apis-docs/SphereonInt/OpenIDFederationAPI) # License diff --git a/build.gradle.kts b/build.gradle.kts index 80cc70bc..70edb771 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ +import java.io.ByteArrayOutputStream + plugins { - // this is necessary to avoid the plugins to be loaded multiple times - // in each subproject's classloader alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.jetbrainsCompose) apply false @@ -39,7 +39,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.1.2-SNAPSHOT" + version = "0.2.22-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects @@ -65,6 +65,128 @@ subprojects { } } } + + // Ensure unique coordinates for different publication types + publications.withType { + val publicationName = name + if (publicationName == "kotlinMultiplatform") { + artifactId = "${project.name}-multiplatform" + } else if (publicationName == "mavenKotlin") { + artifactId = "${project.name}-jvm" + } + } + } + } +} + +tasks.register("checkDockerStatus") { + group = "docker" + description = "Checks if Docker containers are running" + doLast { + val output = ByteArrayOutputStream() + val process = exec { + commandLine("docker", "compose", "ps", "-q", "db", "local-kms-db") + isIgnoreExitValue = true + standardOutput = output + } + + val containersRunning = process.exitValue == 0 && output.toString().trim().isNotEmpty() + project.ext.set("containersRunning", containersRunning) + + if (containersRunning) { + println("Required Docker containers are already running") + } else { + println("Required Docker containers are not running") } } } + +tasks.register("dockerCleanup") { + group = "docker" + description = "Stops and removes specific Docker containers" + doLast { + exec { + commandLine("docker", "compose", "rm", "-fsv", "db", "local-kms-db") + } + } +} + +fun waitForDatabase() { + var ready = false + var attempts = 0 + val maxAttempts = 30 + + while (!ready && attempts < maxAttempts) { + try { + val process = exec { + commandLine("docker", "compose", "exec", "-T", "db", "pg_isready", "-U", "postgres") + isIgnoreExitValue = true + } + ready = process.exitValue == 0 + } catch (e: Exception) { + } + + if (!ready) { + attempts++ + Thread.sleep(2000) + println("Waiting for database to be ready... (Attempt $attempts/$maxAttempts)") + } + } + + if (!ready) { + throw GradleException("Database failed to become ready within the timeout period") + } + println("Database is ready!") +} + +tasks.register("waitForDatabase") { + group = "docker" + description = "Waits for the database to be ready" + doLast { + waitForDatabase() + } +} + +tasks.register("dockerStart") { + group = "docker" + description = "Starts specific Docker containers" + doLast { + exec { + commandLine("docker", "compose", "up", "-d", "db", "local-kms-db") + } + waitForDatabase() + } +} + +tasks.register("dockerEnsureRunning") { + group = "docker" + description = "Ensures Docker containers are running, starting them if needed" + dependsOn("checkDockerStatus") + + doLast { + if (!project.ext.has("containersRunning") || !project.ext.get("containersRunning").toString().toBoolean()) { + exec { + commandLine("docker", "compose", "rm", "-fsv", "db", "local-kms-db") + } + exec { + commandLine("docker", "compose", "up", "-d", "db", "local-kms-db") + } + } + waitForDatabase() + project.ext.set("containersRunning", true) + } +} + +subprojects { + tasks.matching { it.name == "build" }.configureEach { + dependsOn(rootProject.tasks.named("dockerEnsureRunning")) + + doFirst { + if (!rootProject.ext.has("containersRunning") || !rootProject.ext.get("containersRunning").toString() + .toBoolean() + ) { + throw GradleException("Docker containers are not running. Please run './gradlew dockerEnsureRunning' first.") + } + } + } +} \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 76f35e3a..21fcffd8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,6 +2,9 @@ services: db: image: postgres:latest container_name: openid-federation-datastore + user: postgres + security_opt: + - no-new-privileges:true environment: POSTGRES_USER: ${DATASOURCE_USER} POSTGRES_PASSWORD: ${DATASOURCE_PASSWORD} @@ -12,6 +15,12 @@ services: - postgres_data:/var/lib/postgresql/data networks: - openid_network + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" healthcheck: test: [ "CMD-SHELL", "pg_isready -d ${DATASOURCE_DB} -U ${DATASOURCE_USER}" ] interval: 3s @@ -21,6 +30,9 @@ services: local-kms-db: image: postgres:latest container_name: openid-federation-local-kms-datastore + user: postgres + security_opt: + - no-new-privileges:true environment: POSTGRES_USER: ${LOCAL_KMS_DATASOURCE_USER} POSTGRES_PASSWORD: ${LOCAL_KMS_DATASOURCE_PASSWORD} @@ -31,19 +43,29 @@ services: - local_kms_data:/var/lib/postgresql/data networks: - openid_network + depends_on: + db: + condition: service_healthy healthcheck: test: [ "CMD-SHELL", "pg_isready -d ${LOCAL_KMS_DATASOURCE_DB} -U ${LOCAL_KMS_DATASOURCE_USER}" ] interval: 3s timeout: 5s retries: 20 - federation-server: + image: sphereon/openid-federation-server:latest build: context: . dockerfile: ./.docker/federation-server/Dockerfile + deploy: + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M ports: - "8080:8080" - container_name: openid-federation-server environment: DATASOURCE_URL: ${DATASOURCE_URL} DATASOURCE_USER: ${DATASOURCE_USER} @@ -56,20 +78,38 @@ services: LOCAL_KMS_DATASOURCE_DB: ${LOCAL_KMS_DATASOURCE_DB} ROOT_IDENTIFIER: ${ROOT_IDENTIFIER} depends_on: - admin-server: - condition: service_started db: condition: service_healthy + local-kms-db: + condition: service_healthy + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + volumes: + - ./logs/federation-server:/tmp/logs + user: root + entrypoint: > + /bin/sh -c "java -jar /app/federation-server.jar" networks: - openid_network - admin-server: + image: sphereon/openid-federation-admin-server:latest build: context: . dockerfile: ./.docker/admin-server/Dockerfile + deploy: + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M ports: - "8081:8080" - container_name: openid-federation-server-admin environment: DATASOURCE_URL: ${DATASOURCE_URL} DATASOURCE_USER: ${DATASOURCE_USER} @@ -87,25 +127,49 @@ services: condition: service_healthy local-kms-db: condition: service_healthy - keycloak: - condition: service_healthy networks: - openid_network - + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + volumes: + - ./logs/admin-server:/tmp/logs + user: root + entrypoint: > + /bin/sh -c "java -jar /app/admin-server.jar" keycloak: image: keycloak/keycloak:26.0 + user: keycloak + security_opt: + - no-new-privileges:true command: - start-dev - --import-realm + deploy: + resources: + limits: + cpus: '1' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M ports: - "8082:8080" environment: - KC_BOOTSTRAP_ADMIN_USERNAME=${KC_BOOTSTRAP_ADMIN_USERNAME} - KC_BOOTSTRAP_ADMIN_PASSWORD=${KC_BOOTSTRAP_ADMIN_PASSWORD} - KC_HEALTH_ENABLED=true + - JAVA_OPTS=-XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0 -XX:+UseG1GC volumes: - ./.docker/keycloak:/opt/keycloak/data/import/ - restart: always + restart: unless-stopped + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" networks: - openid_network healthcheck: @@ -122,3 +186,4 @@ networks: volumes: postgres_data: local_kms_data: + logs: \ No newline at end of file diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/logs/.gitkeep b/logs/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/logs/admin-server/.gitkeep b/logs/admin-server/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/logs/admin-server/federation-2025-01-15.log b/logs/admin-server/federation-2025-01-15.log new file mode 100644 index 00000000..e9d4b27b --- /dev/null +++ b/logs/admin-server/federation-2025-01-15.log @@ -0,0 +1,73 @@ +[INFO] 2025-01-15T14:52:58.059557320 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=30MB/67MB(45%), Processors=1, Heap=30MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 +Context: + uptime_hours: 0 + uptime_minutes: 0 + memory_used_mb: 30 + memory_total_mb: 67 + memory_usage_percent: 45 + processors: 1 + heap_used_mb: 31 + thread_count: 28 + thread_peak: 28 + thread_daemon: 23 + db_active_connections: 0 + db_idle_connections: 20 + db_total_connections: 20 + db_threads_awaiting_connection: 0 +[INFO] 2025-01-15T14:52:58.153676966 [AdminServerMonitoring] System Load Average: 0.54 +[INFO] 2025-01-15T14:59:23.057599469 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=39MB/77MB(51%), Processors=1, Heap=39MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 +Context: + uptime_hours: 0 + uptime_minutes: 0 + memory_used_mb: 39 + memory_total_mb: 77 + memory_usage_percent: 51 + processors: 1 + heap_used_mb: 39 + thread_count: 28 + thread_peak: 28 + thread_daemon: 23 + db_active_connections: 0 + db_idle_connections: 20 + db_total_connections: 20 + db_threads_awaiting_connection: 0 +[WARN] 2025-01-15T14:59:23.148299338 [AdminServerMonitoring] System Load Average: 1.64 (exceeds threshold: 0.8) +[DEBUG] 2025-01-15T14:59:34.241567342 [RequestLogger] Received accounts Creation request +Context: + operation: accounts Creation + method: POST + uri: /accounts + remote_addr: 172.18.0.1 + protocol: HTTP/1.1 + header_content_type: application/json + header_authorization: [REDACTED] + header_user_agent: PostmanRuntime/7.39.0 + header_accept: */* + header_postman_token: 2421be13-d4e3-42a3-b2a3-e144510c20e2 + header_host: localhost:8081 + header_accept_encoding: gzip, deflate, br + header_connection: keep-alive + header_content_length: 87 +[DEBUG] 2025-01-15T14:59:34.246030579 [AccountService] Getting account by username: root +[DEBUG] 2025-01-15T14:59:34.255876080 [AccountService] Using identifier for username: root as default-root +[INFO] 2025-01-15T14:59:34.967971772 [AccountService] Starting account creation process for username: sphewwwwwwrddeon +[DEBUG] 2025-01-15T14:59:34.972659284 [AccountService] Account creation details - Username: sphewwwwwwrddeon, Identifier: https://www.sphereon.com +[ERROR] 2025-01-15T14:59:34.976862813 [AccountService] Account creation failed: Account with username sphewwwwwwrddeon already exists +[INFO] 2025-01-15T14:59:35.040383377 [ExceptionHandler] Resource conflict occurred - Type: EntityAlreadyExistsException, Message: Account already exists +[INFO] 2025-01-15T17:41:06.972833202 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=26MB/38MB(68%), Processors=1, Heap=26MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 +Context: + uptime_hours: 0 + uptime_minutes: 0 + memory_used_mb: 26 + memory_total_mb: 38 + memory_usage_percent: 68 + processors: 1 + heap_used_mb: 27 + thread_count: 28 + thread_peak: 28 + thread_daemon: 23 + db_active_connections: 0 + db_idle_connections: 20 + db_total_connections: 20 + db_threads_awaiting_connection: 0 +[WARN] 2025-01-15T17:41:07.062505865 [AdminServerMonitoring] System Load Average: 5.44 (exceeds threshold: 0.8) diff --git a/logs/federation-server/.gitkeep b/logs/federation-server/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/Application.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/Application.kt index fa48d02a..0d8f341f 100644 --- a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/Application.kt +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/Application.kt @@ -18,7 +18,7 @@ import java.time.format.DateTimeFormatter class Application(private val logService: LogService) { @PostConstruct fun configureLogger() { - val logDir = File("logs").apply { mkdirs() } + val logDir = File("/tmp/logs").apply { mkdirs() } val logFile = File(logDir, "federation-${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))}.log") diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/handlers/logger/FileLoggerHandler.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/handlers/logger/FileLoggerHandler.kt index 804f1f83..2510f8fc 100644 --- a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/handlers/logger/FileLoggerHandler.kt +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/handlers/logger/FileLoggerHandler.kt @@ -2,31 +2,72 @@ package com.sphereon.oid.fed.server.admin.handlers.logger import com.sphereon.oid.fed.logger.Logger import java.io.File +import java.nio.file.Files class FileLoggerHandler(private val logFile: File) : Logger.LogWriter { init { try { + println("Attempting to initialize log file at: ${logFile.absolutePath}") + logFile.parentFile?.let { parent -> - if (!parent.exists() && !parent.mkdirs()) { - throw IllegalStateException("Failed to create log directory: ${parent.absolutePath}") + if (!parent.exists()) { + println("Log directory doesn't exist, attempting to create: ${parent.absolutePath}") + try { + Files.createDirectories(parent.toPath()) + println("Successfully created log directory") + } catch (e: Exception) { + val msg = "Failed to create log directory: ${parent.absolutePath}. Error: ${e.message}" + println(msg) + throw IllegalStateException(msg, e) + } + } + + // Check directory permissions + if (!parent.canWrite()) { + val msg = "No write permission for log directory: ${parent.absolutePath}" + println(msg) + throw IllegalStateException(msg) } } - if (!logFile.exists() && !logFile.createNewFile()) { - throw IllegalStateException("Failed to create log file: ${logFile.absolutePath}") + + if (!logFile.exists()) { + println("Log file doesn't exist, attempting to create: ${logFile.absolutePath}") + try { + logFile.createNewFile() + println("Successfully created log file") + } catch (e: Exception) { + val msg = "Failed to create log file: ${logFile.absolutePath}. Error: ${e.message}" + println(msg) + throw IllegalStateException(msg, e) + } } + if (!logFile.canWrite()) { - throw IllegalStateException("Log file is not writable: ${logFile.absolutePath}") + val msg = "Log file is not writable: ${logFile.absolutePath}" + println(msg) + throw IllegalStateException(msg) } + + println("Successfully initialized log file handler") } catch (e: SecurityException) { - throw IllegalStateException("Security violation while setting up log file: ${logFile.absolutePath}", e) + val msg = "Security violation while setting up log file: ${logFile.absolutePath}" + println("$msg. Error: ${e.message}") + throw IllegalStateException(msg, e) } catch (e: Exception) { - throw IllegalStateException("Failed to initialize log file: ${logFile.absolutePath}", e) + val msg = "Failed to initialize log file: ${logFile.absolutePath}" + println("$msg. Error: ${e.message}") + throw IllegalStateException(msg, e) } } override fun log(event: Logger.LogEvent) { synchronized(this) { - logFile.appendText("${event.formattedMessage}\n") + try { + logFile.appendText("${event.formattedMessage}\n") + } catch (e: Exception) { + println("Failed to write to log file: ${logFile.absolutePath}. Error: ${e.message}") + // Consider implementing a fallback logging mechanism here + } } } -} +} \ No newline at end of file diff --git a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/middlewares/LoggerMiddleware.kt b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/middlewares/LoggerMiddleware.kt index e4374618..90b7f631 100644 --- a/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/middlewares/LoggerMiddleware.kt +++ b/modules/admin-server/src/main/kotlin/com/sphereon/oid/fed/server/admin/middlewares/LoggerMiddleware.kt @@ -44,7 +44,7 @@ class LoggerMiddleware : OncePerRequestFilter() { } private fun getOperationName(request: HttpServletRequest): String { - val baseResource = request.requestURI.split("/")[1].capitalize() + val baseResource = request.requestURI.split("/")[1] return when (request.method.uppercase()) { "GET" -> "$baseResource Retrieval" "POST" -> "$baseResource Creation" diff --git a/modules/local-kms/build.gradle.kts b/modules/local-kms/build.gradle.kts index 31552972..3c7210e3 100644 --- a/modules/local-kms/build.gradle.kts +++ b/modules/local-kms/build.gradle.kts @@ -58,18 +58,15 @@ kotlin { } publishing { - publications { - create("mavenKotlin") { - - pom { - name.set("OpenID Federation Local KMS") - description.set("Local Key Management System for OpenID Federation") - url.set("https://github.com/Sphereon-Opensource/openid-federation") - licenses { - license { - name.set("The Apache License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - } + publications.withType().configureEach { + pom { + name.set("OpenID Federation Local KMS") + description.set("Local Key Management System for OpenID Federation") + url.set("https://github.com/Sphereon-Opensource/openid-federation") + licenses { + license { + name.set("The Apache License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") } } } diff --git a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt index 0d0899d8..ffaebfbb 100644 --- a/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt +++ b/modules/persistence/src/jvmMain/kotlin/com/sphereon/oid/fed/persistence/database/PlatformSqlDriver.jvm.kt @@ -16,8 +16,8 @@ actual class PlatformSqlDriver { config.jdbcUrl = url config.username = username config.password = password - config.maximumPoolSize = 10 - config.minimumIdle = 5 + config.maximumPoolSize = 20 + config.minimumIdle = 20 config.connectionTimeout = 30000 config.idleTimeout = 600000 config.maxLifetime = 1800000 diff --git a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt index 70baf81b..97291441 100644 --- a/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt +++ b/modules/services/src/commonMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt @@ -3,6 +3,5 @@ package com.sphereon.oid.fed.services.config /** * Configuration class for account-related settings. */ -expect class AccountServiceConfig(rootIdentifier: String = "default-root") : IAccountServiceConfig { - override val rootIdentifier: String +class AccountServiceConfig(override val rootIdentifier: String = "default-root") : IAccountServiceConfig { } \ No newline at end of file diff --git a/modules/services/src/jvmMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt b/modules/services/src/jvmMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt deleted file mode 100644 index ed4c9895..00000000 --- a/modules/services/src/jvmMain/kotlin/com/sphereon/oid/fed/services/config/AccountServiceConfig.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.sphereon.oid.fed.services.config - -/** - * JVM implementation of account configuration. - */ -actual class AccountServiceConfig actual constructor( - actual override val rootIdentifier: String -) : IAccountServiceConfig \ No newline at end of file diff --git a/modules/services/src/jvmMain/resources/application.yml b/modules/services/src/jvmMain/resources/application.yml deleted file mode 100644 index f21bfa50..00000000 --- a/modules/services/src/jvmMain/resources/application.yml +++ /dev/null @@ -1,3 +0,0 @@ -sphereon: - federation: - root-identifier: http://localhost:8081 \ No newline at end of file From a062925657577a9a90600eac3085049f3fbeb28e Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 00:29:02 +0100 Subject: [PATCH 05/16] chore: ignore logs --- .gitignore | 2 + logs/admin-server/federation-2025-01-15.log | 73 --------------------- 2 files changed, 2 insertions(+), 73 deletions(-) delete mode 100644 logs/admin-server/federation-2025-01-15.log diff --git a/.gitignore b/.gitignore index 1db6fbed..bab80ef2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,8 @@ kotlin-js-store/ /.docker/keycloak-dev/ /modules/admin-server/logs/ /logs/* +/logs/admin-server/* +/logs/federation-server/* !logs/.gitkeep !logs/admin-server/.gitkeep !logs/federation-server/.gitkeep \ No newline at end of file diff --git a/logs/admin-server/federation-2025-01-15.log b/logs/admin-server/federation-2025-01-15.log deleted file mode 100644 index e9d4b27b..00000000 --- a/logs/admin-server/federation-2025-01-15.log +++ /dev/null @@ -1,73 +0,0 @@ -[INFO] 2025-01-15T14:52:58.059557320 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=30MB/67MB(45%), Processors=1, Heap=30MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 -Context: - uptime_hours: 0 - uptime_minutes: 0 - memory_used_mb: 30 - memory_total_mb: 67 - memory_usage_percent: 45 - processors: 1 - heap_used_mb: 31 - thread_count: 28 - thread_peak: 28 - thread_daemon: 23 - db_active_connections: 0 - db_idle_connections: 20 - db_total_connections: 20 - db_threads_awaiting_connection: 0 -[INFO] 2025-01-15T14:52:58.153676966 [AdminServerMonitoring] System Load Average: 0.54 -[INFO] 2025-01-15T14:59:23.057599469 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=39MB/77MB(51%), Processors=1, Heap=39MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 -Context: - uptime_hours: 0 - uptime_minutes: 0 - memory_used_mb: 39 - memory_total_mb: 77 - memory_usage_percent: 51 - processors: 1 - heap_used_mb: 39 - thread_count: 28 - thread_peak: 28 - thread_daemon: 23 - db_active_connections: 0 - db_idle_connections: 20 - db_total_connections: 20 - db_threads_awaiting_connection: 0 -[WARN] 2025-01-15T14:59:23.148299338 [AdminServerMonitoring] System Load Average: 1.64 (exceeds threshold: 0.8) -[DEBUG] 2025-01-15T14:59:34.241567342 [RequestLogger] Received accounts Creation request -Context: - operation: accounts Creation - method: POST - uri: /accounts - remote_addr: 172.18.0.1 - protocol: HTTP/1.1 - header_content_type: application/json - header_authorization: [REDACTED] - header_user_agent: PostmanRuntime/7.39.0 - header_accept: */* - header_postman_token: 2421be13-d4e3-42a3-b2a3-e144510c20e2 - header_host: localhost:8081 - header_accept_encoding: gzip, deflate, br - header_connection: keep-alive - header_content_length: 87 -[DEBUG] 2025-01-15T14:59:34.246030579 [AccountService] Getting account by username: root -[DEBUG] 2025-01-15T14:59:34.255876080 [AccountService] Using identifier for username: root as default-root -[INFO] 2025-01-15T14:59:34.967971772 [AccountService] Starting account creation process for username: sphewwwwwwrddeon -[DEBUG] 2025-01-15T14:59:34.972659284 [AccountService] Account creation details - Username: sphewwwwwwrddeon, Identifier: https://www.sphereon.com -[ERROR] 2025-01-15T14:59:34.976862813 [AccountService] Account creation failed: Account with username sphewwwwwwrddeon already exists -[INFO] 2025-01-15T14:59:35.040383377 [ExceptionHandler] Resource conflict occurred - Type: EntityAlreadyExistsException, Message: Account already exists -[INFO] 2025-01-15T17:41:06.972833202 [AdminServerMonitoring] System Health: Uptime=0h0m, Memory=26MB/38MB(68%), Processors=1, Heap=26MB, Threads=28(Peak:28, Daemon:23), DB Connections: Active=0, Idle=20, Total=20 -Context: - uptime_hours: 0 - uptime_minutes: 0 - memory_used_mb: 26 - memory_total_mb: 38 - memory_usage_percent: 68 - processors: 1 - heap_used_mb: 27 - thread_count: 28 - thread_peak: 28 - thread_daemon: 23 - db_active_connections: 0 - db_idle_connections: 20 - db_total_connections: 20 - db_threads_awaiting_connection: 0 -[WARN] 2025-01-15T17:41:07.062505865 [AdminServerMonitoring] System Load Average: 5.44 (exceeds threshold: 0.8) From ad423e4ddacdeb25be48da07b4f978579416dd1a Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 10:48:09 +0100 Subject: [PATCH 06/16] fix: docker hub deployment to correct account --- .github/workflows/ci.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a038b43..10fdd9ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,7 +107,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} docker-publish: - needs: [gradle, auto-tag] + needs: [ gradle, auto-tag ] if: needs.gradle.outputs.success == 'true' runs-on: ubuntu-latest timeout-minutes: 20 @@ -143,10 +143,15 @@ jobs: id: meta-federation uses: docker/metadata-action@v5 with: - images: ${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server + images: sphereon/openid-federation-server tags: | type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=raw,value=${{ needs.auto-tag.outputs.version }} + type=ref,event=branch + type=sha,format=short + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} - name: Build and push federation-server uses: docker/build-push-action@v5 @@ -167,10 +172,15 @@ jobs: id: meta-admin uses: docker/metadata-action@v5 with: - images: ${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-admin-server + images: sphereon/openid-federation-admin-server tags: | type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} type=raw,value=${{ needs.auto-tag.outputs.version }} + type=ref,event=branch + type=sha,format=short + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} - name: Build and push admin-server uses: docker/build-push-action@v5 From 24627f010694698332a27993772ec45f537207f9 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 11:00:43 +0100 Subject: [PATCH 07/16] fix: reuse build artifacts --- .docker/admin-server/Dockerfile | 10 +++++----- .docker/federation-server/Dockerfile | 12 +++++++----- .github/workflows/ci.yml | 24 +++++++++++++++++++++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/.docker/admin-server/Dockerfile b/.docker/admin-server/Dockerfile index 7b73ec5a..bbcf1429 100644 --- a/.docker/admin-server/Dockerfile +++ b/.docker/admin-server/Dockerfile @@ -2,14 +2,14 @@ FROM openjdk:21-jdk AS builder RUN microdnf install findutils WORKDIR /app - COPY . /app - RUN chmod +x ./gradlew -RUN ./gradlew :modules:admin-server:bootJar -x test -x allTests -x jsBrowserTest +RUN if [ ! -f modules/admin-server/build/libs/admin-server-*.jar ]; then \ + ./gradlew :modules:admin-server:bootJar -x test -x allTests -x jsBrowserTest; \ + fi -FROM openjdk:21-jdk AS runner +FROM openjdk:21-jdk RUN microdnf install curl WORKDIR /app @@ -22,4 +22,4 @@ RUN useradd -r -u 1002 -g root admin-server USER admin-server ENTRYPOINT ["java"] -CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "admin-server.jar"] \ No newline at end of file +CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "admin-server.jar"] diff --git a/.docker/federation-server/Dockerfile b/.docker/federation-server/Dockerfile index cc05c460..1c678560 100644 --- a/.docker/federation-server/Dockerfile +++ b/.docker/federation-server/Dockerfile @@ -2,14 +2,14 @@ FROM openjdk:21-jdk AS builder RUN microdnf install findutils WORKDIR /app - COPY . /app - RUN chmod +x ./gradlew -RUN ./gradlew :modules:federation-server:bootJar -x test -x allTests -x jsBrowserTest +RUN if [ ! -f modules/federation-server/build/libs/federation-server-*.jar ]; then \ + ./gradlew :modules:federation-server:bootJar -x test -x allTests -x jsBrowserTest; \ + fi -FROM openjdk:21-jdk AS runner +FROM openjdk:21-jdk RUN microdnf install curl WORKDIR /app @@ -22,4 +22,6 @@ RUN useradd -r -u 1001 -g root federation-server USER federation-server ENTRYPOINT ["java"] -CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "federation-server.jar"] \ No newline at end of file +CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "federation-server.jar"] + +WORKDIR /app \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10fdd9ba..48ad17e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,6 +49,13 @@ jobs: ./gradlew publishJsPackageToNpmjsRegistry ./gradlew publishAllPublicationsToSphereon-opensourceRepository + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: | + modules/federation-server/build/libs/federation-server-*.jar + modules/admin-server/build/libs/admin-server-*.jar auto-tag: needs: gradle runs-on: ubuntu-latest @@ -130,6 +137,22 @@ jobs: with: fetch-depth: 0 + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + path: ./ + + - name: Create directory structure + run: | + mkdir -p modules/federation-server/build/libs/ + mkdir -p modules/admin-server/build/libs/ + mv federation-server-*.jar modules/federation-server/build/libs/ + mv admin-server-*.jar modules/admin-server/build/libs/ + + - name: List downloaded artifacts + run: ls -R modules/*/build/libs/ + - name: Log in to Docker Hub uses: docker/login-action@v3 with: @@ -138,7 +161,6 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - name: Extract metadata (federation-server) id: meta-federation uses: docker/metadata-action@v5 From d0c25b3d81395ae5cffa592798d79881e550a335 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 11:26:47 +0100 Subject: [PATCH 08/16] fix: version bump on commit --- .docker/federation-server/Dockerfile | 2 - .githooks/pre-commit | 57 ++++++++++++++++++++++++++++ .github/workflows/ci.yml | 14 +++++-- build.gradle.kts | 56 ++++++++++++++++++++++++++- init.gradle.kts | 25 ++++++++++++ 5 files changed, 147 insertions(+), 7 deletions(-) create mode 100755 .githooks/pre-commit create mode 100644 init.gradle.kts diff --git a/.docker/federation-server/Dockerfile b/.docker/federation-server/Dockerfile index 1c678560..30b56cca 100644 --- a/.docker/federation-server/Dockerfile +++ b/.docker/federation-server/Dockerfile @@ -23,5 +23,3 @@ USER federation-server ENTRYPOINT ["java"] CMD ["-XX:MaxRAMPercentage=75.0", "-XX:InitialRAMPercentage=50.0", "-XX:+UseG1GC", "-jar", "federation-server.jar"] - -WORKDIR /app \ No newline at end of file diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..d26ca4d0 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,57 @@ +#!/usr/bin/env bash + +# Ensure script works on both Unix and Windows +export MSYS=winsymlinks:nativestrict +export MSYS2=winsymlinks:nativestrict + +# Get the commit message from the staged commit +COMMIT_MSG=$(git log -1 --pretty=%B) + +# Get the current version from build.gradle.kts +CURRENT_VERSION=$(grep 'version = ' build.gradle.kts | sed 's/.*version = "\(.*\)".*/\1/') + +# Remove -SNAPSHOT if present +VERSION_BASE=${CURRENT_VERSION%-SNAPSHOT} + +# Split version into components +IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION_BASE" + +# Determine version bump type based on commit message +if [[ $COMMIT_MSG == *"BREAKING CHANGE"* ]] || [[ $COMMIT_MSG == *"!:"* ]]; then + # Major version bump + MAJOR=$((MAJOR + 1)) + MINOR=0 + PATCH=0 + echo "BREAKING CHANGE detected - Bumping major version" +elif [[ $COMMIT_MSG =~ ^feat: ]]; then + # Minor version bump + MINOR=$((MINOR + 1)) + PATCH=0 + echo "Feature detected - Bumping minor version" +elif [[ $COMMIT_MSG =~ ^(fix|docs|style|refactor|perf|test|chore): ]]; then + # Patch version bump + PATCH=$((PATCH + 1)) + echo "Fix/maintenance detected - Bumping patch version" +else + # Default to patch bump if no conventional commit prefix is found + PATCH=$((PATCH + 1)) + echo "No conventional commit prefix found - Defaulting to patch bump" +fi + +# Construct new version +NEW_VERSION="$MAJOR.$MINOR.$PATCH-SNAPSHOT" + +# Update build.gradle.kts with new version (using platform-independent sed) +if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then + # Windows-specific sed command + sed -i "s/version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" build.gradle.kts +else + # Unix-like systems + sed -i "" "s/version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" build.gradle.kts +fi + +# Add the modified build.gradle.kts to the commit +git add build.gradle.kts + +# Print the version change with type +echo "Bumped version from $CURRENT_VERSION to $NEW_VERSION" \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48ad17e3..49e220d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -143,16 +143,22 @@ jobs: name: build-artifacts path: ./ - - name: Create directory structure + - name: Debug downloaded files + run: | + echo "Current directory contents:" + ls -la + echo "Find all jar files:" + find . -name "*.jar" + + - name: Create directory structure and move artifacts run: | mkdir -p modules/federation-server/build/libs/ mkdir -p modules/admin-server/build/libs/ - mv federation-server-*.jar modules/federation-server/build/libs/ - mv admin-server-*.jar modules/admin-server/build/libs/ + find . -maxdepth 1 -name "federation-server-*.jar" -exec mv {} modules/federation-server/build/libs/ \; + find . -maxdepth 1 -name "admin-server-*.jar" -exec mv {} modules/admin-server/build/libs/ \; - name: List downloaded artifacts run: ls -R modules/*/build/libs/ - - name: Log in to Docker Hub uses: docker/login-action@v3 with: diff --git a/build.gradle.kts b/build.gradle.kts index 60970c2f..d2d63a05 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,59 @@ import java.io.ByteArrayOutputStream +tasks.register("installGitHooks", Copy::class) { + group = "git hooks" + description = "Installs git hooks from .githooks directory" + + val sourceDir = file(".githooks") + val targetDir = file(".git/hooks") + + from(sourceDir) { + include("**/*") + } + into(targetDir) + fileMode = 0b111101101 // 755 in octal: rwxr-xr-x + + inputs.dir(sourceDir) + outputs.dir(targetDir) + + doFirst { + sourceDir.mkdirs() + targetDir.mkdirs() + + val preCommitFile = sourceDir.resolve("pre-commit") + if (!preCommitFile.exists()) { + throw GradleException("pre-commit hook file not found in .githooks directory") + } + + println("Installing Git hooks...") + } + + outputs.upToDateWhen { + val preCommitSource = sourceDir.resolve("pre-commit") + val preCommitTarget = targetDir.resolve("pre-commit") + + if (!preCommitTarget.exists()) { + return@upToDateWhen false + } + + val isUpToDate = preCommitSource.lastModified() <= preCommitTarget.lastModified() && + preCommitSource.length() == preCommitTarget.length() + + isUpToDate + } +} + +tasks.matching { it.name == "build" }.configureEach { + dependsOn("installGitHooks") +} + +gradle.projectsEvaluated { + tasks.named("prepareKotlinBuildScriptModel").configure { + dependsOn("installGitHooks") + } +} + + plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidLibrary) apply false @@ -39,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.3.0-SNAPSHOT" + version = "0.3.2-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects diff --git a/init.gradle.kts b/init.gradle.kts new file mode 100644 index 00000000..08bb49c1 --- /dev/null +++ b/init.gradle.kts @@ -0,0 +1,25 @@ +// This script runs during Gradle initialization +gradle.projectsLoaded { + rootProject.afterEvaluate { + // Check if .git directory exists (we're in a Git repo) + if (file(".git").exists()) { + // Create .githooks directory if it doesn't exist + file(".githooks").mkdirs() + + // Copy the pre-commit hook if it exists + val preCommitHook = file(".githooks/pre-commit") + if (preCommitHook.exists()) { + // Copy hook to .git/hooks + file(".git/hooks").mkdirs() + preCommitHook.copyTo(file(".git/hooks/pre-commit"), overwrite = true) + + // Make the hook executable on Unix-like systems + if (!System.getProperty("os.name").lowercase().contains("windows")) { + Runtime.getRuntime().exec("chmod +x ${file(".git/hooks/pre-commit").absolutePath}") + } + + println("Git pre-commit hook installed successfully") + } + } + } +} \ No newline at end of file From 0f964424eb8c05510697d5d512d4c0987c2c16f5 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 13:51:41 +0100 Subject: [PATCH 09/16] fix: move built jars to a place Dockerfile expects --- .github/workflows/ci.yml | 8 +++++--- build.gradle.kts | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49e220d3..c9993bd3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,9 +154,11 @@ jobs: run: | mkdir -p modules/federation-server/build/libs/ mkdir -p modules/admin-server/build/libs/ - find . -maxdepth 1 -name "federation-server-*.jar" -exec mv {} modules/federation-server/build/libs/ \; - find . -maxdepth 1 -name "admin-server-*.jar" -exec mv {} modules/admin-server/build/libs/ \; - + mv ./federation-server/build/libs/federation-server-*.jar modules/federation-server/build/libs/ + mv ./admin-server/build/libs/admin-server-*.jar modules/admin-server/build/libs/ + # Ensure artifacts are accessible + chmod 644 modules/federation-server/build/libs/*.jar + chmod 644 modules/admin-server/build/libs/*.jar - name: List downloaded artifacts run: ls -R modules/*/build/libs/ - name: Log in to Docker Hub diff --git a/build.gradle.kts b/build.gradle.kts index d2d63a05..3c245f54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.3.2-SNAPSHOT" + version = "0.3.3-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From 40c8a424628ec3d27c20678010ab75bb16c18c5c Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 14:13:50 +0100 Subject: [PATCH 10/16] feat: tag and push to docker hub --- .github/workflows/ci.yml | 96 +++++++++------------------------------- build.gradle.kts | 2 +- 2 files changed, 23 insertions(+), 75 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9993bd3..fb40b8bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,6 @@ jobs: success: ${{ steps.build.outcome == 'success' }} strategy: matrix: - # Removed windows, because build failing with docker network. "bridge" network driver is not supported for Windows containers - # os: [ ubuntu-latest, windows-latest ] os: [ ubuntu-latest ] runs-on: ${{ matrix.os }} steps: @@ -56,15 +54,15 @@ jobs: path: | modules/federation-server/build/libs/federation-server-*.jar modules/admin-server/build/libs/admin-server-*.jar - auto-tag: + docker-publish: needs: gradle runs-on: ubuntu-latest - outputs: - version: ${{ steps.get_version_info.outputs.new_version }} if: github.event_name == 'repository_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || (github.event_name == 'push' && needs.gradle.outputs.success == 'true') + timeout-minutes: 20 permissions: contents: write actions: write + packages: write steps: - name: Checkout repository uses: actions/checkout@v4 @@ -84,83 +82,46 @@ jobs: else BRANCH_NAME="${GITHUB_REF#refs/heads/}" fi - if [[ $BRANCH_NAME == "develop" ]]; then - PREFIX="dev" - elif [[ $BRANCH_NAME == "main" ]]; then - PREFIX="main" - elif [[ $BRANCH_NAME == feature/* ]]; then - PREFIX="feat" - elif [[ $BRANCH_NAME == hotfix/* ]]; then - PREFIX="fix" - elif [[ $BRANCH_NAME == release/* ]]; then - PREFIX="rel" - else - PREFIX="build" - fi GRADLE_VERSION=$(grep 'version = ' build.gradle.kts | sed 's/.*version = "\(.*\)".*/\1/') GRADLE_VERSION=${GRADLE_VERSION%-SNAPSHOT} COMMIT_SHA=$(git rev-parse --short HEAD) PR_NUMBER=${{ github.event.pull_request.number }} - if [[ -n $PR_NUMBER ]]; then - NEW_VERSION="v${GRADLE_VERSION}-${PREFIX}.pr${PR_NUMBER}.${COMMIT_SHA}" + + if [[ $BRANCH_NAME == "main" ]]; then + NEW_VERSION="v${GRADLE_VERSION}" + elif [[ $BRANCH_NAME == "develop" ]]; then + NEW_VERSION="v${GRADLE_VERSION}-beta.${COMMIT_SHA}" + elif [[ $BRANCH_NAME == release/* ]]; then + NEW_VERSION="v${GRADLE_VERSION}-rc.${COMMIT_SHA}" else - NEW_VERSION="v${GRADLE_VERSION}-${PREFIX}.${COMMIT_SHA}" + SAFE_BRANCH=$(echo "${BRANCH_NAME}" | sed 's/[^a-zA-Z0-9]/-/g') + if [[ -n $PR_NUMBER ]]; then + NEW_VERSION="v${GRADLE_VERSION}-alpha.pr${PR_NUMBER}.${COMMIT_SHA}" + else + NEW_VERSION="v${GRADLE_VERSION}-alpha.${SAFE_BRANCH}.${COMMIT_SHA}" + fi fi echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT git tag -a ${NEW_VERSION} -m "Release ${NEW_VERSION}" git push origin ${NEW_VERSION} - env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - docker-publish: - needs: [ gradle, auto-tag ] - if: needs.gradle.outputs.success == 'true' - runs-on: ubuntu-latest - timeout-minutes: 20 - permissions: - contents: read - packages: write - steps: - - name: Debug Event - run: | - echo "Event name: ${{ github.event_name }}" - echo "Ref type: ${{ github.ref_type }}" - echo "Ref: ${{ github.ref }}" - echo "SHA: ${{ github.sha }}" - echo "Base ref: ${{ github.base_ref }}" - echo "Head ref: ${{ github.head_ref }}" - echo "Workflow ref: ${{ github.workflow_ref }}" - - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Download build artifacts uses: actions/download-artifact@v4 with: name: build-artifacts path: ./ - - name: Debug downloaded files - run: | - echo "Current directory contents:" - ls -la - echo "Find all jar files:" - find . -name "*.jar" - - name: Create directory structure and move artifacts run: | mkdir -p modules/federation-server/build/libs/ mkdir -p modules/admin-server/build/libs/ mv ./federation-server/build/libs/federation-server-*.jar modules/federation-server/build/libs/ mv ./admin-server/build/libs/admin-server-*.jar modules/admin-server/build/libs/ - # Ensure artifacts are accessible chmod 644 modules/federation-server/build/libs/*.jar chmod 644 modules/admin-server/build/libs/*.jar - - name: List downloaded artifacts - run: ls -R modules/*/build/libs/ + - name: Log in to Docker Hub uses: docker/login-action@v3 with: @@ -169,19 +130,15 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 + - name: Extract metadata (federation-server) id: meta-federation uses: docker/metadata-action@v5 with: images: sphereon/openid-federation-server tags: | - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - type=raw,value=${{ needs.auto-tag.outputs.version }} - type=ref,event=branch - type=sha,format=short - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} + type=raw,value=${{ steps.get_version_info.outputs.new_version }} + type=raw,value=latest,enable={{is_default_branch}} - name: Build and push federation-server uses: docker/build-push-action@v5 @@ -194,23 +151,14 @@ jobs: cache-from: | type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server:latest type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest - cache-to: | - type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-server:latest,mode=max - type=registry,ref=${{ secrets.DOCKERHUB_USERNAME }}/openid-federation-base:latest,mode=max - - name: Extract metadata (admin-server) id: meta-admin uses: docker/metadata-action@v5 with: images: sphereon/openid-federation-admin-server tags: | - type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} - type=raw,value=${{ needs.auto-tag.outputs.version }} - type=ref,event=branch - type=sha,format=short - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} + type=raw,value=${{ steps.get_version_info.outputs.new_version }} + type=raw,value=latest,enable={{is_default_branch}} - name: Build and push admin-server uses: docker/build-push-action@v5 diff --git a/build.gradle.kts b/build.gradle.kts index 3c245f54..06cd832f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.3.3-SNAPSHOT" + version = "0.3.14-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From 1144cf0da80d16410bf0d64145380c51473caca6 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 17:17:16 +0100 Subject: [PATCH 11/16] fix: semver compatibility --- .github/workflows/ci.yml | 4 ++-- build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb40b8bf..b537c48a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,7 @@ jobs: with: images: sphereon/openid-federation-server tags: | - type=raw,value=${{ steps.get_version_info.outputs.new_version }} + type=semver,value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} - name: Build and push federation-server @@ -157,7 +157,7 @@ jobs: with: images: sphereon/openid-federation-admin-server tags: | - type=raw,value=${{ steps.get_version_info.outputs.new_version }} + type=semver,value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} - name: Build and push admin-server diff --git a/build.gradle.kts b/build.gradle.kts index 06cd832f..ceaed703 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.3.14-SNAPSHOT" + version = "0.4.0-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From b3b0a21073d6151f4cf4c19ea41b1e695e952560 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 17:26:17 +0100 Subject: [PATCH 12/16] fix: semver compatibility --- .github/workflows/ci.yml | 9 ++++++--- build.gradle.kts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b537c48a..6597acce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,7 +137,9 @@ jobs: with: images: sphereon/openid-federation-server tags: | - type=semver,value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{major}},value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} - name: Build and push federation-server @@ -157,9 +159,10 @@ jobs: with: images: sphereon/openid-federation-admin-server tags: | - type=semver,value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version_info.outputs.new_version }} + type=semver,pattern={{major}},value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} - - name: Build and push admin-server uses: docker/build-push-action@v5 with: diff --git a/build.gradle.kts b/build.gradle.kts index ceaed703..53300bb0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.4.0-SNAPSHOT" + version = "0.4.1-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From f540a5902eb83e5f7c05d8779932d8d535fd9c86 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 18:48:18 +0100 Subject: [PATCH 13/16] fix: versioning docker tag pattern --- .github/workflows/ci.yml | 14 ++++++++------ build.gradle.kts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6597acce..9ff07494 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -137,10 +137,11 @@ jobs: with: images: sphereon/openid-federation-server tags: | - type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} - type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version_info.outputs.new_version }} - type=semver,pattern={{major}},value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+\.\d+\.\d+)$,group=1,value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+\.\d+)\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+)\.\d+\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - name: Build and push federation-server uses: docker/build-push-action@v5 @@ -159,10 +160,11 @@ jobs: with: images: sphereon/openid-federation-admin-server tags: | - type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} - type=semver,pattern={{major}}.{{minor}},value=${{ steps.get_version_info.outputs.new_version }} - type=semver,pattern={{major}},value=${{ steps.get_version_info.outputs.new_version }} type=raw,value=latest,enable={{is_default_branch}} + type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+\.\d+\.\d+)$,group=1,value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+\.\d+)\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} + type=match,pattern=v(\d+)\.\d+\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - name: Build and push admin-server uses: docker/build-push-action@v5 with: diff --git a/build.gradle.kts b/build.gradle.kts index 53300bb0..f7546ade 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.4.1-SNAPSHOT" + version = "0.4.2-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From d8126e49c9c7c56b416e962eac14c2cf2aa4b999 Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 18:58:11 +0100 Subject: [PATCH 14/16] chore: remove wrong reference --- README.md | 1 - build.gradle.kts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ad8fad68..77f348e7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@
-[![Snyk Security](https://snyk.io/test/github/Sphereon-Opensource/OpenID-Federation/badge.svg)](https://snyk.io/test/github/Sphereon-Opensource/OpenID-Federation) [![Docker Pulls](https://img.shields.io/docker/pulls/sphereon/openid-federation-server.svg)](https://hub.docker.com/r/sphereon/openid-federation-server) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) diff --git a/build.gradle.kts b/build.gradle.kts index f7546ade..afcf9b3d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.4.2-SNAPSHOT" + version = "0.4.3-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From 15f77f4efb41962dc618c6bc048312ed4ef727ea Mon Sep 17 00:00:00 2001 From: John Melati Date: Thu, 16 Jan 2025 20:29:06 +0100 Subject: [PATCH 15/16] fix: leave only semver active --- .github/workflows/ci.yml | 6 ------ build.gradle.kts | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ff07494..14a5e543 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,9 +139,6 @@ jobs: tags: | type=raw,value=latest,enable={{is_default_branch}} type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+\.\d+\.\d+)$,group=1,value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+\.\d+)\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+)\.\d+\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - name: Build and push federation-server uses: docker/build-push-action@v5 @@ -162,9 +159,6 @@ jobs: tags: | type=raw,value=latest,enable={{is_default_branch}} type=semver,pattern={{version}},value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+\.\d+\.\d+)$,group=1,value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+\.\d+)\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - type=match,pattern=v(\d+)\.\d+\.\d+,group=1,value=${{ steps.get_version_info.outputs.new_version }} - name: Build and push admin-server uses: docker/build-push-action@v5 with: diff --git a/build.gradle.kts b/build.gradle.kts index afcf9b3d..16a73466 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.4.3-SNAPSHOT" + version = "0.4.3.1-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects From bb7f483a440f24966505ce472b649ea32d60ee66 Mon Sep 17 00:00:00 2001 From: John Melati Date: Fri, 17 Jan 2025 10:01:54 +0100 Subject: [PATCH 16/16] fix: only deploy to dockerhub on main and develop --- .github/workflows/ci.yml | 2 +- build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14a5e543..cd9eb8f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: docker-publish: needs: gradle runs-on: ubuntu-latest - if: github.event_name == 'repository_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || (github.event_name == 'push' && needs.gradle.outputs.success == 'true') + if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') && (github.event_name == 'repository_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || (github.event_name == 'push' && needs.gradle.outputs.success == 'true')) timeout-minutes: 20 permissions: contents: write diff --git a/build.gradle.kts b/build.gradle.kts index 16a73466..3e526485 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,7 +93,7 @@ fun getNpmVersion(): String { allprojects { group = "com.sphereon.oid.fed" - version = "0.4.3.1-SNAPSHOT" + version = "0.4.4-SNAPSHOT" val npmVersion by extra { getNpmVersion() } // Common repository configuration for all projects