From 6ab48eb534d38be1496ec942bee0ecbeb4e3b04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=20Tr=C3=B6ger?= Date: Sun, 30 Nov 2025 21:25:47 +0100 Subject: [PATCH] dev/install (#58) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit improved ci/cd pipeline + interactive install script Reviewed-on: https://git.letsstein.de/tom/arbeitszeitmessung/pulls/58 Co-authored-by: Tom Tröger Co-committed-by: Tom Tröger --- .gitea/workflows/build.yaml | 3 +- .gitea/workflows/test.yaml | 4 +- Backend/database.go | 3 +- Backend/helper/time.go | 1 - Docker/.env.example | 11 ---- Docker/docker-compose.yml | 4 +- Docker/env.example | 10 ++++ Makefile | 8 +++ install.sh | 107 ++++++++++++++++++++++++++++++++++++ 9 files changed, 132 insertions(+), 19 deletions(-) delete mode 100644 Docker/.env.example create mode 100644 Docker/env.example create mode 100755 install.sh 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..80c1004 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 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/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 := "" 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/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 new file mode 100644 index 0000000..b79f985 --- /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 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 new file mode 100755 index 0000000..5a0758e --- /dev/null +++ b/install.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +set -e + +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" =~ ^[Yy]$ ]]; 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 +fi + +echo "Preparing .env file..." +if [ ! -f $envFile ]; then + if [ -f $envExample ]; then + echo ".env not found. Creating interactively from .env.example." + > $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." + else + echo "No .env or .env.example found." + echo "Creating an empty .env file for manual editing." + touch $envFile + fi +else + echo "Using existing .env. (found at $envFile)" +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 + echo "You can start them manually with: docker compose up -d" +fi