diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 30e0006..357b688 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -100,4 +100,31 @@ jobs:
run: cd java-api && ./mvnw --no-transfer-progress checkstyle:checkstyle -Dskip.checkstyle=false
- name: All Tests
- run: cd java-api && ./mvnw --no-transfer-progress clean verify -P all-tests --file pom.xml
+ run: cd java-api && ./mvnw --no-transfer-progress clean verify -P tests --file pom.xml
+
+ java-docker-build:
+ name: Build Client Docker image
+ runs-on: ubuntu-latest
+ needs:
+ - client-code-checks
+ steps:
+ - uses: actions/checkout@v4
+ - uses: docker/setup-buildx-action@v3
+ name: Set up Docker Buildx
+
+ - uses: docker/login-action@v3
+ name: Login to GitHub Container Registry
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v6
+ with:
+ push: true
+ context: ./java-api
+ tags: ghcr.io/ricardo-campos-org/react-typescript-todolist/java-api:${{ github.event.number }}
+ build-args: BUILD=${{ github.event.number }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
diff --git a/java-api/Dockerfile b/java-api/Dockerfile
new file mode 100644
index 0000000..fefb283
--- /dev/null
+++ b/java-api/Dockerfile
@@ -0,0 +1,32 @@
+### Builder
+FROM ghcr.io/graalvm/native-image:22.3.3 AS build
+
+# Copy
+WORKDIR /app
+COPY pom.xml mvnw ./
+COPY src ./src
+COPY .mvn/ ./.mvn
+
+# Build
+RUN ./mvnw -B package -Pnative -DskipTests
+
+
+### Deployer
+FROM gcr.io/distroless/java-base:nonroot AS deploy
+ARG PORT=8585
+
+# Receive build number as argument, retain as environment variable
+ARG BUILD_NUMBER
+ENV BUILD_NUMBER=${BUILD_NUMBER}
+
+# Copy
+WORKDIR /app
+COPY --from=build /app/target/tasknote-api ./tasknote-api
+
+# User, port and health check
+USER 1001
+EXPOSE ${PORT}
+HEALTHCHECK CMD timeout 10s bash -c 'true > /dev/tcp/127.0.0.1/8585'
+
+# Startup
+ENTRYPOINT ["/app/tasknote-api", "-Dspring.profiles.active=prod"]
diff --git a/java-api/pom.xml b/java-api/pom.xml
index 4df81cb..c82c601 100644
--- a/java-api/pom.xml
+++ b/java-api/pom.xml
@@ -31,8 +31,70 @@
17
+ UTF-8
+ UTF-8
+ true
+ true
+ true
+ true
+ true
+ true
+ ${project.build.directory}/coverage-reports
+ ${maven.build.timestamp}
+ yyyy-MM-dd HH:mm:ss
+
+
+
+
+ tests
+
+ tests
+ false
+ false
+ false
+ false
+
+
+
+
+
+ prod
+
+ prod
+
+
+
+
+
+ native
+
+ native
+ true
+ true
+ true
+
+
+
+
+ org.graalvm.buildtools
+ native-maven-plugin
+
+
+ build-native
+
+ compile-no-fork
+
+ package
+
+
+
+
+
+
+
+
@@ -113,13 +175,11 @@
io.jsonwebtoken
jjwt-impl
0.12.6
- runtime
io.jsonwebtoken
jjwt-jackson
0.12.6
- runtime
@@ -161,6 +221,232 @@
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 3.5.0
+
+
+ integration-tests
+
+ integration-test
+ verify
+
+
+ @{argLine} -Xmx1024m
+ false
+ ${skip.integration.tests}
+
+ **/*IntegrationTest.java
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.0
+
+ @{argLine} -Xmx1024m
+ ${skip.unit.tests}
+
+ **/*IntegrationTest.java
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+ ${jacoco.skip}
+
+ **/config/**
+ **/dto/**
+ **/entity/**
+ **/exception/**
+ **/filter/**
+ **/interceptor/**
+ **/response/**
+ **/*$*Builder*
+ **/RestExceptionEndpoint.*
+ **/BackendStartApiApplication.*
+
+
+
+
+ pre-unit-test
+
+ prepare-agent
+
+
+ ${jacoco.output.data}/jacoco-ut.exec
+
+
+
+ post-unit-test
+ test
+
+ report
+
+
+ ${jacoco.output.data}/jacoco-ut.exec
+ ${jacoco.output.data}/jacoco-ut
+
+
+
+ pre-integration-test
+ pre-integration-test
+
+ prepare-agent-integration
+
+
+ ${jacoco.output.data}/jacoco-it.exec
+
+
+
+ post-integration-test
+ post-integration-test
+
+ report-integration
+
+
+ ${jacoco.output.data}/jacoco-it.exec
+ ${jacoco.output.data}/jacoco-it
+
+
+
+ merge-unit-and-integration
+ post-integration-test
+
+ merge
+
+
+
+
+ ${jacoco.output.data}
+
+ *.exec
+
+
+
+ ${project.build.directory}/jacoco.exec
+
+
+
+ merged-reports
+ post-integration-test
+
+ report
+
+
+ ${project.build.directory}/jacoco.exec
+ ${jacoco.output.data}/merged-test-report
+
+
+
+ coverage-check
+
+ check
+
+
+
+
+ BUNDLE
+
+
+ LINE
+ COVEREDRATIO
+ 80%
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.10.0
+
+ 17
+ Javadoc Documentation for ${project.name} ${project.version}
+ ${project.name} ${project.version}
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.5.0
+
+
+ default-cli
+
+ enforce
+
+
+
+
+
+ [3.2,)
+ Invalid Maven version. It should be at least 3.2
+
+
+ 17
+ Invalid Java Version. It should be at least 1.8
+
+
+
+ central
+
+
+ central
+
+
+
+ No Snapshots Allowed in releases!
+ true
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.5.0
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 10.18.1
+
+
+
+ ${checkstyle.skip}
+ ${checkstyle.failsOnError}
+
+ ${checkstyle.includeTestSourceDirectory}
+
+ .mvn/google_checks.xml
+ true
+ false
+
+
+
+ validate
+ checkstyle
+
+ check
+
+
+
+
diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/config/CloudNativeConfig.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/CloudNativeConfig.java
new file mode 100644
index 0000000..90ff9df
--- /dev/null
+++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/CloudNativeConfig.java
@@ -0,0 +1,44 @@
+package br.com.tasknoteapp.java_api.config;
+
+import br.com.tasknoteapp.java_api.request.LoginRequest;
+import br.com.tasknoteapp.java_api.request.NotePatchRequest;
+import br.com.tasknoteapp.java_api.request.NoteRequest;
+import br.com.tasknoteapp.java_api.request.NoteUrlPatchRequest;
+import br.com.tasknoteapp.java_api.request.TaskPatchRequest;
+import br.com.tasknoteapp.java_api.request.TaskRequest;
+import br.com.tasknoteapp.java_api.request.TaskUrlPatchRequest;
+import br.com.tasknoteapp.java_api.response.JwtAuthenticationResponse;
+import br.com.tasknoteapp.java_api.response.NoteResponse;
+import br.com.tasknoteapp.java_api.response.NoteUrlResponse;
+import br.com.tasknoteapp.java_api.response.SearchResponse;
+import br.com.tasknoteapp.java_api.response.SummaryResponse;
+import br.com.tasknoteapp.java_api.response.TaskResponse;
+import br.com.tasknoteapp.java_api.response.TaskUrlResponse;
+import br.com.tasknoteapp.java_api.response.UserResponse;
+import org.springframework.aot.hint.annotation.RegisterReflectionForBinding;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportRuntimeHints;
+
+@Configuration
+@RegisterReflectionForBinding({
+ LoginRequest.class,
+ NotePatchRequest.class,
+ NoteRequest.class,
+ NoteUrlPatchRequest.class,
+ TaskPatchRequest.class,
+ TaskRequest.class,
+ TaskUrlPatchRequest.class,
+ JwtAuthenticationResponse.class,
+ NoteResponse.class,
+ NoteUrlResponse.class,
+ SearchResponse.class,
+ SummaryResponse.class,
+ TaskResponse.class,
+ TaskUrlResponse.class,
+ UserResponse.class,
+ io.jsonwebtoken.Claims.class,
+ io.jsonwebtoken.Jwts.class,
+ io.jsonwebtoken.impl.security.StandardSecureDigestAlgorithms.class,
+})
+@ImportRuntimeHints(value = {HttpServletRequestRuntimeHint.class})
+public class CloudNativeConfig {}
diff --git a/java-api/src/main/java/br/com/tasknoteapp/java_api/config/HttpServletRequestRuntimeHint.java b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/HttpServletRequestRuntimeHint.java
new file mode 100644
index 0000000..f555cfe
--- /dev/null
+++ b/java-api/src/main/java/br/com/tasknoteapp/java_api/config/HttpServletRequestRuntimeHint.java
@@ -0,0 +1,22 @@
+package br.com.tasknoteapp.java_api.config;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.aot.hint.ProxyHints;
+import org.springframework.aot.hint.RuntimeHints;
+import org.springframework.aot.hint.RuntimeHintsRegistrar;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+/** This class creates a RuntimeHint for the ServletRequest class. */
+public class HttpServletRequestRuntimeHint implements RuntimeHintsRegistrar {
+
+ @Override
+ public void registerHints(@NonNull RuntimeHints hints, @Nullable ClassLoader classLoader) {
+ try {
+ ProxyHints proxies = hints.proxies();
+ proxies.registerJdkProxy(HttpServletRequest.class);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not register RuntimeHint: " + e.getMessage());
+ }
+ }
+}
diff --git a/java-api/src/main/resources/application.properties b/java-api/src/main/resources/application.properties
index 620ae87..37afea4 100644
--- a/java-api/src/main/resources/application.properties
+++ b/java-api/src/main/resources/application.properties
@@ -7,8 +7,8 @@ management.endpoint.health.show-details=always
# Database, datasource and JPA
spring.datasource.driver-class-name=org.postgresql.Driver
-spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST:localhost}:5432/${POSTGRES_DB:postgres}
-spring.datasource.username=${POSTGRES_USER:postgres}
+spring.datasource.url=jdbc:postgresql://${POSTGRES_HOST:localhost}:5432/${POSTGRES_DB:tasknote}
+spring.datasource.username=${POSTGRES_USER:tasknoteuser}
spring.datasource.password=${POSTGRES_PASSWORD:default}
spring.jpa.properties.hibernate.default_schema=tasknote
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
diff --git a/tools.md b/tools.md
index 45d08c8..cb0a68e 100644
--- a/tools.md
+++ b/tools.md
@@ -1,7 +1,7 @@
# Tools
- **TaskNote:** https://tasknote.local
-- **Docker Hub:** https://hub.docker.com/
+- **GitHub Container Registry:** https://ghcr.io/
- **Time tracking:** https://track.toggl.com/timer
# Building locally
@@ -22,3 +22,29 @@ Build and run with Docker Compose:
```sh
docker compose --profile caddy up --build
```
+
+# Interact with GitHub Package
+
+Login in:
+
+```
+export CR_PAT=YOUR_TOKEN
+echo $CR_PAT | docker login ghcr.io -u RMCampos --password-stdin
+```
+
+Pull image:
+
+```sh
+docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50
+```
+
+Run it:
+
+```sh
+docker run -d --rm \
+ -p 80:5000 \
+ -e VITE_BUILD="client:50" \
+ -e VITE_BACKEND_SERVER="http://localhost:8585" \
+ --name tasknote \
+ ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50
+```
diff --git a/tools/check-backend.sh b/tools/check-backend.sh
new file mode 100755
index 0000000..2b4eac9
--- /dev/null
+++ b/tools/check-backend.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+cd java-api
+./mvnw --no-transfer-progress clean compile -DskipTests && \
+ ./mvnw --no-transfer-progress checkstyle:checkstyle -Dskip.checkstyle=false && \
+ ./mvnw --no-transfer-progress clean verify -P tests --file pom.xml
\ No newline at end of file