Преглед изворни кода

Add daily beta build publish script

  Builds multi-arch Docker image from the current APP_VERSION in config.py
  and pushes to GHCR + Docker Hub, overwriting the same beta tag. Creates
  or updates a GitHub prerelease with changelog notes. Users re-pull the
  tag or use Watchtower to get daily updates. Supports --parallel,
  --ghcr-only, --dockerhub-only, and --skip-release flags. Documents
  daily beta builds in README and DOCKERHUB.md.
maziggy пре 2 месеци
родитељ
комит
6a4d890176
2 измењених фајлова са 73 додато и 132 уклоњено
  1. 1 1
      CHANGELOG.md
  2. 72 131
      docker-publish-daily-beta.sh

+ 1 - 1
CHANGELOG.md

@@ -12,7 +12,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **SpoolBuddy AMS Page: External Slots & Slot Configuration** — The SpoolBuddy AMS page (`/spoolbuddy/ams`) now displays external spool slots (single nozzle: "Ext", dual nozzle: "Ext-L"/"Ext-R") and AMS-HT units in a compact horizontal row below the regular AMS grid, fitting within the 1024×600 kiosk display without scrolling. Clicking any AMS, AMS-HT, or external slot opens the `ConfigureAmsSlotModal` to configure filament type and color — the same modal used on the main Printers page. Dual-nozzle printers show L/R nozzle badges on each AMS unit. Temperature and humidity are displayed with threshold-colored SVG icons (green/gold/red) matching the Bambu Lab style on the main printer cards, using the configured AMS humidity and temperature thresholds from settings.
 - **SpoolBuddy Dashboard Redesign** — Redesigned the SpoolBuddy dashboard with a two-column layout: left column shows device connection status (scale and NFC with state-colored icons — green when device is online, gray when offline) and a compact printers list with live status indicators; right column shows the current spool card. Cards use a dashed border style for a cleaner look. The large weight display card was removed in favor of the inline scale reading in the device card.
 - **SpoolBuddy Kiosk Auth Bypass via API Key** — When Bambuddy auth is enabled, the SpoolBuddy kiosk (Chromium on RPi) was redirected to the login page because the `ProtectedRoute` requires a user object from `GET /auth/me`, which only accepted JWT tokens. The `/auth/me` endpoint now also accepts API keys (via `Authorization: Bearer bb_xxx` or `X-API-Key` header) and returns a synthetic admin user with all permissions. The frontend's `AuthContext` reads an optional `?token=` URL parameter on first load, stores it in localStorage, and strips it from the URL to prevent leakage via browser history or referrer. The install script now includes the API key in the kiosk URL (`/spoolbuddy?token=${API_KEY}`), so the device authenticates automatically on boot without manual login.
-- **Daily Beta Builds** — Added a release script (`docker-publish-daily-beta.sh`) that automates the full beta release workflow: version bump, changelog date update, git tag, multi-arch Docker build+push to both GHCR and Docker Hub, and GitHub prerelease creation with changelog notes. Beta images use version tags (e.g., `0.2.2b2`) and are never tagged as `latest`. Users can opt in to beta update notifications via Settings → Updates → "Include beta versions".
+- **Daily Beta Builds** — Added a release script (`docker-publish-daily-beta.sh`) that reads the current `APP_VERSION` from config, builds a multi-arch Docker image, pushes to both GHCR and Docker Hub, and creates/updates a GitHub prerelease with changelog notes. Daily builds overwrite the same beta version tag (e.g., `0.2.2b1`) — users pull the latest by re-pulling the tag or using Watchtower. Beta images are never tagged as `latest`.
 
 ### Fixed
 - **Printer Card Loses Info When Print Is Paused** ([#562](https://github.com/maziggy/bambuddy/issues/562)) — When a print was paused (via G-code pause command or user action), the printer card showed the print as finished — the progress bar, print name, ETA, layer count, and cover image all disappeared, replaced by the idle "Ready to Print" placeholder. The display conditions only checked for `state === 'RUNNING'` but not `'PAUSE'`, even though other parts of the same page (Skip Objects button, Stop/Resume controls) already handled both states correctly. Now shows print progress info for both `RUNNING` and `PAUSE` states, and the status label correctly reads "Paused" instead of the hardcoded "Printing" fallback.

+ 72 - 131
docker-publish-daily-beta.sh

@@ -1,27 +1,22 @@
 #!/bin/bash
-# Daily beta build: bump version, build Docker, push to registries, create GitHub release
+# Daily beta build: build Docker image, push to registries, create/update GitHub prerelease
 #
 # Usage:
-#   ./docker-publish-daily-beta.sh <version> [--parallel] [--ghcr-only] [--dockerhub-only] [--skip-release]
+#   ./docker-publish-daily-beta.sh [--parallel] [--ghcr-only] [--dockerhub-only] [--skip-release]
 #
 # Examples:
-#   ./docker-publish-daily-beta.sh 0.2.2b2                  # Full release workflow
-#   ./docker-publish-daily-beta.sh 0.2.2b2 --parallel       # Build both archs simultaneously
-#   ./docker-publish-daily-beta.sh 0.2.2b2 --ghcr-only      # Only push to GHCR
-#   ./docker-publish-daily-beta.sh 0.2.2b2 --dockerhub-only # Only push to Docker Hub
-#   ./docker-publish-daily-beta.sh 0.2.2b2 --skip-release   # Build+push without GitHub release
+#   ./docker-publish-daily-beta.sh                  # Full daily beta workflow
+#   ./docker-publish-daily-beta.sh --parallel       # Build both archs simultaneously
+#   ./docker-publish-daily-beta.sh --ghcr-only      # Only push to GHCR
+#   ./docker-publish-daily-beta.sh --dockerhub-only # Only push to Docker Hub
+#   ./docker-publish-daily-beta.sh --skip-release   # Build+push without GitHub release
 #
-# This script performs the full daily beta release workflow:
-#   1. Validate version (must be beta: X.Y.Zb<N>)
-#   2. Bump APP_VERSION in backend/app/core/config.py
-#   3. Update CHANGELOG.md date
-#   4. Git commit + tag
-#   5. Build & push multi-arch Docker images
-#   6. Create GitHub prerelease with changelog notes
-#   7. Verify manifests and release
+# Reads APP_VERSION from backend/app/core/config.py (must be a beta version like 0.2.2b1).
+# Builds and pushes a multi-arch Docker image tagged with that version, overwriting any
+# previous image with the same tag. Optionally creates/updates a GitHub prerelease.
 #
-# Beta versions are never tagged as 'latest'. The in-app update checker uses
-# version string parsing (not GitHub's prerelease flag) to detect betas.
+# Beta versions are never tagged as 'latest'. Users update by pulling the same tag
+# (e.g., docker pull ghcr.io/maziggy/bambuddy:0.2.2b1) or using Watchtower.
 #
 # Prerequisites:
 #   1. Log in to ghcr.io:
@@ -57,7 +52,6 @@ BLUE='\033[0;34m'
 NC='\033[0m' # No Color
 
 # Parse arguments
-VERSION=""
 PARALLEL=false
 PUSH_GHCR=true
 PUSH_DOCKERHUB=true
@@ -76,112 +70,48 @@ for arg in "$@"; do
         --skip-release)
             SKIP_RELEASE=true
             ;;
+        --help|-h)
+            echo "Usage: $0 [--parallel] [--ghcr-only] [--dockerhub-only] [--skip-release]"
+            echo ""
+            echo "Build and publish a daily beta Docker image using the APP_VERSION from config.py."
+            echo ""
+            echo "Options:"
+            echo "  --parallel       Build both architectures simultaneously"
+            echo "  --ghcr-only      Only push to GitHub Container Registry"
+            echo "  --dockerhub-only Only push to Docker Hub"
+            echo "  --skip-release   Build+push without creating/updating GitHub release"
+            echo "  --help, -h       Show this help"
+            exit 0
+            ;;
         *)
-            if [ -z "$VERSION" ]; then
-                VERSION="$arg"
-            fi
+            echo -e "${RED}Unknown argument: $arg${NC}"
+            echo "Run $0 --help for usage"
+            exit 1
             ;;
     esac
 done
 
-if [ -z "$VERSION" ]; then
-    echo -e "${YELLOW}Usage: $0 <version> [--parallel] [--ghcr-only] [--dockerhub-only] [--skip-release]${NC}"
-    echo ""
-    echo "Examples:"
-    echo "  $0 0.2.2b2                  # Full release workflow"
-    echo "  $0 0.2.2b2 --parallel       # Build both archs simultaneously"
-    echo "  $0 0.2.2b2 --ghcr-only      # Only push to GHCR"
-    echo "  $0 0.2.2b2 --dockerhub-only # Only push to Docker Hub"
-    echo "  $0 0.2.2b2 --skip-release   # Build+push without GitHub release"
-    exit 1
-fi
-
 # ============================================================
-# Step 1: Validate version
+# Step 1: Read and validate APP_VERSION
 # ============================================================
-echo -e "${BLUE}[1/7] Validating version...${NC}"
+echo -e "${BLUE}[1/4] Validating APP_VERSION...${NC}"
 
-if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+b[0-9]+$ ]]; then
-    echo -e "${RED}Error: Version must be a beta version matching X.Y.Zb<N> (e.g., 0.2.2b2)${NC}"
-    echo "Got: $VERSION"
-    exit 1
-fi
+VERSION=$(grep -oP 'APP_VERSION = "\K[^"]+' "$CONFIG_FILE")
 
-# Check for clean working tree
-if [ -n "$(git status --porcelain)" ]; then
-    echo -e "${RED}Error: Git working tree is not clean. Commit or stash changes first.${NC}"
-    git status --short
+if [ -z "$VERSION" ]; then
+    echo -e "${RED}Error: Could not read APP_VERSION from ${CONFIG_FILE}${NC}"
     exit 1
 fi
 
-echo -e "${GREEN}  Version: ${VERSION} (valid beta)${NC}"
-echo -e "${GREEN}  Working tree: clean${NC}"
-
-# ============================================================
-# Step 2: Bump APP_VERSION in config.py
-# ============================================================
-echo -e "${BLUE}[2/7] Bumping APP_VERSION...${NC}"
-
-CURRENT_VERSION=$(grep -oP 'APP_VERSION = "\K[^"]+' "$CONFIG_FILE")
-echo "  Current: $CURRENT_VERSION"
-echo "  New:     $VERSION"
-
-sed -i "s/^APP_VERSION = \".*\"/APP_VERSION = \"${VERSION}\"/" "$CONFIG_FILE"
-
-# Verify the replacement
-NEW_VERSION=$(grep -oP 'APP_VERSION = "\K[^"]+' "$CONFIG_FILE")
-if [ "$NEW_VERSION" != "$VERSION" ]; then
-    echo -e "${RED}Error: Failed to update APP_VERSION in ${CONFIG_FILE}${NC}"
+if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+b[0-9]+$ ]]; then
+    echo -e "${RED}Error: APP_VERSION '${VERSION}' is not a beta version (expected X.Y.Zb<N>)${NC}"
     exit 1
 fi
-echo -e "${GREEN}  Updated ${CONFIG_FILE}${NC}"
-
-# ============================================================
-# Step 3: Update CHANGELOG.md date
-# ============================================================
-echo -e "${BLUE}[3/7] Updating CHANGELOG.md...${NC}"
-
-TODAY=$(date +%Y-%m-%d)
-
-# Check if the changelog already has this version with a date
-if grep -qP "^## \[${VERSION}\] - \d{4}-\d{2}-\d{2}" "$CHANGELOG_FILE"; then
-    echo -e "${YELLOW}  CHANGELOG already has ${VERSION} with a date — skipping${NC}"
-else
-    # Replace "Unreleased" or "Unrelased" (handles typo) for any version header
-    sed -i -E "s/^## \[[^]]+\] - Unreleas?ed$/## [${VERSION}] - ${TODAY}/" "$CHANGELOG_FILE"
-
-    # Verify
-    if grep -q "^## \[${VERSION}\] - ${TODAY}" "$CHANGELOG_FILE"; then
-        echo -e "${GREEN}  Updated to: ## [${VERSION}] - ${TODAY}${NC}"
-    else
-        echo -e "${YELLOW}  Warning: No 'Unreleased' header found to update${NC}"
-        echo "  You may need to manually update CHANGELOG.md"
-    fi
-fi
 
-# ============================================================
-# Step 4: Git commit + tag
-# ============================================================
-echo -e "${BLUE}[4/7] Creating git commit and tag...${NC}"
-
-git add "$CONFIG_FILE" "$CHANGELOG_FILE"
-
-if git diff --cached --quiet; then
-    echo -e "${YELLOW}  No changes to commit (version may already be set)${NC}"
-else
-    git commit -m "Release v${VERSION}"
-    echo -e "${GREEN}  Committed: Release v${VERSION}${NC}"
-fi
-
-if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
-    echo -e "${YELLOW}  Tag v${VERSION} already exists — skipping${NC}"
-else
-    git tag "v${VERSION}"
-    echo -e "${GREEN}  Tagged: v${VERSION}${NC}"
-fi
+echo -e "${GREEN}  APP_VERSION: ${VERSION}${NC}"
 
 # ============================================================
-# Step 5: Build & push Docker images
+# Step 2: Build & push Docker images
 # ============================================================
 echo ""
 
@@ -189,7 +119,7 @@ echo ""
 CPU_COUNT=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
 
 echo -e "${GREEN}================================================${NC}"
-echo -e "${GREEN}  Building daily beta Docker image${NC}"
+echo -e "${GREEN}  Daily beta build${NC}"
 echo -e "${GREEN}  Version: ${VERSION}${NC}"
 echo -e "${GREEN}  Platforms: ${PLATFORMS}${NC}"
 echo -e "${GREEN}  CPU cores: ${CPU_COUNT}${NC}"
@@ -227,7 +157,7 @@ if [ "$PUSH_DOCKERHUB" = true ]; then
 fi
 
 # Setup buildx builder if not exists
-echo -e "${BLUE}[5/7] Setting up Docker Buildx and building...${NC}"
+echo -e "${BLUE}[2/4] Setting up Docker Buildx and building...${NC}"
 if ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then
     echo "Creating new buildx builder: $BUILDER_NAME (optimized for ${CPU_COUNT} cores)"
     docker buildx create \
@@ -341,14 +271,14 @@ else
 fi
 
 # ============================================================
-# Step 6: Create GitHub release
+# Step 3: Create/update GitHub release
 # ============================================================
 if [ "$SKIP_RELEASE" = true ]; then
-    echo -e "${YELLOW}[6/7] Skipping GitHub release (--skip-release)${NC}"
+    echo -e "${YELLOW}[3/4] Skipping GitHub release (--skip-release)${NC}"
 else
-    echo -e "${BLUE}[6/7] Creating GitHub release...${NC}"
+    echo -e "${BLUE}[3/4] Creating/updating GitHub release...${NC}"
 
-    # Extract release notes from CHANGELOG: content between ## [<version>] and the next ## [
+    # Extract release notes from CHANGELOG: content between ## [<version>] and the next ## [ heading
     CHANGELOG_NOTES=$(sed -n "/^## \[${VERSION}\]/,/^## \[/{/^## \[/!p}" "$CHANGELOG_FILE" | sed '/^$/d; 1{/^$/d}')
 
     if [ -z "$CHANGELOG_NOTES" ]; then
@@ -372,16 +302,17 @@ docker pull maziggy/bambuddy:${VERSION}"
     fi
 
     # Create the release body
+    TODAY=$(date +%Y-%m-%d)
     RELEASE_BODY=$(cat <<EOF
 > [!NOTE]
-> This is a **daily beta build**. It contains the latest fixes and improvements but may have undiscovered issues.
+> This is a **daily beta build** (${TODAY}). It contains the latest fixes and improvements but may have undiscovered issues.
 >
 > **Docker users:** Update by pulling the new image:
 > \`\`\`
 > ${PULL_COMMANDS}
 > \`\`\`
 >
-> **To receive beta update notifications in Bambuddy:** Enable *"Include beta versions"* in Settings → Updates.
+> **Tip:** Use [Watchtower](https://containrrr.dev/watchtower/) to automatically update when new daily builds are pushed.
 
 ---
 
@@ -389,28 +320,38 @@ ${CHANGELOG_NOTES}
 EOF
     )
 
-    # Push the tag to remote
-    echo "  Pushing tag v${VERSION} to remote..."
-    git push origin "v${VERSION}"
-
-    # Push the commit to remote
-    CURRENT_BRANCH=$(git branch --show-current)
-    echo "  Pushing ${CURRENT_BRANCH} to remote..."
-    git push origin "${CURRENT_BRANCH}"
+    # Check if release already exists
+    if gh release view "v${VERSION}" >/dev/null 2>&1; then
+        echo "  Updating existing release v${VERSION}..."
+        gh release edit "v${VERSION}" \
+            --title "Daily Beta Build v${VERSION} (${TODAY})" \
+            --prerelease \
+            --notes "$RELEASE_BODY"
+        echo -e "${GREEN}  Updated GitHub release: v${VERSION}${NC}"
+    else
+        echo "  Creating new release v${VERSION}..."
 
-    # Create GitHub release
-    gh release create "v${VERSION}" \
-        --title "Daily Beta Build v${VERSION}" \
-        --prerelease \
-        --notes "$RELEASE_BODY"
+        # Ensure the tag exists on remote
+        if ! git ls-remote --tags origin "v${VERSION}" | grep -q "v${VERSION}"; then
+            echo "  Creating and pushing tag v${VERSION}..."
+            if ! git rev-parse "v${VERSION}" >/dev/null 2>&1; then
+                git tag "v${VERSION}"
+            fi
+            git push origin "v${VERSION}"
+        fi
 
-    echo -e "${GREEN}  Created GitHub release: v${VERSION}${NC}"
+        gh release create "v${VERSION}" \
+            --title "Daily Beta Build v${VERSION} (${TODAY})" \
+            --prerelease \
+            --notes "$RELEASE_BODY"
+        echo -e "${GREEN}  Created GitHub release: v${VERSION}${NC}"
+    fi
 fi
 
 # ============================================================
-# Step 7: Verify
+# Step 4: Verify
 # ============================================================
-echo -e "${BLUE}[7/7] Verifying...${NC}"
+echo -e "${BLUE}[4/4] Verifying...${NC}"
 
 if [ "$PUSH_GHCR" = true ]; then
     echo -e "${BLUE}GHCR manifest:${NC}"