feat: updates (#631)

* build(deps): bump org.springframework.boot:spring-boot-starter-parent

Bumps [org.springframework.boot:spring-boot-starter-parent](https://github.com/spring-projects/spring-boot) from 3.5.4 to 3.5.5.
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
- [Commits](https://github.com/spring-projects/spring-boot/compare/v3.5.4...v3.5.5)

---
updated-dependencies:
- dependency-name: org.springframework.boot:spring-boot-starter-parent
  dependency-version: 3.5.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump io.jsonwebtoken:jjwt-jackson in /server

Bumps io.jsonwebtoken:jjwt-jackson from 0.12.7 to 0.13.0.

---
updated-dependencies:
- dependency-name: io.jsonwebtoken:jjwt-jackson
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump io.jsonwebtoken:jjwt-impl in /server

Bumps [io.jsonwebtoken:jjwt-impl](https://github.com/jwtk/jjwt) from 0.12.7 to 0.13.0.
- [Release notes](https://github.com/jwtk/jjwt/releases)
- [Changelog](https://github.com/jwtk/jjwt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jwtk/jjwt/compare/0.12.7...0.13.0)

---
updated-dependencies:
- dependency-name: io.jsonwebtoken:jjwt-impl
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump io.jsonwebtoken:jjwt-api in /server

Bumps [io.jsonwebtoken:jjwt-api](https://github.com/jwtk/jjwt) from 0.12.7 to 0.13.0.
- [Release notes](https://github.com/jwtk/jjwt/releases)
- [Changelog](https://github.com/jwtk/jjwt/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jwtk/jjwt/compare/0.12.7...0.13.0)

---
updated-dependencies:
- dependency-name: io.jsonwebtoken:jjwt-api
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* feat: add Taskfile

* feat: add files, tasks and more automations

* feat: disable email sending if not configured

* chore: rename client to tasknote-web

* feat: add devtools for faster development

* feat: Re-tag Docker image with 'latest' tag

* feat: update wording and improve taskfile

* Implement ApplicationRunner for startup logging

* fix: add reachability json file

* feat: drop old config for JJWT

* Revert "feat: drop old config for JJWT"

This reverts commit ed29cf4684454b0d5e3f1a284b479e2bb6872ad7.

* chore: JJWT finally working now

* test: fix test cases

* ci: fix permissions

* test: add more test cases

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
2025-08-31 13:43:26 -03:00
committed by GitHub
co-authored by dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
parent caa0b8b9ea
commit 2da0a9f113
26 changed files with 529 additions and 133 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
#!/bin/bash
DOCKER_IMG="server:nightly"
DOCKER_IMG="tasknote-api:nightly"
docker image inspect $DOCKER_IMG --format="ignore me"
if [ $? -eq 1 ]; then
@@ -19,10 +19,10 @@ if [ $? -eq 1 ]; then
echo "Done!"
cd ..
docker build --file server/Dockerfile.dev --tag server:nightly .
docker build --file server/Dockerfile.dev --tag tasknote-api:nightly .
else
echo "Image found! Let's keep going."
fi
docker run -it --rm --name server -e CHECK="TRUE" -v ./server:/app server:nightly
docker run -it --rm --name tasknote-api -e CHECK="TRUE" -v ./server:/app tasknote-api:nightly
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash
docker run -it --rm --name client -e CHECK="TRUE" -v ./client:/app client:nightly
docker run -it --rm --name tasknote-web -e CHECK="TRUE" -v ./client:/app tasknote-web:nightly
+1 -1
View File
@@ -41,7 +41,7 @@ response=$(curl -X POST \
-H "Content-Type: application/json" \
-H "x-api-key: ${API_KEY}" \
-d '{
"dockerImage": "ghcr.io/ricardo-campos-org/react-typescript-todolist/client:prod-v359",
"dockerImage": "ghcr.io/ricardo-campos-org/react-typescript-todolist/tasknote-web:prod-v359",
"applicationId": "'"${CLIENT_APPID}"'",
"username": "'"${GHCR_USERNAME}"'",
"password": "'"${GHCR_PASSWORD}"'",
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
SERVICE="$1"
# Get the IP address of the Docker container running the database
IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $SERVICE)
# Output the IP address
echo "$IP"
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
# Checks if a given image and tag are present locally to prevent running when it's not
TARGET="$1"
IS=$(docker images $TARGET:candidate | wc -l)
if [ $IS -eq 0 ]; then
echo "Image $TARGET:candidate not found locally, please build it"
exit 1;
fi
echo "Image $TARGET:candidate found"
exit 0
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
# Check if a given service is not running
# Return 0 (success) if it's not
TARGET="$1"
echo "Check for running image for $TARGET"
IS=$(docker ps --filter name=$TARGET --filter status=running | grep $TARGET | wc -l)
if [ $IS -eq 0 ]; then
echo "Service $TARGET is not running"
exit 0
fi
echo "Service $TARGET is running"
exit 1
+14
View File
@@ -0,0 +1,14 @@
#!/bin/bash
TARGET="$1"
echo "Check for running image for $TARGET"
IS=$(docker ps --filter name=$TARGET --filter status=running | grep $TARGET | wc -l)
if [ $IS -eq 1 ]; then
echo "Service $TARGET is running"
exit 0
fi
echo "Service $TARGET not running"
exit 1
+5 -3
View File
@@ -11,13 +11,15 @@ if [ "$TARGET" == "back" ]; then
echo "Creating basic env file for database and back-end"
cd server
echo "POSTGRES_DB=postgres" >> .env
echo "POSTGRES_HOST=localhost" >> .env
echo "POSTGRES_USER=postgres" >> .env
echo "POSTGRES_DB=tasknote" >> .env
echo "POSTGRES_HOST=db" >> .env
echo "POSTGRES_USER=tasknoteuser" >> .env
echo "POSTGRES_PASSWORD=default" >> .env
echo "POSTGRES_PORT=5432" >> .env
echo "SERVER_SERVLET_CONTEXT_PATH=/" >> .env
echo "CORS_ALLOWED_ORIGINS=http://localhost:5000" >> .env
echo "SECURITY_KEY=this-is-a-very-long-security-key-for-dev" >> .env
echo "MAILGUN_APIKEY=invalid-api-key-only-placeholder" >> .env
elif [ "$TARGET" == "front" ]; then
if [ -f "client/.env" ]; then
echo "Env file in place. Leaving..."
+2 -2
View File
@@ -21,10 +21,10 @@ if [ $? -eq 1 ]; then
exit 1
fi
SERVER_HOST="http://"$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' server)":8585"
SERVER_HOST="http://"$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' tasknote-api):8585"
if [ "$SERVER_HOST" == "http://:8585" ]; then
echo "Back-end server not running. Make sure to run it before starting the web app."
echo "Back-end tasknote-api not running. Make sure to run it before starting the web app."
exit 0
fi
+3 -3
View File
@@ -14,12 +14,12 @@ echo "Done!"
cd ..
docker build --file server/Dockerfile.dev --tag server:nightly .
docker build --file server/Dockerfile.dev --tag tasknote-api:nightly .
DB_HOST=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db)
docker run -d --rm \
--name server \
--name tasknote-api \
-p 8585:8585 \
-p 5005:5005 \
-e POSTGRES_DB=$POSTGRES_DB \
@@ -30,4 +30,4 @@ docker run -d --rm \
-e CORS_ALLOWED_ORIGINS=$CORS_ALLOWED_ORIGINS \
-e SERVER_SERVLET_CONTEXT_PATH=$SERVER_SERVLET_CONTEXT_PATH \
-v ./server:/app \
server:nightly
tasknote-api:nightly
+13 -40
View File
@@ -9,7 +9,7 @@ All kind of tools and useful links and commands can be found here!
## Building locally
**Client - Frontend Web App:**
**Tasknote-web - Frontend Web App:**
Before building, you need define some env vars:
@@ -30,13 +30,13 @@ If you want to build with Docker:
docker build --no-cache \
--build-arg VITE_BUILD="v999-$(date '+%Y-%m-%d-%H%M%S')" \
--build-arg SOURCE_PR="v999-123456789-$(date '+%Y-%m-%d-%H%M%S')" \
-t client:candidate \
-t tasknote-web:candidate \
./client
```
That's it!
**Server - Backend REST API:**
**Tasknote-api - Backend REST API:**
For the backend there's a Dockerfile ready, just run (from the project root):
@@ -44,30 +44,12 @@ For the backend there's a Dockerfile ready, just run (from the project root):
docker build --no-cache \
--build-arg BUILD="v999-$(date '+%Y-%m-%d-%H%M%S')" \
--build-arg SOURCE_PR="v999-123456789-$(date '+%Y-%m-%d-%H%M%S')" \
-t server:candidate \
-t tasknote-api:candidate \
./server
```
That's it!
## Deploying manually
1. Connect into the server via SSH
2. Run deploy scripts
Here are a few steps:
```bash
export SERVER_IP=
export SERVER_ADDRESS=
npm ci --ignore-scripts --no-update-notifier --omit=dev
export VITE_BACKEND_SERVER=$SERVER_ADDRESS/server
npm run build
zip -r "client_$VERSION.zip" dist/
scp "client_$VERSION.zip" root@$SERVER_IP:/root/
```
## Running with Docker
**DB:**
@@ -81,23 +63,23 @@ docker run -d -p 5432:5432 --rm \
postgres:15.8-bookworm
```
**Server:**
**Tasknote-api:**
```bash
docker run -d -p 8585:8585 --rm \
--name server \
--name tasknote-api \
-e POSTGRES_DB=$POSTGRES_DB \
-e POSTGRES_USER=$POSTGRES_USER \
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
-e POSTGRES_PORT=$POSTGRES_PORT \
-e POSTGRES_HOST=$POSTGRES_HOST \
-e CORS_ALLOWED_ORIGINS=$CORS_ALLOWED_ORIGINS \
ghcr.io/ricardo-campos-org/react-typescript-todolist/server:<PR-Number>
ghcr.io/ricardo-campos-org/react-typescript-todolist/tasknote-api:<PR-Number>
```
Build Cloud Native: `./mvnw -B package -Pnative -DskipTests`
**Client:**
**Tasknote-web:**
The frontend app will run on Nginx.
@@ -113,13 +95,13 @@ echo $CR_PAT | docker login ghcr.io -u RMCampos --password-stdin
**Pulling images:**
```sh
docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/client:50
docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/server:50
docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/tasknote-web:50
docker pull ghcr.io/ricardo-campos-org/react-typescript-todolist/tasknote-api:50
```
**Pushing images:**
```sh
docker push ghcr.io/ricardo-campos-org/react-typescript-todolist/server:316
docker push ghcr.io/ricardo-campos-org/react-typescript-todolist/tasknote-api:316
```
- Get container IP
@@ -133,12 +115,12 @@ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db
docker inspect --format "{{json .State.Health}}" container_name_or_id | jq
# Or to see it live
while true; do clear; docker inspect --format "{{json .State.Health}}" server | jq; sleep 1; done
while true; do clear; docker inspect --format "{{json .State.Health}}" tasknote-api | jq; sleep 1; done
```
- Extract Env value from docker image (without running)
```bash
docker inspect client:candidate | jq -r '.[0].Config.Env[] | select(startswith("SOURCE_PR="))' | sed -n 's/SOURCE_PR=\(v[0-9]*\).*/\1/p'
docker inspect tasknote-web:candidate | jq -r '.[0].Config.Env[] | select(startswith("SOURCE_PR="))' | sed -n 's/SOURCE_PR=\(v[0-9]*\).*/\1/p'
```
## Restoring DB for testing
@@ -157,12 +139,3 @@ docker run \
docker exec -i my-postgres-db pg_restore -U <user> -d <db-name> < 2025-04-26T20_00_00.114Z.sql
```
<div className="py-5 text-center">
<div className="d-block d-sm-none bg-primary text-white p-3">XS (Extra Small): less than 576px</div>
<div className="d-none d-sm-block d-md-none bg-secondary text-white p-3">SM (Small): ≥576px</div>
<div className="d-none d-md-block d-lg-none bg-success text-white p-3">MD (Medium): ≥768px</div>
<div className="d-none d-lg-block d-xl-none bg-warning text-dark p-3">LG (Large): ≥992px</div>
<div className="d-none d-xl-block d-xxl-none bg-danger text-white p-3">XL (Extra Large): ≥1200px</div>
<div className="d-none d-xxl-block bg-dark text-white p-3">XXL (Extra Extra Large): ≥1400px</div>
</div>