Skip to content

feat: auto-update system, background command execution, standard classes refactor, and more#58

Open
mstrhakr wants to merge 143 commits intomainfrom
dev
Open

feat: auto-update system, background command execution, standard classes refactor, and more#58
mstrhakr wants to merge 143 commits intomainfrom
dev

Conversation

@mstrhakr
Copy link
Owner

@mstrhakr mstrhakr commented Mar 16, 2026

Summary

This PR promotes the dev beta track to stable. It has been running in production on the beta channel with good results.

Note: The PLG file in this diff shows dev branch metadata (version, pluginURL) because it reflects the last beta build on the dev branch. On merge to main, the tag-release.yml -> build.yml CI pipeline automatically generates a stable version tag, builds the package, and updates the PLG with the stable version, MD5, and main branch URL.


Issues Addressed


What's New

Auto-Update System

A full auto-update feature for Docker Compose stacks - compares pinned/digest hashes, runs on a configurable cron schedule, and exposes full UI controls.

  • Per-stack enable/disable toggles with toggle-all header control
  • Scheduler on/off switch with configurable cron interval
  • "Run Now" button with serialized requests to avoid server overload
  • Digest-based comparison to detect real image changes
  • Log sanitization for disallowed paths
  • Path validation and writable-directory checks throughout
  • autoupdate.json config with JSON validation and safe crontab removal

Background Compose Command Execution (Background Actions)

Compose commands (up, down, pull, etc.) now run in the background with async logging and browser notifications, so the UI is no longer blocked during long operations.

  • Per-stack failure isolation in multi-stack runs - one failure no longer kills the whole batch
  • Clearer per-stack output in ttyd multi-stack runs
  • View the last command log per stack to see how the commands played out.
  • Background action queue + status history for long-running compose jobs and retry/failover behavior.

Standard Classes Refactor (ContainerInfo / StackInfo)

Introduces proper PHP classes to normalize container and stack data throughout the backend.

  • Consistent camelCase property names replacing ad-hoc array keys
  • StackInfo caching with cache management methods
  • StackInfo::createNew() internalized with improved folder naming and input validation
  • OverrideInfo decoupled from stack identity resolution
  • Container ID coerced to string before truncation - fixes crash on missing IDs
  • Pinned digest preserved through toUpdateArray so update badges retain context
  • Restored container discovery and pinned digest display after the refactor

Override Management

  • Centralized override management via OverrideInfo class
  • pruneOrphanOverrideServices() automatically removes stale service entries from override files on compose up
  • Service rename detection preserves user labels/icons across renames

Security

  • isIndirect() path validation hardened with additional checks
  • Added isValidPath() / isAllowedPath() methods to Util
  • All autoupdate paths validated before use; log messages sanitized

UI Fixes

  • Re-entrant detail reloads prevented during container rendering
  • Spinner updated for backup actions with better visibility
  • Auto-update settings layout and styling improvements

Build & CI

  • Dynamic version loading from versions.env in build scripts
  • SkipTests parameter added to build script for faster iteration
  • Workflow permissions fixed (code scanning alert resolved)
  • FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 standardized across all workflows
  • Beta releases now gated on open PR from dev ΓåÆ main
  • Beta changelog includes PR link and diff against latest stable

Tests

  • BATS setup script added; test framework loading path fixed
  • AutoupdateTest aligned with path validation and encoding changes
  • Config file override pattern in PHPUnit teardown; env var cleanup
  • phpunit.xml failOnWarning set to false to unblock CI

mstrhakr and others added 30 commits March 15, 2026 21:04
Introduce centralized ContainerInfo and StackInfo PHP classes in util.php
that normalize container identity and stack metadata across the codebase.

PHP changes:
- ContainerInfo: PascalCase->camelCase normalization, fromDockerInspect(),
  fromUpdateResponse(), mergeUpdateStatus(), toArray(), toUpdateArray(),
  automatic isPinned derivation from @sha256: in image reference
- StackInfo: eager identity (project, sanitizedName, path, composeSource,
  composeFilePath, isIndirect, overrideInfo) with lazy metadata getters
  (getName, getDescription, getEnvFilePath, getIconUrl, getWebUIUrl,
  getDefaultProfiles, getAutostart, getStartedAt, getProfiles),
  getDefinedServices(), buildComposeArgs(), pruneOrphanOverrideServices()

Migrated PHP callers:
- exec.php: getStackContainers, checkStackUpdates, checkAllStacksUpdates
- exec_functions.php: buildComposeArgs() now thin deprecated wrapper
- compose_util_functions.php: echoComposeCommand, echoComposeCommandMultiple
- compose_list.php: all inline metadata reads replaced with StackInfo
- dashboard_stacks.php: metadata reads replaced with StackInfo

JS changes:
- Added createContainerInfo(), createStackInfo(), mergeStackUpdateStatus()
  factory functions for consistent client-side normalization
- Migrated buildStackInfoFromCache() to use createStackInfo()
- Migrated checkStackUpdates() inline construction to createStackInfo()
- Migrated updateParentStackFromContainers() to mergeStackUpdateStatus()
- Replaced both PascalCase normalization blocks with createContainerInfo()
- Updated mergeUpdateStatus() to use createContainerInfo() for name matching

Tests:
- ContainerInfoTest: 22 tests covering both factories, merge, serialization
- StackInfoTest: 33 tests covering identity, compose resolution, metadata,
  caching, and buildComposeArgs
- All 304 existing tests pass (0 failures, 7 pre-existing skips)
- Remove unnecessary Object.assign merging of PascalCase originals
- Align JS createContainerInfo shell default to '/bin/bash'
- Add @ to file_get_contents in StackInfo constructor
- Make OverrideInfo::getDefinedServices() private
- Fix htmlspecialchars(null) deprecation in compose_list.php
- Remove extra blank doc-comment lines in OverrideInfo::resolve()
- Add OverrideInfo::fromStackInfo() as primary factory that accepts
  pre-resolved StackInfo fields, eliminating duplicate filesystem I/O
- Extract resolveOverride() as shared core for both factory paths
- Deprecate OverrideInfo::fromStack() (kept for backward compat)
- Remove $composeRoot, getProjectPath(), getDefinedServices() from
  OverrideInfo — these were stack-level concerns
- Simplify pruneOrphanServices() to accept string[] instead of
  resolving services internally
- Add getMainFileServices() to StackInfo for pruning without override
- Replace remaining OverrideInfo::fromStack() calls in exec.php with
  StackInfo::fromProject()
- Fix addStack passing display name instead of folder basename
- Add StackInfo::clearCache() to test setUp methods
Move stack directory creation logic from the exec.php addStack handler
into a new StackInfo::createNew() static factory method. This centralizes
folder naming, collision avoidance, compose/indirect file wiring, metadata
writes, and override initialization inside the domain class that already
models these artifacts.

- Add StackInfo::createNew() with folder sanitization, collision handling,
  indirect support, and metadata file creation
- Move sanitizeFolderName() to util.php (backward-compat stub in
  exec_functions.php)
- Reduce addStack case to input validation + factory call + JSON response
- Add 10 unit tests covering createNew() scenarios (basic, indirect,
  collision, description, caching, override init)
- Prevent compounded random suffixes on folder name collisions by always appending a single random suffix to the base name
- Add safety cap to collision attempts to avoid infinite loops
- Validate empty and whitespace stack names, throwing clear exceptions
- Add tests for empty name, whitespace name, and collision suffix behavior
- sanitizeFolderName: block path traversal (/, \, ..)
- StackInfo::createNew: add defense-in-depth path validation
- Fix error message trailing period mismatch with tests
- Use COMPOSE_FILE_NAMES[0] instead of hard-coded compose.yaml
- Sanitize exception messages returned to client (hide filesystem paths)
- Introduced deploy.ps1 script for building and deploying the compose.manager package to Unraid servers.
- Created autoupdate.php to handle configuration retrieval, saving, and cron job management for auto-updates.
- Implemented autoupdate_runner.php to execute scheduled updates based on autoupdate.json configuration.
- Added compose_projects.php to list available Docker Compose projects.
- Developed compose_autoupdate.sh script to perform the actual Docker Compose update process.
- Created unit tests for autoupdate_runner.php and autoupdate.php to ensure functionality and error handling.
- Fix path boundary check in isAllowedAutoUpdatePath() to prevent false
  positives (e.g. /mnt/compose_root_evil matching /mnt/compose_root)
- Switch cron install/remove/status to use crontab marker blocks instead
  of /etc/cron.d, which is not persistent across Unraid reboots
- Fix scheduling timing: use last_run tracking so any configured time
  triggers correctly regardless of the 15-minute cron polling interval
- Validate and sanitize time format in autoupdate_runner.php before use
- Validate stack paths in autoupdate_runner.php against compose_root
  before executing scheduled updates
- Validate stack path keys in saveConfig to prevent security bypass
- Add flock-based locking to compose_autoupdate.sh to prevent race
  conditions with concurrent stack operations
- Remove unused PLUGIN_ROOT variable from compose_autoupdate.sh
- Fix JSON double-parse in loadUpdatesUI() and refreshCronStatus()
  since jQuery auto-parses JSON responses from Content-Type headers
- Escape time value in Updates tab table rows to prevent stored XSS
@mstrhakr mstrhakr changed the title feat: auto-update system, background command execution, and standard classes refactor feat: auto-update system, background command execution, standard classes refactor, and more Mar 20, 2026
@mstrhakr
Copy link
Owner Author

I will wait one more week before merge. Only bug fixes from here out. If you have any issues with the beta please comment here over posting an issue.

mstrhakr and others added 26 commits March 22, 2026 12:37
… visibility, used docker mangers css for this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment