#!/bin/bash set -euo pipefail IFS=$'\n\t' # Generate PR plugin file for Unraid # Usage: ./generate-pr-plugin.sh [plugin_url] VERSION=$1 PR_NUMBER=$2 COMMIT_SHA=$3 LOCAL_TARBALL=$4 # Local file for SHA calculation REMOTE_TARBALL=$5 # Remote filename for download TXZ_URL=$6 PLUGIN_URL=${7:-""} # Optional plugin URL for updates if [ -z "$VERSION" ] || [ -z "$PR_NUMBER" ] || [ -z "$COMMIT_SHA" ] || [ -z "$LOCAL_TARBALL" ] || [ -z "$REMOTE_TARBALL" ] || [ -z "$TXZ_URL" ]; then echo "Usage: $0 [plugin_url]" exit 1 fi # If no plugin URL provided, generate one based on R2 location if [ -z "$PLUGIN_URL" ]; then # Extract base URL from TXZ_URL and use consistent filename PLUGIN_URL="${TXZ_URL%.tar.gz}.plg" fi # Use consistent filename (no version in filename, version is inside the plugin) PLUGIN_NAME="webgui-pr-${PR_NUMBER}.plg" TARBALL_SHA256=$(sha256sum "$LOCAL_TARBALL" | awk '{print $1}') echo "Generating plugin: $PLUGIN_NAME" echo "Tarball SHA256: $TARBALL_SHA256" cat > "$PLUGIN_NAME" << 'EOF' ]> ##&version; - Test build for PR #≺ (commit &commit;) - This plugin installs modified files from the PR for testing - Original files are backed up and restored upon removal "$MANIFEST" echo "Step 2: Update will now proceed with installation of new PR files..." echo "" # The update continues by running the install method which will extract new files ]]> TXZ_URL_PLACEHOLDER &sha256; "$MANIFEST" # Get file list first echo "Examining tarball contents..." tar -tzf "$TARBALL" | head -20 echo "" # Count total files FILE_COUNT=$(tar -tzf "$TARBALL" | grep -v '/$' | wc -l) echo "Total files to process: $FILE_COUNT" echo "" # Get file list tar -tzf "$TARBALL" > /tmp/plugin_files.txt # Backup original files BEFORE extraction while IFS= read -r file; do # Skip directories if [[ "$file" == */ ]]; then continue fi # The tarball contains usr/local/emhttp/... (no leading slash) # When we extract with -C /, it becomes /usr/local/emhttp/... SYSTEM_FILE="/${file}" BACKUP_FILE="$BACKUP_DIR/$(echo "$file" | tr '/' '_')" echo "Processing: $file" # Only backup if we haven't already backed up this file # (preserves original backups across updates) if [ -f "$BACKUP_FILE" ]; then echo " → Using existing backup: $BACKUP_FILE" echo "$SYSTEM_FILE|$BACKUP_FILE" >> "$MANIFEST" elif [ -f "$SYSTEM_FILE" ]; then echo " → Creating backup of original: $SYSTEM_FILE" cp -p "$SYSTEM_FILE" "$BACKUP_FILE" echo "$SYSTEM_FILE|$BACKUP_FILE" >> "$MANIFEST" else echo " → Will create new: $SYSTEM_FILE" echo "$SYSTEM_FILE|NEW" >> "$MANIFEST" fi done < /tmp/plugin_files.txt # Clean up temp file rm -f /tmp/plugin_files.txt # Extract the tarball to root with verbose output # Since tarball contains usr/local/emhttp/..., extracting to / makes it /usr/local/emhttp/... echo "" echo "Extracting files to system (verbose mode)..." echo "----------------------------------------" tar -xzvf "$TARBALL" -C / EXTRACT_STATUS=$? echo "----------------------------------------" echo "Extraction completed with status: $EXTRACT_STATUS" echo "" # Verify extraction echo "Verifying installation..." INSTALLED_COUNT=0 while IFS='|' read -r file backup; do if [ -f "$file" ]; then INSTALLED_COUNT=$((INSTALLED_COUNT + 1)) fi done < "$MANIFEST" echo "Successfully installed $INSTALLED_COUNT files" echo "" echo "✅ Installation complete!" echo "" echo "Summary:" echo "--------" echo "Files deployed: $INSTALLED_COUNT" echo "" if [ $INSTALLED_COUNT -gt 0 ]; then echo "Modified files:" while IFS='|' read -r file backup; do if [ -f "$file" ]; then if [ "$backup" == "NEW" ]; then echo " [NEW] $file" else echo " [MOD] $file" fi fi done < "$MANIFEST" else echo "⚠️ WARNING: No files were installed!" echo "Check that the tarball structure matches the expected format." fi echo "" echo "⚠️ This is a TEST plugin for PR #PR_PLACEHOLDER" echo "⚠️ Remove this plugin before applying production updates" echo "" echo "⚠️ NOTE: Under certain circumstances, it might be necessary to reboot the server for the code changes to take effect" ]]> $(function() { // Check for updates (non-dismissible) caPluginUpdateCheck("webgui-pr-PR_PLACEHOLDER.plg", {noDismiss: true},function(result){ try { let json = JSON.parse(result); if ( ! json.version ) { addBannerWarning("Note: webgui-pr-PR_PLACEHOLDER has either been merged or removed"); } } catch(e) {} }); // Create banner with uninstall link (nondismissible) let bannerMessage = "Modified GUI installed via webgui-pr-PR_PLACEHOLDER plugin. " + "Click here to uninstall"; // true = warning style, true = non-dismissible addBannerWarning(bannerMessage, true, true); // Define uninstall function window.uninstallPRPlugin = function() { swal({ title: "Uninstall PR Test Plugin?", text: "This will restore all original files and remove the test plugin.", type: "warning", showCancelButton: true, confirmButtonText: "Yes, uninstall", cancelButtonText: "Cancel", closeOnConfirm: false, showLoaderOnConfirm: true }, function(isConfirm) { if (isConfirm) { // Execute plugin removal using openPlugin (Unraid's standard method) // The "refresh" parameter will automatically reload the page when uninstall is completed openPlugin("plugin remove webgui-pr-PR_PLACEHOLDER.plg", "Removing PR Test Plugin", "", "refresh"); } }); }; }); ]]> EOF # Replace placeholders (compatible with both Linux and macOS) if [[ "$OSTYPE" == "darwin"* ]]; then # macOS requires backup extension with -i sed -i '' "s/VERSION_PLACEHOLDER/${VERSION}/g" "$PLUGIN_NAME" sed -i '' "s/REMOTE_TARBALL_PLACEHOLDER/${REMOTE_TARBALL}/g" "$PLUGIN_NAME" sed -i '' "s/SHA256_PLACEHOLDER/${TARBALL_SHA256}/g" "$PLUGIN_NAME" sed -i '' "s/PR_PLACEHOLDER/${PR_NUMBER}/g" "$PLUGIN_NAME" sed -i '' "s/COMMIT_PLACEHOLDER/${COMMIT_SHA}/g" "$PLUGIN_NAME" sed -i '' "s|TXZ_URL_PLACEHOLDER|${TXZ_URL}|g" "$PLUGIN_NAME" sed -i '' "s|PLUGIN_URL_PLACEHOLDER|${PLUGIN_URL}|g" "$PLUGIN_NAME" else # Linux sed sed -i "s/VERSION_PLACEHOLDER/${VERSION}/g" "$PLUGIN_NAME" sed -i "s/REMOTE_TARBALL_PLACEHOLDER/${REMOTE_TARBALL}/g" "$PLUGIN_NAME" sed -i "s/SHA256_PLACEHOLDER/${TARBALL_SHA256}/g" "$PLUGIN_NAME" sed -i "s/PR_PLACEHOLDER/${PR_NUMBER}/g" "$PLUGIN_NAME" sed -i "s/COMMIT_PLACEHOLDER/${COMMIT_SHA}/g" "$PLUGIN_NAME" sed -i "s|TXZ_URL_PLACEHOLDER|${TXZ_URL}|g" "$PLUGIN_NAME" sed -i "s|PLUGIN_URL_PLACEHOLDER|${PLUGIN_URL}|g" "$PLUGIN_NAME" fi echo "Plugin generated: $PLUGIN_NAME"