Skip to content

Commit

Permalink
Add Heroku-aware database config
Browse files Browse the repository at this point in the history
  • Loading branch information
matchilling committed Jun 9, 2024
1 parent 8b3c8ad commit 143a8e1
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 0 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Build

on:
workflow_call:
inputs:
enable-checks:
default: true
description: "Enable validations"
required: false
type: boolean
version:
required: true
type: string

env:
JAVA_DISTRIBUTION: "corretto"
JAVA_VERSION: "17"

jobs:
build:
name: Validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.version }}

- name: Setup JDK
uses: actions/setup-java@v4
with:
cache: 'gradle'
distribution: ${{ env.JAVA_DISTRIBUTION }}
java-version: ${{ env.JAVA_VERSION }}

- name: Run validations
if: ${{ inputs.enable-checks }}
run: ./gradlew test
22 changes: 22 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Main

on:
push:
branches: [ master ]
workflow_dispatch:
workflow_call:
inputs:
version:
required: false
type: string

permissions:
id-token: write
contents: read
pull-requests: write

jobs:
build:
uses: ./.github/workflows/build.yml
with:
version: ${{ github.sha }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.tronalddump.app.configuration;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableJpaRepositories(basePackages = "io.tronalddump")
@EnableTransactionManagement
public class DataSourceConfiguration {

@Bean
public DataSource dataSource(DataSourceProperties dataSourceProperties) {
return DataSourceBuilder.create()
.driverClassName(dataSourceProperties.getDriverClassName())
.password(dataSourceProperties.getPassword())
.type(HikariDataSource.class)
.url(dataSourceProperties.getUrl())
.username(dataSourceProperties.getUsername())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.tronalddump.app.configuration;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "spring.datasource")
public interface DataSourceProperties {

String getDriverClassName();

String getPassword();

String getUrl();

String getUsername();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.tronalddump.app.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

@ConditionalOnProperty(prefix = "spring.datasource", name = "url")
@Configuration
public class DefaultDataSourceProperties implements DataSourceProperties {

private final String driverClassName;
private final String password;
private final String url;
private final String username;

public DefaultDataSourceProperties(
@Value("${spring.datasource.driver-class-name}") String driverClassName,
@Value("${spring.datasource.password}") String password,
@Value("${spring.datasource.url}") String url,
@Value("${spring.datasource.username}") String username
) {
this.driverClassName = driverClassName;
this.password = password;
this.url = url;
this.username = username;
}

@Override
public String getDriverClassName() {
return this.driverClassName;
}

@Override
public String getPassword() {
return this.password;
}

@Override
public String getUrl() {
return this.url;
}

@Override
public String getUsername() {
return this.username;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.tronalddump.app.configuration;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

import java.net.URI;

@ConditionalOnProperty(prefix = "spring.datasource", name = "uri")
@Configuration
public class HerokuDataSourceProperties implements DataSourceProperties {

private static final String SCHEMA_POSTGRESQL = "postgresql";

private final String driverClassName;
private final String password;
private final String url;
private final String username;

public HerokuDataSourceProperties(
@Value("${spring.datasource.driver-class-name}") String driverClassName,
@Value("${spring.datasource.uri}") String uniformResourceIdentifier
) {
URI uri = URI.create(uniformResourceIdentifier);

String[] userInfo = uri.getUserInfo().split(":");

this.driverClassName = driverClassName;
this.password = userInfo[1];
this.url = String.format(
"jdbc:%s://%s:%s/%s",
this.scheme(uri),
uri.getHost().replace("/", ""),
uri.getPort(),
uri.getPath().replace("/", "")
);
this.username = userInfo[0];
}

private String scheme(URI uri) {
if ("postgres".compareToIgnoreCase(uri.getScheme()) == 0) {
return SCHEMA_POSTGRESQL;
}

throw new RuntimeException(
String.format("Unsupported schema %s given", uri.getScheme())
);
}

@Override
public String getDriverClassName() {
return this.driverClassName;
}

@Override
public String getPassword() {
return this.password;
}

@Override
public String getUrl() {
return this.url;
}

@Override
public String getUsername() {
return this.username;
}
}
12 changes: 12 additions & 0 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
application.base_url_api = api.tronalddump.io
application.base_url_ui = www.tronalddump.io

# Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
#spring.datasource.url = jdbc:postgresql://localhost:5432/tronald
#spring.datasource.username = postgres
#spring.datasource.password = postgres
spring.datasource.uri = ${DATABASE_URL}

# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update

# Local
slack.oauth.client_id = xxxxxxxxxxx.xxxxxxxxxxxx
slack.oauth.client_secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Expand Down

0 comments on commit 143a8e1

Please sign in to comment.