Skip to content

Commit

Permalink
ci: add ci (#16)
Browse files Browse the repository at this point in the history
* ci: add ci for frontend

* chore: lint the job service

* ci: jobs service

* test: fix api gateway tests

* ci: refactor backend ci

* feat: improve Docker flow

* ci: handle pushed tags

* chore: update KtLint Gradle plugin

* chore: run linter

* ci: refactor the frontend lint flow

---------

Signed-off-by: Mauran <[email protected]>
Co-authored-by: Mauran <[email protected]>
  • Loading branch information
Kuruyia and thomas-mauran authored Nov 19, 2023
1 parent 0d44f6a commit 63f3437
Show file tree
Hide file tree
Showing 29 changed files with 391 additions and 148 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/flow_backend_build_push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Build & push backend container image

on:
workflow_call:
inputs:
service-build-context-path:
description: The path to the context to use when building the container image
default: ./backend
required: false
type: string
service-name:
description: The name of the service to build
required: true
type: string
push-image:
description: Whether to push the container image to the registry
default: false
required: false
type: boolean
image-tags:
description: The tags to pass to the "docker/metadata-action" action
required: true
type: string

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- name: Setup Docker buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/metadata-action@v5
name: Extract metadata (tags, labels) for Docker
id: meta
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ inputs.service-name }}
tags: ${{ inputs.image-tags }}
flavor: latest=false

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
push: ${{ inputs.push-image }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
context: "{{ defaultContext }}:${{ inputs.service-build-context-path }}"
build-args: SERVICE_NAME=${{ inputs.service-name }}
34 changes: 34 additions & 0 deletions .github/workflows/flow_backend_lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Lint backend

on:
workflow_call:
inputs:
gradle-root-project-path:
description: The path to the Gradle root project
default: ./backend
required: false
type: string

jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.gradle-root-project-path }}
steps:
- uses: actions/checkout@v4

- name: Use Java
uses: actions/setup-java@v3
with:
java-version: 17
distribution: corretto

- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Lint Kotlin
run: ./gradlew ktlintCheck

- name: Execute Gradle build
run: ./gradlew build -x test
38 changes: 38 additions & 0 deletions .github/workflows/flow_front_lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Lint frontend

on:
workflow_call:
inputs:
app-dir-path:
description: The directory where the frontend application is stored
default: ./front
required: false
type: string

jobs:
lint:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ${{ inputs.app-dir-path }}
steps:
- uses: actions/checkout@v4

- name: Use Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
cache-dependency-path: ${{ inputs.app-dir-path }}

- name: Install dependencies
run: npm ci

- name: Run Prettier
run: npm run prettier:check

- name: Run ESLint
run: npm run eslint:check

- name: Run TypeScript
run: npm run typescript:check
43 changes: 43 additions & 0 deletions .github/workflows/on_push_pr_main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Push & PR to the main branch

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

jobs:
lint_frontend:
name: Lint frontend
uses: ./.github/workflows/flow_front_lint.yml

lint_backend:
name: Lint backend
uses: ./.github/workflows/flow_backend_lint.yml

build_api_gateway:
name: Build & push Docker image of the API gateway
needs: lint_backend
uses: ./.github/workflows/flow_backend_build_push.yml
with:
service-name: api_gateway
push-image: ${{ github.event_name != 'pull_request' }}
image-tags: |
type=sha
type=ref,event=branch
type=edge,branch=main
build_jobs_service:
name: Build & push Docker image of the Jobs service
needs: lint_backend
uses: ./.github/workflows/flow_backend_build_push.yml
with:
service-name: jobs
push-image: ${{ github.event_name != 'pull_request' }}
image-tags: |
type=sha
type=ref,event=branch
type=edge
29 changes: 29 additions & 0 deletions .github/workflows/on_semver_tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Push a semver tag

on:
push:
tags:
- v*.*.*

jobs:
build_api_gateway:
name: Build & push Docker image of the API gateway
uses: ./.github/workflows/flow_backend_build_push.yml
with:
service-name: api_gateway
push-image: ${{ github.event_name != 'pull_request' }}
image-tags: |
type=sha
type=semver,pattern={{version}}
type=raw,value=latest
build_jobs_service:
name: Build & push Docker image of the Jobs service
uses: ./.github/workflows/flow_backend_build_push.yml
with:
service-name: jobs
push-image: ${{ github.event_name != 'pull_request' }}
image-tags: |
type=sha
type=semver,pattern={{version}}
type=raw,value=latest
21 changes: 21 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Build stage
FROM amazoncorretto:17-alpine AS build
ARG SERVICE_NAME
WORKDIR /app

COPY ./$SERVICE_NAME ./$SERVICE_NAME
COPY ./gradle ./gradle
COPY ./gradle.properties .
COPY ./gradlew .
COPY ./settings.gradle.kts .

RUN --mount=type=cache,target=/root/.gradle ./gradlew clean build -x test

# Run stage
FROM amazoncorretto:17-alpine AS run
ARG SERVICE_NAME
WORKDIR /app

COPY --from=build /app/$SERVICE_NAME/build/libs/*-SNAPSHOT.jar ./app.jar

ENTRYPOINT ["java", "-jar", "./app.jar"]
42 changes: 23 additions & 19 deletions backend/api_gateway/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot")
id("io.spring.dependency-management")
kotlin("jvm")
kotlin("plugin.spring")
kotlin("plugin.jpa")
id("org.springframework.boot")
id("io.spring.dependency-management")
id("org.jlleitschuh.gradle.ktlint")
kotlin("jvm")
kotlin("plugin.spring")
kotlin("plugin.jpa")
}

group = "com.linkedout"
version = "1.0.0-SNAPSHOT"

java {
sourceCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-security:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-validation:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-web:3.1.5")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.springframework.boot:spring-boot-starter-actuator:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-security:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-validation:3.1.5")
implementation("org.springframework.boot:spring-boot-starter-web:3.1.5")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}

tasks.withType<Test> {
useJUnitPlatform()
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.springframework.security.oauth2.server.resource.authentication.JwtAut
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter
import org.springframework.security.web.SecurityFilterChain


@Configuration
@EnableWebSecurity
@EnableMethodSecurity
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.linkedout.backend

import org.junit.jupiter.api.Test
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
internal class ApiGatewayApplicationTests {
companion object {
@Container
private val postgreSQLContainer = PostgreSQLContainer<Nothing>("postgres:latest")

@DynamicPropertySource
@JvmStatic
fun registerDynamicProperties(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl)
registry.add("spring.datasource.username", postgreSQLContainer::getUsername)
registry.add("spring.datasource.password", postgreSQLContainer::getPassword)
}
}

@Test
fun contextLoads() {
}
}
Loading

0 comments on commit 63f3437

Please sign in to comment.