Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f9fae10af | |||
| f45988d0e7 | |||
| 32f39223f4 | |||
| 20528b60c5 | |||
| c610c06a0e | |||
| 2cef1672d2 | |||
| eb8542c410 | |||
| 1ebd83ec2c | |||
| e80bf946c0 | |||
| bfbbff597e | |||
| d80f3f56b7 | |||
| 726fca0866 | |||
| 614f73250a | |||
| 0d2488eb0b | |||
| 7e6a1d6b03 | |||
| ebf144f1a9 | |||
| 78fda8d569 | |||
| 248594ce0d | |||
| 783c68a243 | |||
| 031d41643e | |||
| cae3199e53 |
@@ -1,11 +0,0 @@
|
||||
NUITKA_BUILD=0
|
||||
INVENTAR_HTTP_PORT=10000
|
||||
INVENTAR_HTTP_PORTS=10000
|
||||
INVENTAR_APP_IMAGE=ghcr.io/aiirondev/legendary-octo-garbanzo:v0.7.42
|
||||
INVENTAR_APP_CPUS=1.0
|
||||
INVENTAR_APP_MEM_LIMIT=384m
|
||||
INVENTAR_APP_MEM_SWAP_LIMIT=768m
|
||||
INVENTAR_WORKERS=4
|
||||
INVENTAR_THREADS=2
|
||||
INVENTAR_WORKER_TIMEOUT=30
|
||||
INVENTAR_WORKER_CONNECTIONS=100
|
||||
@@ -1,4 +1,4 @@
|
||||
name: https://github.com/AIIrondev/legendary-octo-garbanzo
|
||||
name: Release Inventarsystem
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -25,6 +25,7 @@ env:
|
||||
|
||||
jobs:
|
||||
release-docker:
|
||||
# Hinweis: Falls dein lokaler Gitea-Runner ein anderes Label hat (z.B. 'linux' oder 'self-hosted'), passe dies hier an.
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -34,18 +35,20 @@ jobs:
|
||||
- name: Set metadata
|
||||
id: meta
|
||||
env:
|
||||
# Gitea stellt das GITHUB_TOKEN für Kompatibilität mit GitHub Actions automatisch zur Verfügung
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
BUMP_TYPE: ${{ github.event.inputs.bump || 'patch' }}
|
||||
REPO: ${{ gitea.repository }}
|
||||
EVENT_NAME: ${{ gitea.event_name }}
|
||||
REF_NAME: ${{ gitea.ref_name }}
|
||||
BUMP_TYPE: ${{ gitea.event.inputs.bump || 'patch' }}
|
||||
DOCKER_API_VERSION: '1.44'
|
||||
run: |
|
||||
if [ "$EVENT_NAME" = "push" ] && [ -n "$REF_NAME" ]; then
|
||||
TAG="$REF_NAME"
|
||||
else
|
||||
# Fetch latest release tag via GitHub API (fall back to v0.8.31)
|
||||
# Gitea API Endpunkt nutzen, um das aktuellste Release abzufragen
|
||||
latest_tag="v0.8.31"
|
||||
if meta_json=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null); then
|
||||
if meta_json=$(curl -fsSL -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/json" "https://git.invario-software.eu/api/v1/repos/$REPO/releases/latest" 2>/dev/null); then
|
||||
tag_name=$(printf "%s" "$meta_json" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)
|
||||
if [ -n "$tag_name" ]; then
|
||||
latest_tag="$tag_name"
|
||||
@@ -108,19 +111,58 @@ jobs:
|
||||
TAG="${base}.${i}"
|
||||
fi
|
||||
|
||||
IMAGE="ghcr.io/aiirondev/legendary-octo-garbanzo:${TAG}"
|
||||
# Docker Images verlangen Kleinbuchstaben. Repository-Namen daher umwandeln.
|
||||
LOWER_REPO=$(echo "$REPO" | tr '[:upper:]' '[:lower:]')
|
||||
IMAGE="git.invario-software.eu/${LOWER_REPO}:${TAG}"
|
||||
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
echo "image=$IMAGE" >> "$GITHUB_OUTPUT"
|
||||
echo "lower_repo=$LOWER_REPO" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Ensure Docker CLI is available and up to date
|
||||
run: |
|
||||
install_docker=true
|
||||
|
||||
# Prüfen, ob Docker existiert und ob die Version ausreicht
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
# Extrahiere die Major-Version (z. B. "20" aus "20.10.24" oder "26" aus "26.1.0")
|
||||
DOCKER_MAJOR=$(docker --version | grep -oE '[0-9]+' | head -n1)
|
||||
|
||||
# API 1.44 erfordert mindestens Docker v25
|
||||
if [ -n "$DOCKER_MAJOR" ] && [ "$DOCKER_MAJOR" -ge 25 ]; then
|
||||
install_docker=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$install_docker" = true ]; then
|
||||
echo "Veraltete oder fehlende Docker-Installation erkannt. Führe Update durch..."
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y curl
|
||||
# Nutzt das offizielle Docker-Skript (installiert docker-ce statt das alte docker.io)
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
elif command -v apk >/dev/null 2>&1; then
|
||||
apk update
|
||||
apk add --no-cache docker-cli
|
||||
else
|
||||
echo "Error: no supported package manager found to install docker"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Docker CLI ist bereits auf einem aktuellen Stand."
|
||||
fi
|
||||
|
||||
docker --version
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GHCR
|
||||
- name: Login to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
registry: git.invario-software.eu
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push release image
|
||||
uses: docker/build-push-action@v6
|
||||
@@ -128,10 +170,9 @@ jobs:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
load: true # Lädt das Image in den lokalen Docker-Daemon für den 'docker save' Schritt
|
||||
tags: |
|
||||
${{ steps.meta.outputs.image }}
|
||||
ghcr.io/aiirondev/legendary-octo-garbanzo:latest
|
||||
git.invario-software.eu/${{ steps.meta.outputs.lower_repo }}:latest
|
||||
|
||||
- name: Build local image tar for offline deploy
|
||||
run: |
|
||||
@@ -139,20 +180,10 @@ jobs:
|
||||
IMG="${{ steps.meta.outputs.image }}"
|
||||
TAG="${{ steps.meta.outputs.tag }}"
|
||||
|
||||
if docker image inspect "$IMG" >/dev/null 2>&1; then
|
||||
echo "Using local image $IMG"
|
||||
docker save "$IMG" | gzip > "inventarsystem-image-${TAG}.tar.gz"
|
||||
exit 0
|
||||
fi
|
||||
echo "Pulling freshly pushed image from registry: $IMG"
|
||||
docker pull "$IMG"
|
||||
|
||||
echo "Local image $IMG not found, trying to pull"
|
||||
if docker pull "$IMG" >/dev/null 2>&1; then
|
||||
docker save "$IMG" | gzip > "inventarsystem-image-${TAG}.tar.gz"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Pull failed, attempting local docker build as fallback"
|
||||
docker build -t "$IMG" .
|
||||
echo "Saving image to offline tar archive..."
|
||||
docker save "$IMG" | gzip > "inventarsystem-image-${TAG}.tar.gz"
|
||||
|
||||
- name: Create release-only docker bundle
|
||||
@@ -161,7 +192,7 @@ jobs:
|
||||
cat > release-bundle/docker-compose.yml <<EOF
|
||||
services:
|
||||
app:
|
||||
image: \${INVENTAR_APP_IMAGE:-ghcr.io/aiirondev/legendary-octo-garbanzo:${{ steps.meta.outputs.tag }}}
|
||||
image: \${INVENTAR_APP_IMAGE:-${{ steps.meta.outputs.image }}}
|
||||
container_name: inventarsystem-app
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
@@ -225,7 +256,7 @@ jobs:
|
||||
EOF
|
||||
|
||||
# Copy runtime scripts and config if present
|
||||
for f in start.sh stop.sh restart.sh backup.sh config.json update.sh; do
|
||||
for f in start.sh stop.sh restart.sh backup.sh restore.sh config.json update.sh; do
|
||||
if [ -f "$f" ]; then
|
||||
cp "$f" "release-bundle/$(basename "$f")"
|
||||
fi
|
||||
@@ -242,12 +273,10 @@ jobs:
|
||||
find release-bundle -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} \; || true
|
||||
tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle .
|
||||
|
||||
- name: Create or update GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
- name: Create or update Gitea Release
|
||||
uses: https://gitea.com/actions/gitea-release-action@v1
|
||||
with:
|
||||
tag_name: ${{ steps.meta.outputs.tag }}
|
||||
files: |
|
||||
inventarsystem-docker-bundle.tar.gz
|
||||
inventarsystem-image-${{ steps.meta.outputs.tag }}.tar.gz
|
||||
fail_on_unmatched_files: false
|
||||
generate_release_notes: true
|
||||
inventarsystem-image-${{ steps.meta.outputs.tag }}.tar.gz
|
||||
@@ -120,19 +120,19 @@ Das Inventarsystem stellt folgende Wartungsskripte bereit:
|
||||
**Option 1**
|
||||
|
||||
```bash
|
||||
wget -O - https://raw.githubusercontent.com/AIIrondev/legendary-octo-garbanzo/main/install.sh | sudo bash
|
||||
wget -O - https://git.invario-software.eu/Invario/Inventarsystem/raw/branch/main/install.sh | sudo bash
|
||||
```
|
||||
|
||||
**Option 2**
|
||||
|
||||
```bash
|
||||
curl -s https://raw.githubusercontent.com/AIIrondev/legendary-octo-garbanzo/main/install.sh | sudo bash
|
||||
curl -s https://git.invario-software.eu/Invario/Inventarsystem/raw/branch/main/install.sh | sudo bash
|
||||
```
|
||||
|
||||
Legacy-MongoDB uebernehmen und altes Host-System aufraeumen:
|
||||
|
||||
```bash
|
||||
curl -s https://raw.githubusercontent.com/AIIrondev/legendary-octo-garbanzo/main/install.sh | \
|
||||
curl -s https://git.invario-software.eu/Invario/Inventarsystem/raw/branch/main/install.sh | \
|
||||
sudo bash -s -- --migrate-legacy-db --remove-legacy-system
|
||||
```
|
||||
|
||||
|
||||
+1
-1
@@ -5180,7 +5180,7 @@ def upload_item():
|
||||
item_type_input = sanitize_form_value(request.form.get('item_type_input', ''))
|
||||
library_category = sanitize_form_value(request.form.get('library_category', ''))
|
||||
|
||||
if library_caregory != '':
|
||||
if library_category != '':
|
||||
item_is_library = True
|
||||
|
||||
try:
|
||||
|
||||
@@ -3,7 +3,12 @@ set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
COMPOSE_FILE="docker-compose-multitenant.yml"
|
||||
|
||||
# Directories
|
||||
INVOICE_ARCHIVE_DIR="${INVOICE_ARCHIVE_DIR:-/var/backups/invoice-archive}"
|
||||
FULL_BACKUP_DIR="${FULL_BACKUP_DIR:-/var/backups/inventarsystem}"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
|
||||
KEEP_DAYS="${INVOICE_KEEP_DAYS:-3650}"
|
||||
MODE="auto"
|
||||
BASE_NAME=""
|
||||
@@ -14,9 +19,7 @@ Usage: $0 [options]
|
||||
|
||||
Options:
|
||||
--invoice-archive-dir DIR Directory for invoice archive files
|
||||
(default: $INVOICE_ARCHIVE_DIR)
|
||||
--invoice-keep-days N Remove archived invoice files older than N days
|
||||
(default: $KEEP_DAYS)
|
||||
--invoice-keep-days N Remove archived files older than N days
|
||||
--mode auto|docker|host Backup mode (default: auto)
|
||||
--base-name NAME Base filename prefix for archive files
|
||||
-h, --help Show this help message
|
||||
@@ -26,127 +29,78 @@ EOF
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--invoice-archive-dir)
|
||||
INVOICE_ARCHIVE_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--invoice-keep-days)
|
||||
KEEP_DAYS="$2"
|
||||
shift 2
|
||||
;;
|
||||
--mode)
|
||||
MODE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--base-name)
|
||||
BASE_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Error: unknown option '$1'" >&2
|
||||
usage
|
||||
exit 2
|
||||
;;
|
||||
--invoice-archive-dir) INVOICE_ARCHIVE_DIR="$2"; shift 2 ;;
|
||||
--invoice-keep-days) KEEP_DAYS="$2"; shift 2 ;;
|
||||
--mode) MODE="$2"; shift 2 ;;
|
||||
--base-name) BASE_NAME="$2"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) echo "Error: unknown option '$1'" >&2; usage; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
ensure_directory() {
|
||||
mkdir -p "$INVOICE_ARCHIVE_DIR"
|
||||
mkdir -p "$FULL_BACKUP_DIR"
|
||||
}
|
||||
|
||||
cleanup_old_archives() {
|
||||
if [[ -n "$KEEP_DAYS" ]]; then
|
||||
find "$INVOICE_ARCHIVE_DIR" -maxdepth 1 -type f \( -name 'invoices-*.jsonl' -o -name 'invoices-*.csv' -o -name 'invoices-*.meta.json' \) -mtime +"$KEEP_DAYS" -print -delete || true
|
||||
find "$INVOICE_ARCHIVE_DIR" -maxdepth 1 -type f -mtime +"$KEEP_DAYS" -print -delete 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
host_backup() {
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
if ! python3 -c 'import pymongo' >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
python3 "$SCRIPT_DIR/Web/backup_invoices.py" \
|
||||
--archive-dir "$INVOICE_ARCHIVE_DIR" \
|
||||
--base-name "$BASE_NAME"
|
||||
# Cleanup old bundled backups (older than 30 days)
|
||||
find "$FULL_BACKUP_DIR" -maxdepth 1 -type f -name "full_backup_*.tar.gz" -mtime +30 -print -delete 2>/dev/null || true
|
||||
}
|
||||
|
||||
docker_backup() {
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
return 1
|
||||
fi
|
||||
if ! docker compose -f "$COMPOSE_FILE" ps -q app >/dev/null 2>&1; then
|
||||
return 1
|
||||
if ! command -v docker >/dev/null 2>&1; then return 1; fi
|
||||
|
||||
local timestamp="$(date +'%Y-%m-%d_%H-%M-%S')"
|
||||
local staging_dir="/tmp/backup_stage_$timestamp"
|
||||
|
||||
echo "[$(date +'%T')] Starting unified system backup..."
|
||||
mkdir -p "$staging_dir"
|
||||
|
||||
# 1. MongoDB Dump (into staging)
|
||||
if docker compose -f "$COMPOSE_FILE" ps -q mongodb >/dev/null 2>&1; then
|
||||
echo "[$(date +'%T')] Dumping Database..."
|
||||
docker compose -f "$COMPOSE_FILE" exec -T mongodb mongodump --archive --gzip > "$staging_dir/db.archive.gz"
|
||||
fi
|
||||
|
||||
local app_container
|
||||
app_container="$(docker compose -f "$COMPOSE_FILE" ps -q app | tr -d '[:space:]')"
|
||||
if [[ -z "$app_container" ]]; then
|
||||
return 1
|
||||
# 2. Archive Assets (into staging)
|
||||
if [ -d "./Web/uploads" ]; then
|
||||
echo "[$(date +'%T')] Archiving assets..."
|
||||
tar -czf "$staging_dir/assets.tar.gz" -C . Web/uploads Web/thumbnails Web/previews 2>/dev/null || true
|
||||
fi
|
||||
|
||||
local timestamp
|
||||
timestamp="$(date +'%Y-%m-%d_%H-%M-%S')"
|
||||
local output_dir
|
||||
local remote_base
|
||||
# 3. Archive Logs (into staging)
|
||||
if [ -d "$LOG_DIR" ]; then
|
||||
echo "[$(date +'%T')] Archiving logs..."
|
||||
tar -czf "$staging_dir/logs.tar.gz" -C "$(dirname "$LOG_DIR")" "$(basename "$LOG_DIR")"
|
||||
fi
|
||||
|
||||
output_dir="/tmp/invoice_archive_${timestamp}"
|
||||
remote_base="${output_dir}/${BASE_NAME}"
|
||||
|
||||
docker compose -f "$COMPOSE_FILE" exec -T app mkdir -p "$output_dir"
|
||||
docker compose -f "$COMPOSE_FILE" exec -T app python3 /app/Web/backup_invoices.py \
|
||||
--archive-dir "$output_dir" \
|
||||
--base-name "$BASE_NAME"
|
||||
|
||||
mkdir -p "$INVOICE_ARCHIVE_DIR"
|
||||
docker cp "$app_container":"${remote_base}.jsonl" "$INVOICE_ARCHIVE_DIR/"
|
||||
docker cp "$app_container":"${remote_base}.csv" "$INVOICE_ARCHIVE_DIR/"
|
||||
docker cp "$app_container":"${remote_base}.meta.json" "$INVOICE_ARCHIVE_DIR/"
|
||||
|
||||
docker compose -f "$COMPOSE_FILE" exec -T app rm -rf "$output_dir"
|
||||
# 4. Bundle everything into one file
|
||||
echo "[$(date +'%T')] Bundling archive..."
|
||||
tar -czf "$FULL_BACKUP_DIR/full_backup_$timestamp.tar.gz" -C "$staging_dir" .
|
||||
|
||||
# 5. Cleanup staging
|
||||
rm -rf "$staging_dir"
|
||||
|
||||
echo "[$(date +'%T')] Backup complete: $FULL_BACKUP_DIR/full_backup_$timestamp.tar.gz"
|
||||
return 0
|
||||
}
|
||||
|
||||
main() {
|
||||
if [[ -z "$BASE_NAME" ]]; then
|
||||
BASE_NAME="invoices-$(date +'%Y-%m-%d_%H-%M-%S')"
|
||||
fi
|
||||
|
||||
parse_args "$@"
|
||||
ensure_directory
|
||||
|
||||
case "$MODE" in
|
||||
auto)
|
||||
auto|docker)
|
||||
if docker_backup; then
|
||||
cleanup_old_archives
|
||||
return 0
|
||||
fi
|
||||
if host_backup; then
|
||||
cleanup_old_archives
|
||||
return 0
|
||||
fi
|
||||
echo "Error: could not perform invoice backup in auto mode. Docker or host Python with pymongo is required." >&2
|
||||
return 1
|
||||
;;
|
||||
docker)
|
||||
if docker_backup; then
|
||||
cleanup_old_archives
|
||||
return 0
|
||||
fi
|
||||
echo "Error: docker backup failed or app container is unavailable." >&2
|
||||
return 1
|
||||
;;
|
||||
host)
|
||||
if host_backup; then
|
||||
cleanup_old_archives
|
||||
return 0
|
||||
fi
|
||||
echo "Error: host backup failed. Ensure python3 and pymongo are installed." >&2
|
||||
echo "Error: Docker backup failed." >&2
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
@@ -157,5 +111,4 @@ main() {
|
||||
esac
|
||||
}
|
||||
|
||||
parse_args "$@"
|
||||
main
|
||||
main "$@"
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
"username": "",
|
||||
"password": "",
|
||||
"from_address": "",
|
||||
"default_sender_name": "Invario Inventurprogramm",
|
||||
"default_sender_name": "Invario Inventarprogramm",
|
||||
"timeout_seconds": 30
|
||||
},
|
||||
"images": {
|
||||
|
||||
+15
-14
@@ -8,8 +8,8 @@ else
|
||||
INSTALLER_DIR="$(pwd)"
|
||||
fi
|
||||
PROJECT_DIR="/opt/Inventarsystem"
|
||||
REPO_SLUG="AIIrondev/legendary-octo-garbanzo"
|
||||
API_URL="https://api.github.com/repos/$REPO_SLUG/releases/latest"
|
||||
REPO_SLUG="Invario/Inventarsystem"
|
||||
API_URL="https://git.invario-software.eu/api/v1/repos/$REPO_SLUG/releases/latest"
|
||||
BUNDLE_ASSET="inventarsystem-docker-bundle.tar.gz"
|
||||
APP_IMAGE_ASSET_PREFIX="inventarsystem-image-"
|
||||
LEGACY_DB_NAME="Inventarsystem"
|
||||
@@ -39,7 +39,7 @@ need_cmd() {
|
||||
|
||||
refresh_start_script_from_main() {
|
||||
local start_url
|
||||
start_url="https://raw.githubusercontent.com/$REPO_SLUG/main/start.sh"
|
||||
start_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/start.sh"
|
||||
|
||||
if curl -fsSL "$start_url" -o "$TMP_DIR/start.sh"; then
|
||||
sudo install -m 755 "$TMP_DIR/start.sh" "$PROJECT_DIR/start.sh"
|
||||
@@ -62,7 +62,7 @@ import re
|
||||
import sys
|
||||
|
||||
compose_file, tag = sys.argv[1], sys.argv[2]
|
||||
target_image = f"ghcr.io/aiirondev/legendary-octo-garbanzo:{tag}"
|
||||
target_image = f"git.invario-software.eu/invario/inventarsystem:{tag}"
|
||||
|
||||
with open(compose_file, "r", encoding="utf-8") as f:
|
||||
lines = f.readlines()
|
||||
@@ -173,9 +173,9 @@ Usage: $0 [options]
|
||||
Options:
|
||||
--migrate-legacy-db Back up host MongoDB and import into Docker MongoDB
|
||||
--remove-legacy-system Remove old host MongoDB/system after successful import
|
||||
--skip-cleanup-old Do not run cleanup-old.sh after install
|
||||
--cleanup-old-remove-cron Also remove matching cron entries during old-system cleanup
|
||||
--multitenant Use docker-compose-multitenant.yml (default)
|
||||
--skip-cleanup-old Do not run cleanup-old.sh after install
|
||||
--cleanup-old-remove-cron Also remove matching cron entries during old-system cleanup
|
||||
--multitenant Use docker-compose-multitenant.yml (default)
|
||||
--legacy-db-name <name> Legacy database name (default: $LEGACY_DB_NAME)
|
||||
--legacy-mongo-uri <uri> Legacy Mongo URI (default: $LEGACY_MONGO_URI)
|
||||
--legacy-system-dir <path> Optional old system directory to remove after migration
|
||||
@@ -432,8 +432,9 @@ main() {
|
||||
|
||||
curl -fL "$image_url" -o "$TMP_DIR/inventarsystem-image-$tag.tar.gz"
|
||||
sudo docker load -i "$TMP_DIR/inventarsystem-image-$tag.tar.gz" >/dev/null
|
||||
# Compatibility alias: some legacy compose bundles may still reference :latest.
|
||||
sudo docker tag "ghcr.io/aiirondev/legendary-octo-garbanzo:$tag" "ghcr.io/aiirondev/legendary-octo-garbanzo:latest" >/dev/null 2>&1 || true
|
||||
|
||||
# Tagge das geladene Gitea-Image als latest
|
||||
sudo docker tag "git.invario-software.eu/invario/inventarsystem:$tag" "git.invario-software.eu/invario/inventarsystem:latest" >/dev/null 2>&1 || true
|
||||
|
||||
if [ ! -f "$PROJECT_DIR/start.sh" ]; then
|
||||
echo "Error: release bundle is missing start.sh"
|
||||
@@ -470,19 +471,19 @@ EOF
|
||||
NUITKA_BUILD=0
|
||||
INVENTAR_HTTP_PORT=10000
|
||||
INVENTAR_HTTPS_PORT=10001
|
||||
INVENTAR_APP_IMAGE=ghcr.io/aiirondev/legendary-octo-garbanzo:$tag
|
||||
INVENTAR_APP_IMAGE=git.invario-software.eu/invario/inventarsystem:$tag
|
||||
EOF
|
||||
sudo install -m 644 "$TMP_DIR/.docker-build.env" "$PROJECT_DIR/.docker-build.env"
|
||||
elif sudo grep -q '^INVENTAR_APP_IMAGE=' "$PROJECT_DIR/.docker-build.env"; then
|
||||
sudo sed -i "s|^INVENTAR_APP_IMAGE=.*|INVENTAR_APP_IMAGE=ghcr.io/aiirondev/legendary-octo-garbanzo:$tag|" "$PROJECT_DIR/.docker-build.env"
|
||||
sudo sed -i "s|^INVENTAR_APP_IMAGE=.*|INVENTAR_APP_IMAGE=git.invario-software.eu/invario/inventarsystem:$tag|" "$PROJECT_DIR/.docker-build.env"
|
||||
else
|
||||
echo "INVENTAR_APP_IMAGE=ghcr.io/aiirondev/legendary-octo-garbanzo:$tag" | sudo tee -a "$PROJECT_DIR/.docker-build.env" >/dev/null
|
||||
echo "INVENTAR_APP_IMAGE=git.invario-software.eu/invario/inventarsystem:$tag" | sudo tee -a "$PROJECT_DIR/.docker-build.env" >/dev/null
|
||||
fi
|
||||
|
||||
backup_legacy_database
|
||||
|
||||
echo "Starting stack..."
|
||||
sudo env INVENTAR_APP_IMAGE="ghcr.io/aiirondev/legendary-octo-garbanzo:$tag" bash "$PROJECT_DIR/start.sh"
|
||||
sudo env INVENTAR_APP_IMAGE="git.invario-software.eu/invario/inventarsystem:$tag" bash "$PROJECT_DIR/start.sh"
|
||||
|
||||
restore_legacy_backup_into_docker
|
||||
cleanup_old_services
|
||||
@@ -492,4 +493,4 @@ EOF
|
||||
echo "Open: https://localhost"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
main "$@"
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
BACKUP_DIR="/var/backups/inventarsystem"
|
||||
COMPOSE_FILE="docker-compose-multitenant.yml"
|
||||
|
||||
# 1. Find the latest backup bundle
|
||||
LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/full_backup_*.tar.gz | head -n1 2>/dev/null || true)
|
||||
|
||||
if [[ -z "$LATEST_BACKUP" ]]; then
|
||||
echo "Error: No backup bundle found in $BACKUP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "--- RESTORE PROCEDURE ---"
|
||||
echo "Found latest bundle: $(basename "$LATEST_BACKUP")"
|
||||
read -p "WARNING: This will OVERWRITE your current database and assets! Continue? (y/N) " confirm
|
||||
[[ "$confirm" != "y" ]] && exit 1
|
||||
|
||||
# 2. Extract the bundle to a temporary location
|
||||
RESTORE_TMP="/tmp/restore_$(date +%s)"
|
||||
mkdir -p "$RESTORE_TMP"
|
||||
echo "Extracting bundle..."
|
||||
tar -xzf "$LATEST_BACKUP" -C "$RESTORE_TMP"
|
||||
|
||||
# 3. Stop application
|
||||
echo "Stopping application..."
|
||||
docker compose -f "$COMPOSE_FILE" stop app
|
||||
|
||||
# 4. Restore Database
|
||||
if [ -f "$RESTORE_TMP/db.archive.gz" ]; then
|
||||
echo "Restoring MongoDB..."
|
||||
zcat "$RESTORE_TMP/db.archive.gz" | docker compose -f "$COMPOSE_FILE" exec -T mongodb mongorestore --archive --gzip --drop
|
||||
else
|
||||
echo "Warning: Database archive not found in bundle."
|
||||
fi
|
||||
|
||||
# 5. Restore Assets
|
||||
if [ -f "$RESTORE_TMP/assets.tar.gz" ]; then
|
||||
echo "Restoring Assets (Uploads/Thumbnails/Previews)..."
|
||||
tar -xzf "$RESTORE_TMP/assets.tar.gz" -C .
|
||||
else
|
||||
echo "Warning: Asset archive not found in bundle."
|
||||
fi
|
||||
|
||||
# 6. Restore Logs (Optional)
|
||||
if [ -f "$RESTORE_TMP/logs.tar.gz" ]; then
|
||||
echo "Restoring Logs..."
|
||||
tar -xzf "$RESTORE_TMP/logs.tar.gz" -C .
|
||||
fi
|
||||
|
||||
# 7. Start application
|
||||
echo "Restarting application..."
|
||||
docker compose -f "$COMPOSE_FILE" start app
|
||||
|
||||
# 8. Cleanup
|
||||
rm -rf "$RESTORE_TMP"
|
||||
echo "Restore complete!"
|
||||
@@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
ENV_FILE="$SCRIPT_DIR/.docker-build.env"
|
||||
APP_IMAGE_REPO="ghcr.io/aiirondev/legendary-octo-garbanzo"
|
||||
APP_IMAGE_REPO="git.invario-software.eu/invario/inventarsystem"
|
||||
DIST_DIR="$SCRIPT_DIR/dist"
|
||||
RUNTIME_COMPOSE_OVERRIDE_FILE="$SCRIPT_DIR/.docker-compose.runtime.override.yml"
|
||||
|
||||
@@ -676,4 +676,4 @@ fi
|
||||
verify_stack_health
|
||||
|
||||
echo "Stack started."
|
||||
echo "Open: http://<server-ip>:$HTTP_PORT_VALUE"
|
||||
echo "Open: http://<server-ip>:$HTTP_PORT_VALUE"
|
||||
@@ -2,18 +2,18 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Release-only updater for Docker deployment.
|
||||
# Updates are pulled exclusively from GitHub Releases assets.
|
||||
# Updates are pulled exclusively from Gitea Releases assets.
|
||||
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOG_DIR="$PROJECT_DIR/logs"
|
||||
LOG_FILE="$LOG_DIR/update.log"
|
||||
STATE_FILE="$PROJECT_DIR/.release-version"
|
||||
REPO_SLUG="AIIrondev/legendary-octo-garbanzo"
|
||||
API_URL="https://api.github.com/repos/$REPO_SLUG/releases/latest"
|
||||
REPO_SLUG="Invario/Inventarsystem"
|
||||
API_URL="https://git.invario-software.eu/api/v1/repos/$REPO_SLUG/releases/latest"
|
||||
BUNDLE_ASSET="inventarsystem-docker-bundle.tar.gz"
|
||||
APP_IMAGE_ASSET_PREFIX="inventarsystem-image-"
|
||||
ENV_FILE="$PROJECT_DIR/.docker-build.env"
|
||||
APP_IMAGE_REPO="ghcr.io/aiirondev/legendary-octo-garbanzo"
|
||||
APP_IMAGE_REPO="git.invario-software.eu/invario/inventarsystem"
|
||||
DIST_DIR="$PROJECT_DIR/dist"
|
||||
COMPOSE_FILE="docker-compose-multitenant.yml"
|
||||
MIN_ROOT_FREE_MB="${INVENTAR_MIN_ROOT_FREE_MB:-2048}"
|
||||
@@ -153,7 +153,7 @@ Usage: $0 [options]
|
||||
|
||||
Options:
|
||||
--multitenant Use docker-compose-multitenant.yml (default)
|
||||
development Install development build from GHCR or local dist
|
||||
development Install development build from Gitea Registry or local dist
|
||||
-h, --help Show this help message
|
||||
EOF
|
||||
}
|
||||
@@ -204,14 +204,14 @@ create_backup() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -x "$PROJECT_DIR/run-backup.sh" ]; then
|
||||
if "$PROJECT_DIR/run-backup.sh" >> "$LOG_FILE" 2>&1; then
|
||||
if [ -x "$PROJECT_DIR/backup.sh" ]; then
|
||||
if "$PROJECT_DIR/backup.sh" --mode auto >> "$LOG_FILE" 2>&1; then
|
||||
log_message "Backup completed"
|
||||
else
|
||||
log_message "WARNING: Backup failed; continuing with release update"
|
||||
fi
|
||||
else
|
||||
log_message "WARNING: run-backup.sh not found; skipping backup"
|
||||
log_message "WARNING: backup.sh not found; skipping backup"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -275,10 +275,10 @@ load_release_image() {
|
||||
|
||||
refresh_runtime_scripts_from_main() {
|
||||
local start_url stop_url restart_url update_url
|
||||
start_url="https://raw.githubusercontent.com/$REPO_SLUG/main/start.sh"
|
||||
stop_url="https://raw.githubusercontent.com/$REPO_SLUG/main/stop.sh"
|
||||
restart_url="https://raw.githubusercontent.com/$REPO_SLUG/main/restart.sh"
|
||||
update_url="https://raw.githubusercontent.com/$REPO_SLUG/main/update.sh"
|
||||
start_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/start.sh"
|
||||
stop_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/stop.sh"
|
||||
restart_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/restart.sh"
|
||||
update_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/update.sh"
|
||||
|
||||
curl -fsSL "$start_url" -o "$PROJECT_DIR/start.sh" || log_message "WARNING: Could not refresh start.sh from main"
|
||||
curl -fsSL "$stop_url" -o "$PROJECT_DIR/stop.sh" || log_message "WARNING: Could not refresh stop.sh from main"
|
||||
@@ -357,7 +357,7 @@ download_and_extract_bundle() {
|
||||
cp -f "$tmp_dir/update.sh" "$PROJECT_DIR/update.sh"
|
||||
fi
|
||||
|
||||
# Neu: Multi-Tenant Ressourcen kopieren, falls vorhanden
|
||||
# Multi-Tenant Ressourcen kopieren, falls vorhanden
|
||||
if [ -f "$tmp_dir/docker-compose-multitenant.yml" ]; then
|
||||
cp -f "$tmp_dir/docker-compose-multitenant.yml" "$PROJECT_DIR/docker-compose-multitenant.yml"
|
||||
fi
|
||||
@@ -374,7 +374,7 @@ download_and_extract_bundle() {
|
||||
done
|
||||
|
||||
# Ensure executable permissions on all copied scripts
|
||||
chmod +x "$PROJECT_DIR/start.sh" "$PROJECT_DIR/stop.sh" "$PROJECT_DIR/restart.sh" "$PROJECT_DIR/update.sh" "$PROJECT_DIR/backup.sh" "$PROJECT_DIR/manage-tenant.sh" "$PROJECT_DIR/run-tenant-cmd.sh" 2>/dev/null || true 2>/dev/null || true
|
||||
chmod +x "$PROJECT_DIR/start.sh" "$PROJECT_DIR/stop.sh" "$PROJECT_DIR/restart.sh" "$PROJECT_DIR/update.sh" "$PROJECT_DIR/backup.sh" "$PROJECT_DIR/manage-tenant.sh" "$PROJECT_DIR/run-tenant-cmd.sh" 2>/dev/null || true
|
||||
chmod +x "$PROJECT_DIR"/manage-tenant.sh "$PROJECT_DIR"/run-tenant-cmd.sh 2>/dev/null || true
|
||||
|
||||
if [ ! -f "$PROJECT_DIR/config.json" ] && [ -f "$tmp_dir/config.json" ]; then
|
||||
@@ -412,7 +412,7 @@ EOF
|
||||
|
||||
if ! load_local_dist_image "$tag"; then
|
||||
if ! load_release_image "$meta_file" "$tag"; then
|
||||
log_message "Falling back to tagged GHCR image $app_image"
|
||||
log_message "Falling back to tagged Gitea Registry image $app_image"
|
||||
if ! docker pull "$app_image" >> "$LOG_FILE" 2>&1; then
|
||||
log_message "Falling back to local Docker build for $app_image"
|
||||
docker build -t "$app_image" "$PROJECT_DIR" >> "$LOG_FILE" 2>&1
|
||||
@@ -511,7 +511,7 @@ EOF
|
||||
printf '\nINVENTAR_APP_IMAGE=%s\n' "$app_image" >> "$ENV_FILE"
|
||||
fi
|
||||
|
||||
# Try local dist first, then pull from GHCR
|
||||
# Try local dist first, then pull from Gitea Registry
|
||||
if ! load_local_dist_image "$tag"; then
|
||||
log_message "Attempting to pull development image $app_image"
|
||||
if ! docker pull "$app_image" >> "$LOG_FILE" 2>&1; then
|
||||
@@ -540,7 +540,7 @@ EOF
|
||||
|
||||
trap 'rm -rf "${tmp_dir:-}"' EXIT
|
||||
|
||||
log_message "Checking latest GitHub release for $REPO_SLUG..."
|
||||
log_message "Checking latest Gitea release for $REPO_SLUG..."
|
||||
if ! fetch_release_metadata "$meta_file"; then
|
||||
log_message "WARNING: Could not fetch release metadata. Falling back to self-healing start path."
|
||||
if INVENTAR_SETUP_CRON=0 bash "$PROJECT_DIR/start.sh" >> "$LOG_FILE" 2>&1; then
|
||||
@@ -623,7 +623,7 @@ EOF
|
||||
log_message "Update completed successfully to release $latest_tag"
|
||||
|
||||
sudo ./opt/Inventarsystem/restart.sh
|
||||
echo "Restart of the Server Completet"
|
||||
echo "Restart of the Server Completed"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user