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:
co-authored by
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
parent
caa0b8b9ea
commit
2da0a9f113
@@ -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,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
|
||||
|
||||
@@ -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}"'",
|
||||
|
||||
Executable
+9
@@ -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"
|
||||
Executable
+14
@@ -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
|
||||
Executable
+16
@@ -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
|
||||
Executable
+14
@@ -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
|
||||
@@ -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..."
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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>
|
||||
Reference in New Issue
Block a user