Compare commits
1 Commits
working-po
...
db7bcfa60a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db7bcfa60a |
@@ -1,9 +0,0 @@
|
||||
services:
|
||||
runner:
|
||||
image: docker.io/gitea/act_runner:latest
|
||||
environment:
|
||||
GITEA_INSTANCE_URL: "http://192.168.0.25:3000"
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: "IfowioCs4PedXyRJMnedDVCXkRHjyDrZv1sdvaif"
|
||||
GITEA_RUNNER_NAME: "runner-1"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
@@ -1,50 +0,0 @@
|
||||
name: Build and Deploy Kotlin gradle Application
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- working-poc
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build backend docker image
|
||||
run: |
|
||||
sudo /usr/bin/docker build -t gitea-workshop-app -f ./Dockerfile-backend . --no-cache
|
||||
|
||||
- name: Extract backend docker image into archive
|
||||
run: |
|
||||
sudo /usr/bin/docker save gitea-workshop-app:latest -o ./gitea-workshop-app.tar
|
||||
|
||||
- name: Transfer artifacts to remote server
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
|
||||
chmod 400 ~/.ssh/id_rsa
|
||||
scp -o StrictHostKeyChecking=no -P $REMOTE_PORT ./gitea-workshop-app.tar $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
|
||||
scp -o StrictHostKeyChecking=no -P $REMOTE_PORT ./docker-compose.yml $REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH
|
||||
|
||||
- name: Launch application onto remote server
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
|
||||
REMOTE_HOST: ${{ secrets.PROD_REMOTE_HOST }}
|
||||
REMOTE_USER: ${{ secrets.PROD_REMOTE_USER }}
|
||||
REMOTE_PORT: ${{ secrets.PROD_REMOTE_PORT }}
|
||||
REMOTE_PATH: ${{ secrets.PROD_REMOTE_PATH }}
|
||||
run: |
|
||||
ssh -o StrictHostKeyChecking=no $REMOTE_HOST -l $REMOTE_USER -p $REMOTE_PORT << EOC
|
||||
cd $REMOTE_PATH
|
||||
sudo /usr/bin/docker load < $REMOTE_PATH/gitea-workshop-app.tar
|
||||
sudo /usr/bin/docker compose down
|
||||
sudo /usr/bin/docker compose up --detach
|
||||
EOC
|
||||
@@ -1,15 +0,0 @@
|
||||
FROM gradle:8.12.1-jdk21 AS builder
|
||||
COPY ./gradlew /app/
|
||||
COPY ./build.gradle.kts /app/
|
||||
COPY ./settings.gradle.kts /app/
|
||||
COPY ./demo-application /app/demo-application
|
||||
COPY ./demo-domain /app/demo-domain
|
||||
COPY ./demo-exposition /app/demo-exposition
|
||||
COPY ./demo-infrastructure /app/demo-infrastructure
|
||||
COPY ./demo-launcher /app/demo-launcher
|
||||
WORKDIR /app
|
||||
RUN gradle build jar
|
||||
|
||||
FROM eclipse-temurin:21-jre-alpine AS final
|
||||
COPY --from=builder /app/demo-launcher/build/libs/demo-launcher.jar /app/demo-launcher.jar
|
||||
CMD ["java", "-jar", "/app/demo-launcher.jar"]
|
||||
@@ -1,11 +0,0 @@
|
||||
meta {
|
||||
name: Debug
|
||||
type: http
|
||||
seq: 3
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{url}}/api/debug/info
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
meta {
|
||||
name: Get all products
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
get {
|
||||
url: {{url}}/api/products
|
||||
body: none
|
||||
auth: none
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "GiteaActionsWorkshop",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
vars {
|
||||
url: http://localhost:8080
|
||||
}
|
||||
@@ -1,6 +1,13 @@
|
||||
object Versions {
|
||||
const val springBoot = "3.4.3"
|
||||
const val springDependencyManagement = "1.1.7"
|
||||
const val kotlinJvm = "1.9.25"
|
||||
const val kotlinPluginSpring = "1.9.25"
|
||||
}
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version "2.1.20"
|
||||
kotlin("plugin.spring") version "2.1.20"
|
||||
kotlin("jvm") version "1.9.25"
|
||||
kotlin("plugin.spring") version "1.9.25"
|
||||
id("io.spring.dependency-management") version "1.1.7"
|
||||
}
|
||||
|
||||
@@ -26,14 +33,14 @@ subprojects {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform("org.springframework.boot:spring-boot-dependencies:3.4.4"))
|
||||
implementation("com.michael-bull.kotlin-result:kotlin-result:2.0.1")
|
||||
implementation(platform("org.springframework.boot:spring-boot-dependencies:${Versions.springBoot}"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom("org.springframework.boot:spring-boot-dependencies:3.4.4")
|
||||
mavenBom("org.springframework.boot:spring-boot-dependencies:${Versions.springBoot}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("io.spring.dependency-management") version "1.1.7"
|
||||
id("java")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
implementation(project(":demo-domain"))
|
||||
implementation("org.springframework:spring-context")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
|
||||
implementation("com.michael-bull.kotlin-result:kotlin-result-coroutines:2.0.1")
|
||||
}
|
||||
@@ -1,45 +1,12 @@
|
||||
package com.example.demo.application.product
|
||||
|
||||
import com.example.demo.domain.core.error.FunctionalError
|
||||
import com.example.demo.domain.product.inputport.ProductInputPort
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import com.example.demo.domain.product.model.ProductType
|
||||
import com.example.demo.domain.product.outputport.ProductOutputPort
|
||||
import com.github.michaelbull.result.*
|
||||
import com.github.michaelbull.result.coroutines.coroutineBinding
|
||||
import com.example.demo.domain.product.port.ProductPort
|
||||
import org.springframework.stereotype.Service
|
||||
import java.util.*
|
||||
|
||||
@Service
|
||||
class ProductUseCases(
|
||||
private val productOutputPort: ProductOutputPort
|
||||
) : ProductInputPort {
|
||||
override suspend fun getAll(): Result<List<Product>, FunctionalError> = productOutputPort.getAll()
|
||||
.mapError { FunctionalError(it.message) }
|
||||
|
||||
// override suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError> {
|
||||
// if (name.isBlank()) {
|
||||
// return Err(FunctionalError("Product name should be set."))
|
||||
// }
|
||||
//
|
||||
// val newProduct = Product(id = UUID.randomUUID(), name, type)
|
||||
// return productOutputPort.save(newProduct)
|
||||
// .mapError { FunctionalError(it.message) }
|
||||
// .map { newProduct }
|
||||
// }
|
||||
|
||||
override suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError> = coroutineBinding {
|
||||
validateName(name).bind()
|
||||
|
||||
val newProduct = Product(id = UUID.randomUUID(), name, type)
|
||||
productOutputPort.save(newProduct)
|
||||
.mapError { FunctionalError(it.message) }
|
||||
.map { newProduct }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private fun validateName(name: String): Result<Unit, FunctionalError> = when {
|
||||
name.isBlank() -> Err(FunctionalError("Product name should be set."))
|
||||
else -> Ok(Unit)
|
||||
}
|
||||
private val productPort: ProductPort
|
||||
) {
|
||||
fun getAll(): List<Product> = productPort.getAll()
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("java")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.example.demo.domain.core.error
|
||||
|
||||
open class DomainError(val message: String)
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.example.demo.domain.core.error
|
||||
|
||||
class FunctionalError(message: String) : DomainError(message)
|
||||
@@ -1,3 +0,0 @@
|
||||
package com.example.demo.domain.core.error
|
||||
|
||||
class TechnicalError(message: String) : DomainError(message)
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.example.demo.domain.product.inputport
|
||||
|
||||
import com.example.demo.domain.core.error.FunctionalError
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import com.example.demo.domain.product.model.ProductType
|
||||
import com.github.michaelbull.result.Result
|
||||
|
||||
interface ProductInputPort {
|
||||
suspend fun create(name: String, type: ProductType): Result<Product, FunctionalError>
|
||||
suspend fun getAll(): Result<List<Product>, FunctionalError>
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.example.demo.domain.product.outputport
|
||||
|
||||
import com.example.demo.domain.core.error.TechnicalError
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import com.github.michaelbull.result.Result
|
||||
import java.util.UUID
|
||||
|
||||
interface ProductOutputPort {
|
||||
fun getById(id: UUID): Product?
|
||||
|
||||
suspend fun getAll(): Result<List<Product>, TechnicalError>
|
||||
|
||||
fun save(product: Product): Result<Unit, TechnicalError>
|
||||
|
||||
fun deleteById(id: UUID)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.example.demo.domain.product.port
|
||||
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import java.util.UUID
|
||||
|
||||
interface ProductPort {
|
||||
fun getById(id: UUID): Product?
|
||||
|
||||
fun getAll(): List<Product>
|
||||
|
||||
fun save(product: Product)
|
||||
|
||||
fun deleteById(id: UUID)
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("io.spring.dependency-management") version "1.1.7"
|
||||
id("java")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -9,7 +10,4 @@ dependencies {
|
||||
implementation(project(":demo-domain"))
|
||||
implementation("org.springframework:spring-context")
|
||||
implementation("org.springframework:spring-web")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||
implementation("com.michael-bull.kotlin-result:kotlin-result-coroutines:2.0.1")
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.3")
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.example.demo.exposition.debug
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/debug")
|
||||
class DebugController {
|
||||
@GetMapping("/info")
|
||||
fun debug(): String = """
|
||||
{
|
||||
"message": "Hello world!"
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
@@ -1,28 +1,16 @@
|
||||
package com.example.demo.exposition.product
|
||||
|
||||
import com.example.demo.domain.core.error.FunctionalError
|
||||
import com.example.demo.domain.product.inputport.ProductInputPort
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import com.example.demo.exposition.product.model.ProductCreationRequest
|
||||
import com.example.demo.application.product.ProductUseCases
|
||||
import com.example.demo.exposition.product.model.ProductDto
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.github.michaelbull.result.map
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/products")
|
||||
class ProductController(
|
||||
private val productInputPort: ProductInputPort
|
||||
private val productUseCases: ProductUseCases
|
||||
) {
|
||||
@GetMapping
|
||||
suspend fun getAll(): Result<List<ProductDto>, FunctionalError> = productInputPort.getAll()
|
||||
.map { products -> products.map(::ProductDto) }
|
||||
|
||||
@PostMapping
|
||||
suspend fun create(@RequestBody request: ProductCreationRequest): Result<Product, FunctionalError> =
|
||||
productInputPort.create(request.name, request.type)
|
||||
fun getAll(): List<ProductDto> = productUseCases.getAll().map(::ProductDto)
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.example.demo.exposition.product.core.advice
|
||||
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
|
||||
@RestControllerAdvice
|
||||
class ResultControllerAdvice {
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package com.example.demo.exposition.product.model
|
||||
|
||||
import com.example.demo.domain.product.model.ProductType
|
||||
|
||||
data class ProductCreationRequest(
|
||||
val name: String,
|
||||
val type: ProductType
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("io.spring.dependency-management") version "1.1.7"
|
||||
id("java")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -8,6 +9,4 @@ dependencies {
|
||||
implementation(project(":demo-application"))
|
||||
implementation(project(":demo-domain"))
|
||||
implementation("org.springframework:spring-context")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||
implementation("com.michael-bull.kotlin-result:kotlin-result-coroutines:2.0.1")
|
||||
}
|
||||
@@ -1,18 +1,15 @@
|
||||
package com.example.demo.infrastructure.product
|
||||
|
||||
import com.example.demo.domain.core.error.TechnicalError
|
||||
import com.example.demo.domain.product.model.Product
|
||||
import com.example.demo.domain.product.model.ProductType.LIQUID
|
||||
import com.example.demo.domain.product.model.ProductType.SOLID
|
||||
import com.example.demo.domain.product.outputport.ProductOutputPort
|
||||
import com.github.michaelbull.result.Ok
|
||||
import com.github.michaelbull.result.Result
|
||||
import com.example.demo.domain.product.port.ProductPort
|
||||
import org.springframework.stereotype.Component
|
||||
import java.util.*
|
||||
|
||||
@Component
|
||||
class ProductInMemoryAdapter : ProductOutputPort {
|
||||
private val products = mutableListOf(
|
||||
class ProductInMemoryAdapter : ProductPort {
|
||||
private val products = mutableListOf<Product>(
|
||||
Product(
|
||||
id = UUID.randomUUID(),
|
||||
name = "Banana x5",
|
||||
@@ -27,11 +24,15 @@ class ProductInMemoryAdapter : ProductOutputPort {
|
||||
|
||||
override fun getById(id: UUID): Product? = products.find { product -> product.id == id }
|
||||
|
||||
override suspend fun getAll(): Result<List<Product>, TechnicalError> = Ok(products)
|
||||
override fun getAll(): List<Product> = products
|
||||
|
||||
override fun save(product: Product): Result<Unit, TechnicalError> {
|
||||
products += product
|
||||
return Ok(Unit)
|
||||
override fun save(product: Product) {
|
||||
if (getById(product.id) == null) {
|
||||
products.add(product)
|
||||
} else {
|
||||
deleteById(product.id)
|
||||
save(product)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteById(id: UUID) {
|
||||
|
||||
@@ -2,21 +2,18 @@ plugins {
|
||||
kotlin("jvm")
|
||||
id("org.springframework.boot") version "3.4.3"
|
||||
id("io.spring.dependency-management") version "1.1.7"
|
||||
id("java")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib"))
|
||||
implementation(kotlin("reflect"))
|
||||
implementation(project(":demo-domain"))
|
||||
implementation(project(":demo-application"))
|
||||
implementation(project(":demo-infrastructure"))
|
||||
implementation(project(":demo-exposition"))
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
}
|
||||
|
||||
springBoot {
|
||||
mainClass = "com.example.demo.launcher.ApplicationLauncherKt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
services:
|
||||
backend:
|
||||
image: gitea-workshop-app:latest
|
||||
container_name: gitea-workshop-app-backend
|
||||
ports:
|
||||
- "50000:8080"
|
||||
restart: always
|
||||
networks:
|
||||
- "gitea-workshop"
|
||||
|
||||
networks:
|
||||
gitea-workshop:
|
||||
Reference in New Issue
Block a user