From 62c12cceba8a6b9462414e5da1e765b9bb3f070c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 13:46:10 +0100 Subject: [PATCH 1/6] added install script --- Docker/.env.example | 11 --------- Docker/env.example | 10 ++++++++ install.sh | 57 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 11 deletions(-) delete mode 100644 Docker/.env.example create mode 100644 Docker/env.example create mode 100755 install.sh diff --git a/Docker/.env.example b/Docker/.env.example deleted file mode 100644 index 256e380..0000000 --- a/Docker/.env.example +++ /dev/null @@ -1,11 +0,0 @@ -POSTGRES_USER=root -POSTGRES_PASSWORD=very_secure -POSTGRES_API_USER=api_nutzer -POSTGRES_API_PASS=password -POSTGRES_PATH=../DB -POSTGRES_DB=arbeitszeitmessung -EXPOSED_PORT=8000 -TZ=Europe/Berlin -PGTZ=Europe/Berlin -API_TOKEN=dont_access -EMPTY_DAYS=false diff --git a/Docker/env.example b/Docker/env.example new file mode 100644 index 0000000..fb99eed --- /dev/null +++ b/Docker/env.example @@ -0,0 +1,10 @@ +POSTGRES_USER=root # Postgres ADMIN Nutzername +POSTGRES_PASSWORD=very_secure # Postgres ADMIN Passwort +POSTGRES_API_USER=api_nutzer # Postgres API Nutzername (für Arbeitszeitmessung) +POSTGRES_API_PASS=password # Postgres API Passwort (für Arbeitszeitmessung) +POSTGRES_PATH=../DB # Datebank Pfad (relativ zu Docker Ordner oder absoluter pfad mit /...) +POSTGRES_DB=arbeitszeitmessung # Postgres Datenbank Name +EXPOSED_PORT=8000 # Port auf welchem Arbeitszeitmessung läuft +TZ=Europe/Berlin # Zeitzone +PGTZ=Europe/Berlin # Zeitzone +API_TOKEN=dont_access # API Token für ESP Endpoints diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..b8ca96c --- /dev/null +++ b/install.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -e + +# --- CHECK PREREQUISITES ----------------------------------------------------- + +echo "Checking Docker installation..." +if ! command -v docker >/dev/null 2>&1; then + echo "Docker not found. Install Docker? [y/N]" + read -r install_docker + if [ "$install_docker" = "y" ] || [ "$install_docker" = "Y" ]; then + curl -fsSL https://get.docker.com | sh + else + echo "Docker is required. Exiting." + exit 1 + fi +else + echo "Docker is already installed." +fi + +echo "Checking Docker Compose..." +if ! docker compose version >/dev/null 2>&1; then + echo "Docker Compose plugin missing. You may need to update Docker." + exit 1 +else + echo "Docker Compose available." +fi + +# --- LOAD ENV FILE ------------------------------------------------------------ + +if [ ! -f "Docker/.env" ]; then + echo ".env file not found in the current directory." + echo "Create one now? [y/N]" + read -r create_env + if [ "$create_env" = "y" ] || [ "$create_env" = "Y" ]; then + cp Docker/env.example Docker/.env 2>/dev/null || touch .env + echo "Created .env (./Docker/.env). Edit it before continuing." + exit 0 + else + echo "A .env file is required. Exiting." + exit 1 + fi +else + echo "Using existing .env file (Docker/.env)." +fi + +# --- START DOCKER COMPOSE ----------------------------------------------------- + +echo "Start containers now with docker compose up -d? [y/N]" +read -r start_containers + +if [ "$start_containers" = "y" ] || [ "$start_containers" = "Y" ]; then + cd Docker + docker compose up -d + echo "Containers started." +else + echo "You can start containers manually with: docker compose up -d" +fi -- 2.49.1 From 8cb63d33428b807a2533d6f7a1b6849a5904ce63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 18:15:57 +0100 Subject: [PATCH 2/6] interactive config --- install.sh | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/install.sh b/install.sh index b8ca96c..cd40bd6 100755 --- a/install.sh +++ b/install.sh @@ -1,13 +1,14 @@ #!/usr/bin/env bash set -e -# --- CHECK PREREQUISITES ----------------------------------------------------- +envFile=Docker/.env +envExample=Docker/env.example echo "Checking Docker installation..." if ! command -v docker >/dev/null 2>&1; then echo "Docker not found. Install Docker? [y/N]" read -r install_docker - if [ "$install_docker" = "y" ] || [ "$install_docker" = "Y" ]; then + if [[ "$install_docker" =~ ^[Yy]$ ]]; then curl -fsSL https://get.docker.com | sh else echo "Docker is required. Exiting." @@ -21,37 +22,41 @@ echo "Checking Docker Compose..." if ! docker compose version >/dev/null 2>&1; then echo "Docker Compose plugin missing. You may need to update Docker." exit 1 -else - echo "Docker Compose available." fi -# --- LOAD ENV FILE ------------------------------------------------------------ +echo "Preparing .env file..." +if [ ! -f $envFile ]; then + if [ -f $envExample ]; then + echo ".env not found. Creating interactively from .env.example." + > $envFile -if [ ! -f "Docker/.env" ]; then - echo ".env file not found in the current directory." - echo "Create one now? [y/N]" - read -r create_env - if [ "$create_env" = "y" ] || [ "$create_env" = "Y" ]; then - cp Docker/env.example Docker/.env 2>/dev/null || touch .env - echo "Created .env (./Docker/.env). Edit it before continuing." - exit 0 + while IFS="=" read -r key val; do + [[ "$key" =~ ^#.*$ || -z "$key" ]] && continue + default_value=$(echo "$val" | sed 's/"//g') + printf "Value for $key (default: $default_value): " + read -r user_value < /dev/tty + if [ -z "$user_value" ]; then + echo "$key=$default_value" >> $envFile + else + echo "$key=$user_value" >> $envFile + fi + done < $envExample + + echo ".env created." else - echo "A .env file is required. Exiting." - exit 1 + echo "No .env or .env.example found." + echo "Creating an empty .env file for manual editing." + touch $envFile fi else - echo "Using existing .env file (Docker/.env)." + echo "Using existing .env. (found at $envFile)" fi -# --- START DOCKER COMPOSE ----------------------------------------------------- - -echo "Start containers now with docker compose up -d? [y/N]" +echo "Start containers with docker compose up -d? [y/N]" read -r start_containers - -if [ "$start_containers" = "y" ] || [ "$start_containers" = "Y" ]; then - cd Docker +if [[ "$start_containers" =~ ^[Yy]$ ]]; then docker compose up -d echo "Containers started." else - echo "You can start containers manually with: docker compose up -d" + echo "You can start them manually with: docker compose up -d" fi -- 2.49.1 From dd8a29acc2c6ac58bc37e2de3fe048cf4a2c0245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 19:54:00 +0100 Subject: [PATCH 3/6] added install script + reworked pipeline --- .gitea/workflows/build.yaml | 3 +- .gitea/workflows/test.yaml | 13 ++++---- Backend/database.go | 3 +- Docker/docker-compose.yml | 4 +-- Docker/env.example | 2 +- Makefile | 8 +++++ install.sh | 63 +++++++++++++++++++++++++++++++------ 7 files changed, 75 insertions(+), 21 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index c32282f..a73ba14 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -2,7 +2,8 @@ name: Arbeitszeitmessung Deploy run-name: ${{ gitea.actor }} is building and deploying arbeitszeitmesssung on: push: - tags: "*" + tags: + - "*" jobs: testing: diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 2a3dfc4..22d5898 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -15,8 +15,8 @@ jobs: POSTGRES_DB: arbeitszeitmessung env: POSTGRES_HOST: postgres - POSTGRES_USER: root - POSTGRES_PASSWORD: password + POSTGRES_API_USER: root + POSTGRES_API_PASS: password POSTGRES_DB: arbeitszeitmessung POSTGRES_PORT: 5432 RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache @@ -26,10 +26,7 @@ jobs: with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 - - name: Setup go - uses: actions/setup-go@v5 - with: - go-version-file: Backend/go.mod + - uses: https://gitea.com/actions/go-hashfiles@v0.0.1 id: hash-go with: @@ -46,6 +43,10 @@ jobs: key: arbeitszeitmessung-${{ steps.hash-go.outputs.hash }} restore-keys: |- arbeitszeitmessung- + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version-file: Backend/go.mod - name: Run Go Tests run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json - name: Verify coverage report exists diff --git a/Backend/database.go b/Backend/database.go index bad1b77..8394d1f 100644 --- a/Backend/database.go +++ b/Backend/database.go @@ -14,7 +14,8 @@ func OpenDatabase() (models.IDatabase, error) { dbName := helper.GetEnv("POSTGRES_DB", "arbeitszeitmessung") dbUser := helper.GetEnv("POSTGRES_API_USER", "api_nutzer") dbPassword := helper.GetEnv("POSTGRES_API_PASS", "password") + dbTz := helper.GetEnv("TZ", "Europe/Berlin") - connStr := fmt.Sprintf("postgres://%s:%s@%s:5432/%s?sslmode=disable&TimeZone=Europe/Berlin", dbUser, dbPassword, dbHost, dbName) + connStr := fmt.Sprintf("postgres://%s:%s@%s:5432/%s?sslmode=disable&TimeZone=%s", dbUser, dbPassword, dbHost, dbName, dbTz) return sql.Open("postgres", connStr) } diff --git a/Docker/docker-compose.yml b/Docker/docker-compose.yml index f08a18b..d3d97c0 100644 --- a/Docker/docker-compose.yml +++ b/Docker/docker-compose.yml @@ -6,9 +6,7 @@ services: env_file: - .env environment: - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_DB: ${POSTGRES_DB} + PGTZ: ${TZ} PGDATA: /var/lib/postgresql/data/pg_data volumes: - ${POSTGRES_PATH}:/var/lib/postgresql/data diff --git a/Docker/env.example b/Docker/env.example index fb99eed..b79f985 100644 --- a/Docker/env.example +++ b/Docker/env.example @@ -4,7 +4,7 @@ POSTGRES_API_USER=api_nutzer # Postgres API Nutzername (für Arbeitszeitmessu POSTGRES_API_PASS=password # Postgres API Passwort (für Arbeitszeitmessung) POSTGRES_PATH=../DB # Datebank Pfad (relativ zu Docker Ordner oder absoluter pfad mit /...) POSTGRES_DB=arbeitszeitmessung # Postgres Datenbank Name -EXPOSED_PORT=8000 # Port auf welchem Arbeitszeitmessung läuft +EXPOSED_PORT=8000 # Port auf welchem Arbeitszeitmessung läuft regex:^[0-9]{1,5}$ TZ=Europe/Berlin # Zeitzone PGTZ=Europe/Berlin # Zeitzone API_TOKEN=dont_access # API Token für ESP Endpoints diff --git a/Makefile b/Makefile index 58d90fb..8de2724 100644 --- a/Makefile +++ b/Makefile @@ -52,3 +52,11 @@ test: scan: test $(MAKE) -C Backend scan + +Docker/.env: + cp Docker/env.example Docker/.env + echo "Konfigurations Datei erstellt (./Docker/.env), bitte zuerst ausfüllen und danach erneut 'make install' ausführen" + exit 0 + +install: Docker/.env + echo "Install" diff --git a/install.sh b/install.sh index cd40bd6..5a0758e 100755 --- a/install.sh +++ b/install.sh @@ -30,16 +30,60 @@ if [ ! -f $envFile ]; then echo ".env not found. Creating interactively from .env.example." > $envFile - while IFS="=" read -r key val; do - [[ "$key" =~ ^#.*$ || -z "$key" ]] && continue - default_value=$(echo "$val" | sed 's/"//g') - printf "Value for $key (default: $default_value): " - read -r user_value < /dev/tty - if [ -z "$user_value" ]; then - echo "$key=$default_value" >> $envFile - else - echo "$key=$user_value" >> $envFile + while IFS= read -r line; do + + #ignore empty lines and comments + [[ "$line" =~ ^#.*$ || -z "$line" ]] && continue + + + key=$(printf "%s" "$line" | cut -d '=' -f 1) + rest=$(printf "%s" "$line" | cut -d '=' -f 2-) + + # extract inline comment portion + comment=$(printf "%s" "$rest" | sed -n 's/.*# \(.*\)$/\1/p') + raw_val=$(printf "%s" "$rest" | sed 's/ *#.*//') + default_value=$(printf "%s" "$raw_val" | sed 's/"//g') + + regex="" + if [[ "$comment" =~ regex:(.*)$ ]]; then + regex="${BASH_REMATCH[1]}" fi + + comment=$(printf "%s" "$comment" | sed 's/ regex:.*//') + + while true; do + if [ -z "$comment" ]; then + printf "Value for $key - $comment (default: $default_value" + else + printf "Value for $key (default: $default_value" + fi + if [ -n "$regex" ]; then + printf ", must match: %s" "$regex" + fi + printf "):\n" + + read user_input < /dev/tty + + # empty input -> take default + [ -z "$user_input" ] && user_input="$default_value" + + printf "\e[A$user_input\n" + + # validate + if [ -n "$regex" ]; then + if [[ "$user_input" =~ $regex ]]; then + echo "$key=$user_input" >> $envFile + break + else + printf "Invalid value. Does not match regex: %s\n" "$regex" + continue + fi + else + echo "$key=$user_input" >> $envFile + break + fi + done + done < $envExample echo ".env created." @@ -55,6 +99,7 @@ fi echo "Start containers with docker compose up -d? [y/N]" read -r start_containers if [[ "$start_containers" =~ ^[Yy]$ ]]; then + cd Docker docker compose up -d echo "Containers started." else -- 2.49.1 From 7d04062a3a8c8d7da0061a8f5e519d20d5cb8615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 19:54:49 +0100 Subject: [PATCH 4/6] try now --- .gitea/workflows/test.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 22d5898..80c1004 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -26,7 +26,10 @@ jobs: with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 - + - name: Setup go + uses: actions/setup-go@v5 + with: + go-version-file: Backend/go.mod - uses: https://gitea.com/actions/go-hashfiles@v0.0.1 id: hash-go with: @@ -43,10 +46,6 @@ jobs: key: arbeitszeitmessung-${{ steps.hash-go.outputs.hash }} restore-keys: |- arbeitszeitmessung- - - name: Setup go - uses: actions/setup-go@v5 - with: - go-version-file: Backend/go.mod - name: Run Go Tests run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json - name: Verify coverage report exists -- 2.49.1 From f5a4f956974c928d849c9ebf0351943198ce6ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 19:57:13 +0100 Subject: [PATCH 5/6] removed coverage and json to see whats happening --- .gitea/workflows/test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 80c1004..9589818 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -47,7 +47,7 @@ jobs: restore-keys: |- arbeitszeitmessung- - name: Run Go Tests - run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json + run: cd Backend && mkdir .test && go test ./... - name: Verify coverage report exists run: | if [ -f "Backend/.test/coverage.out" ]; then -- 2.49.1 From db14d6070a284819241e9992b2526bba858d7fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 19:59:22 +0100 Subject: [PATCH 6/6] reverted format duration change --- .gitea/workflows/test.yaml | 2 +- Backend/helper/time.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitea/workflows/test.yaml b/.gitea/workflows/test.yaml index 9589818..80c1004 100644 --- a/.gitea/workflows/test.yaml +++ b/.gitea/workflows/test.yaml @@ -47,7 +47,7 @@ jobs: restore-keys: |- arbeitszeitmessung- - name: Run Go Tests - run: cd Backend && mkdir .test && go test ./... + run: cd Backend && mkdir .test && go test ./... -coverprofile=.test/coverage.out -json > .test/report.json - name: Verify coverage report exists run: | if [ -f "Backend/.test/coverage.out" ]; then diff --git a/Backend/helper/time.go b/Backend/helper/time.go index f55a92c..30198fc 100644 --- a/Backend/helper/time.go +++ b/Backend/helper/time.go @@ -31,7 +31,6 @@ func FormatDuration(d time.Duration) string { // Converts duration to string func FormatDurationFill(d time.Duration, fill bool) string { - return fmt.Sprintf("%.1f", d.Hours()) hours := int(d.Abs().Hours()) minutes := int(d.Abs().Minutes()) % 60 sign := "" -- 2.49.1