From 80262aca9be96eae19ad91a43ac6efe8cc433256 Mon Sep 17 00:00:00 2001 From: AIIrondev Date: Wed, 5 Aug 2026 20:14:41 +0200 Subject: [PATCH] additiopn of a deverlopment mode --- .github/workflows/release-docker.yml | 44 ++++++++- update.sh | 138 ++++++++++++++++++++++++--- 2 files changed, 169 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index 4d8f772..0426625 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -4,6 +4,8 @@ on: push: tags: - "v*" + branches: + - develop workflow_dispatch: inputs: bump: @@ -39,11 +41,36 @@ jobs: EVENT_NAME: ${{ gitea.event_name }} REF_NAME: ${{ gitea.ref_name }} BUMP_TYPE: ${{ gitea.event.inputs.bump || 'patch' }} + RUN_NUMBER: ${{ gitea.run_number }} DOCKER_API_VERSION: '1.44' run: | - if [ "$EVENT_NAME" = "push" ] && [ -n "$REF_NAME" ]; then + if [ "$EVENT_NAME" = "push" ] && [ "$REF_NAME" = "develop" ]; then + prerelease=true + latest_tag="v0.8.31" + 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" + fi + fi + + if [[ "$latest_tag" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + major=${BASH_REMATCH[1]} + minor=${BASH_REMATCH[2]} + patch=${BASH_REMATCH[3]} + else + major=0 + minor=8 + patch=31 + fi + + patch=$((patch + 1)) + TAG="v${major}.${minor}.${patch}-dev.${RUN_NUMBER:-0}" + elif [ "$EVENT_NAME" = "push" ] && [ -n "$REF_NAME" ]; then + prerelease=false TAG="$REF_NAME" else + prerelease=false latest_tag="v0.8.31" 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) @@ -67,7 +94,7 @@ jobs: else patch=$((patch + 1)) fi - + TAG="v${major}.${minor}.${patch}" fi @@ -109,6 +136,7 @@ jobs: echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "image=$IMAGE" >> "$GITHUB_OUTPUT" echo "lower_repo=$LOWER_REPO" >> "$GITHUB_OUTPUT" + echo "prerelease=$prerelease" >> "$GITHUB_OUTPUT" - name: Ensure Docker CLI is available and up to date run: | @@ -148,6 +176,7 @@ jobs: password: ${{ secrets.REGISTRY_TOKEN }} - name: Build and push release image + if: steps.meta.outputs.prerelease != 'true' uses: docker/build-push-action@v6 with: context: . @@ -157,6 +186,16 @@ jobs: ${{ steps.meta.outputs.image }} git.invario-software.eu/${{ steps.meta.outputs.lower_repo }}:latest + - name: Build and push prerelease image + if: steps.meta.outputs.prerelease == 'true' + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ steps.meta.outputs.image }} + - name: Create release-only docker bundle run: | mkdir -p release-bundle @@ -253,5 +292,6 @@ jobs: uses: https://gitea.com/actions/gitea-release-action@v1 with: tag_name: ${{ steps.meta.outputs.tag }} + prerelease: ${{ steps.meta.outputs.prerelease }} files: | inventarsystem-docker-bundle.tar.gz \ No newline at end of file diff --git a/update.sh b/update.sh index 4f25be8..970011e 100755 --- a/update.sh +++ b/update.sh @@ -9,13 +9,13 @@ LOG_DIR="$PROJECT_DIR/logs" LOG_FILE="$LOG_DIR/update.log" STATE_FILE="$PROJECT_DIR/.release-version" REPO_SLUG="Invario/Inventarsystem" -API_URL="https://git.invario-software.eu/api/v1/repos/$REPO_SLUG/releases/latest" +API_BASE_URL="https://git.invario-software.eu/api/v1/repos/$REPO_SLUG" BUNDLE_ASSET="inventarsystem-docker-bundle.tar.gz" ENV_FILE="$PROJECT_DIR/.docker-build.env" APP_IMAGE_REPO="git.invario-software.eu/invario/inventarsystem" COMPOSE_FILE="docker-compose-multitenant.yml" MIN_ROOT_FREE_MB="${INVENTAR_MIN_ROOT_FREE_MB:-2048}" -MODE="release" +MODE="stable" mkdir -p "$LOG_DIR" chmod 777 "$LOG_DIR" 2>/dev/null || true @@ -119,6 +119,7 @@ usage() { Usage: $0 [options] Options: + -dev Install the latest prerelease build --multitenant Use docker-compose-multitenant.yml (default) -h, --help Show this help message EOF @@ -127,6 +128,10 @@ EOF parse_args() { while [[ $# -gt 0 ]]; do case "$1" in + -dev) + MODE="development" + shift + ;; --multitenant) COMPOSE_FILE="docker-compose-multitenant.yml" shift @@ -179,7 +184,8 @@ create_backup() { fetch_release_metadata() { local meta_file="$1" - curl -fsSL "$API_URL" -o "$meta_file" + local endpoint="${2:-latest}" + curl -fsSL "$API_BASE_URL/releases/$endpoint" -o "$meta_file" } parse_latest_tag() { @@ -207,6 +213,89 @@ for asset in data.get('assets', []): PY } +parse_release_tag() { + local meta_file="$1" + python3 - <<'PY' "$meta_file" +import json, sys +with open(sys.argv[1], 'r', encoding='utf-8') as f: + data = json.load(f) +print(data.get('tag_name', '').strip()) +PY +} + +parse_prerelease_flag() { + local meta_file="$1" + python3 - <<'PY' "$meta_file" +import json, sys +with open(sys.argv[1], 'r', encoding='utf-8') as f: + data = json.load(f) +print('true' if data.get('prerelease') else 'false') +PY +} + +latest_stable_release() { + local meta_file="$1" + local releases_file="$2" + local release_count=0 + + if ! curl -fsSL "$API_BASE_URL/releases" -o "$releases_file"; then + return 1 + fi + + if ! python3 - <<'PY' "$releases_file" "$meta_file" +import json, sys +releases_path, target_path = sys.argv[1], sys.argv[2] +with open(releases_path, 'r', encoding='utf-8') as f: + releases = json.load(f) +for release in releases: + if not release.get('prerelease') and not release.get('draft'): + with open(target_path, 'w', encoding='utf-8') as out: + json.dump(release, out) + raise SystemExit(0) +raise SystemExit(1) +PY + then + return 1 + fi + return 0 +} + +latest_prerelease() { + local meta_file="$1" + local releases_file="$2" + + if ! curl -fsSL "$API_BASE_URL/releases" -o "$releases_file"; then + return 1 + fi + + if ! python3 - <<'PY' "$releases_file" "$meta_file" +import json, sys +releases_path, target_path = sys.argv[1], sys.argv[2] +with open(releases_path, 'r', encoding='utf-8') as f: + releases = json.load(f) +for release in releases: + if release.get('prerelease') and not release.get('draft'): + with open(target_path, 'w', encoding='utf-8') as out: + json.dump(release, out) + raise SystemExit(0) +raise SystemExit(1) +PY + then + return 1 + fi + return 0 +} + +fetch_latest_release_bundle() { + local release_meta="$1" + local bundle_url + bundle_url="$(parse_asset_url "$release_meta" "$BUNDLE_ASSET")" + if [ -z "$bundle_url" ]; then + return 1 + fi + printf '%s' "$bundle_url" +} + refresh_runtime_scripts_from_main() { local start_url stop_url restart_url update_url start_url="https://git.invario-software.eu/$REPO_SLUG/raw/branch/main/start.sh" @@ -368,12 +457,36 @@ main() { archive_logs create_backup - # If user requested a development install, perform a simple dev deploy flow + # If user requested a development install, deploy the latest prerelease. if [ "$MODE" = "development" ]; then log_message "Requested development install" - local tag="dev" - local app_image="$APP_IMAGE_REPO:$tag" - local compose_path="$PROJECT_DIR/$COMPOSE_FILE" + local tag meta_file releases_file bundle_url app_image compose_path + local tmp_dir + + tmp_dir="$(mktemp -d)" + meta_file="$tmp_dir/prerelease.json" + releases_file="$tmp_dir/releases.json" + trap 'rm -rf "${tmp_dir:-}"' EXIT + + if ! latest_prerelease "$meta_file" "$releases_file"; then + log_message "ERROR: Could not find a prerelease in Gitea" + exit 1 + fi + + tag="$(parse_release_tag "$meta_file")" + if [ -z "$tag" ]; then + log_message "ERROR: Could not determine prerelease tag" + exit 1 + fi + + bundle_url="$(fetch_latest_release_bundle "$meta_file")" + if [ -z "$bundle_url" ]; then + log_message "ERROR: Prerelease asset not found: $BUNDLE_ASSET" + exit 1 + fi + + app_image="$APP_IMAGE_REPO:$tag" + compose_path="$PROJECT_DIR/$COMPOSE_FILE" if [ ! -f "$compose_path" ]; then log_message "ERROR: compose file not found: $compose_path" @@ -399,6 +512,9 @@ EOF exit 1 fi + download_and_extract_bundle "$bundle_url" "$tmp_dir" + refresh_runtime_scripts_from_main + # Bring up stack docker compose -f "$compose_path" --env-file "$ENV_FILE" pull mongodb redis >> "$LOG_FILE" 2>&1 || true docker compose -f "$compose_path" --env-file "$ENV_FILE" up -d --remove-orphans >> "$LOG_FILE" 2>&1 @@ -409,7 +525,7 @@ EOF fi echo "$tag" > "$STATE_FILE" - log_message "Development update completed successfully" + log_message "Development update completed successfully to prerelease $tag" exit 0 fi @@ -419,8 +535,8 @@ EOF trap 'rm -rf "${tmp_dir:-}"' EXIT - log_message "Checking latest Gitea release for $REPO_SLUG..." - if ! fetch_release_metadata "$meta_file"; then + log_message "Checking latest stable Gitea release for $REPO_SLUG..." + if ! fetch_release_metadata "$meta_file" "latest"; 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 if verify_stack_health; then @@ -436,7 +552,7 @@ EOF exit 0 fi - latest_tag="$(parse_latest_tag "$meta_file")" + latest_tag="$(parse_release_tag "$meta_file")" if [ -z "$latest_tag" ]; then log_message "WARNING: Could not determine latest release tag. Falling back to self-healing start path." if INVENTAR_SETUP_CRON=0 bash "$PROJECT_DIR/start.sh" >> "$LOG_FILE" 2>&1; then