The backward-compatible next() method is no longer needed since all
call sites have been updated to use the clearer method names:
- completeDeployment()
- failDeployment()
- transitionToStatus()
This completes the refactoring to make status transitions more explicit
and maintainable.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem:**
Deployment failure notifications were not being sent due to two bugs:
1. **Timing Issue in next() function:**
- When failed() called next(FAILED), the database still had status "in_progress"
- The notification check looked for ALREADY failed status (not found yet)
- Status was updated AFTER the check, losing the notification
2. **Direct Status Update:**
- Healthcheck failures directly updated status to FAILED
- Bypassed next() entirely, no notification sent
**Solution:**
Refactored status transition logic with clear separation of concerns:
- Moved notification logic AFTER status update (not before)
- Created transitionToStatus() as single source of truth
- Added completeDeployment() and failDeployment() for clarity
- Extracted status-specific side effects into dedicated methods
- Updated healthcheck failure to use failDeployment()
**Benefits:**
- ✅ Notifications sent for ALL failure scenarios
- ✅ Clear, self-documenting method names
- ✅ Single responsibility per method
- ✅ Type-safe using enum instead of strings
- ✅ Harder to bypass notification logic accidentally
- ✅ Backward compatible (old next() preserved)
**Changed:**
- app/Jobs/ApplicationDeploymentJob.php (+101/-21 lines)
Fixes#6911🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Problem
Scheduled tasks, backups, and auto-updates stopped working after 1-2 months
with error: MaxAttemptsExceededException: App\Jobs\ScheduledJobManager has
been attempted too many times.
Root cause: ScheduledJobManager used WithoutOverlapping with only
releaseAfter(60), causing locks without expiration (TTL=-1) that persisted
indefinitely when jobs hung or processes crashed.
## Solution
### Part 1: Prevention (Future Locks)
- Added expireAfter(60) to ScheduledJobManager middleware
- Lock now auto-expires after 60 seconds (matches everyMinute schedule)
- Changed from releaseAfter(60) to expireAfter(60)->dontRelease()
- Follows Laravel best practices and matches other Coolify jobs
### Part 2: Recovery (Existing Locks)
- Enhanced cleanup:redis command with --clear-locks flag
- Scans Redis for stale locks (TTL=-1) and removes them
- Called automatically during app:init on startup/upgrade
- Provides immediate recovery for affected instances
## Changes
- app/Jobs/ScheduledJobManager.php: Added expireAfter(60)->dontRelease()
- app/Console/Commands/CleanupRedis.php: Added cleanupCacheLocks() method
- app/Console/Commands/Init.php: Auto-clear locks on startup
- tests/Unit/ScheduledJobManagerLockTest.php: Test to prevent regression
- STALE_LOCK_FIX.md: Complete documentation
## Testing
- Unit tests pass (2 tests, 8 assertions)
- Code formatted with Pint
- Matches pattern used by CleanupInstanceStuffsJob
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, the bash escaping functions (`escapeBashEnvValue()` and `escapeBashDoubleQuoted()`) had strict string type hints that rejected null values, causing deployment failures when environment variables had null values.
Changes:
- Updated both functions to accept nullable strings (`?string $value`)
- Handle null/empty values by returning empty quoted strings (`''` for single quotes, `""` for double quotes)
- Added 3 new tests to cover null and empty value handling
- All 29 tests pass
This fix ensures deployments work correctly even when environment variables have null values, while maintaining the existing behavior for all other cases.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Two improvements to Git deployment handling:
1. **ApplicationDeploymentJob.php**:
- Fixed log message to show actual resolved commit SHA (`$this->commit`)
- Previously showed `$this->application->git_commit_sha` which could be "HEAD"
- Now displays the actual 40-character commit SHA that will be deployed
2. **Application.php (generateGitLsRemoteCommands)**:
- Added `escapeshellarg()` for repository URL in 'other' deployment type
- Prevents shell injection in git ls-remote commands
- Complements existing shell escaping in `generateGitImportCommands`
- Ensures consistent security across all Git operations
**Security Impact:**
- All Git commands now use properly escaped repository URLs
- Prevents command injection through malicious repository URLs
- Consistent escaping in both ls-remote and clone operations
**User Experience:**
- Deployment logs now show exact commit SHA being deployed
- More accurate debugging information for deployment issues
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes pure Dockerfile deployment failing with 'env file not found' error.
The deploy_simple_dockerfile() method was missing the call to
save_runtime_environment_variables() which creates the .env file
needed during the rolling update phase. This call is present in
all other deployment methods (dockerfile, dockercompose, nixpacks,
static) but was missing here.
This ensures the .env file exists when docker compose tries to
use --env-file during the rolling update.
- Strip leading slashes from publish_directory to prevent /app// paths
- Only add slash prefix if directory is not empty
- Ensures clean Docker COPY paths in build output
Fixes deployment failures when Git repositories redirect (e.g., tangled.sh → tangled.org)
and improves security by adding proper shell escaping for repository URLs.
**Root Cause:**
Git redirect warnings can appear on the same line as ls-remote output with no newline:
`warning: redirecting to https://tangled.org/...196d3df... refs/heads/master`
The previous parsing logic split by newlines and extracted text before tabs, which
included the entire warning message instead of just the 40-character commit SHA.
**Changes:**
1. **Fixed commit SHA extraction** (ApplicationDeploymentJob.php):
- Changed from line-based parsing to regex pattern matching
- Uses `/([0-9a-f]{40})\s*\t/` to find valid 40-char hex commit SHA before tab
- Handles warnings on same line, separate lines, multiple warnings, and whitespace
- Added comprehensive Ray debug logs for troubleshooting
2. **Added security fix** (Application.php):
- Added `escapeshellarg()` for repository URLs in 'other' deployment type
- Prevents shell injection and fixes parsing issues with special characters like `@`
- Added Ray debug logs for deployment type tracking
3. **Comprehensive test coverage** (GitLsRemoteParsingTest.php):
- Tests normal output without warnings
- Tests redirect warning on separate line
- Tests redirect warning on same line (actual tangled.sh format)
- Tests multiple warning lines
- Tests extra whitespace handling
**Resolves:**
- Linear issue COOLGH-53: Valid git URLs are rejected as being invalid
- GitHub issue #6568: tangled.sh deployments failing
- Handles Git redirects universally for all Git hosting services
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add support for QUEUED, KILLED, and CANCELLED statuses
- Replace if-elseif chain with match expression for better exhaustiveness
- Add appropriate emoji indicators for each status
- Ensure all ProcessStatus enum values are handled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed backup_log_uuid property to nullable and removed eager initialization in constructor. This allows the ID to be generated when actually needed rather than upfront.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added actual HTTP POST delivery for webhook notifications and comprehensive Ray debugging for development.
Changes:
- Updated Team model to implement SendsWebhook interface
- Added routeNotificationForWebhook() method to Team
- Enhanced SendWebhookJob with Ray logging for request/response
- Added Ray debugging to WebhookChannel for dispatch tracking
- Added Ray debugging to Webhook Livewire component
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated the build_logs_url to use the correct environment UUID instead of the environment name, ensuring accurate links to deployment logs.
- This change improves the reliability of the deployment notification system by directing users to the correct log location.
- Introduced a new notification class, BackupSuccessWithS3Warning, to alert users when local backups succeed but S3 uploads fail.
- Updated DatabaseBackupJob to track local backup success and handle S3 upload errors, improving error reporting and user notifications.
- Modified ScheduledDatabaseBackupExecution model to include a new s3_uploaded boolean field for tracking S3 upload status.
- Adjusted views and validation logic to reflect changes in backup execution status and S3 handling.
- Added tests to ensure the new s3_uploaded column is correctly implemented and validated.
- Updated the should_skip_build method to save runtime environment variables even when the build step is skipped, ensuring that the latest environment settings are preserved.
- Enhanced logging in prepare_builder_image to differentiate between the first attempt and subsequent attempts, improving clarity in deployment logs.
- Implemented a check for the NIXPACKS_NODE_VERSION variable in the ApplicationDeploymentJob.
- Added log entries to notify users when NIXPACKS_NODE_VERSION is not set, indicating that Node.js 18 will be used by default, which is EOL.
- Provided guidance on how to override the default version by setting NIXPACKS_NODE_VERSION in environment variables.
- Refactored the DatabaseBackupJob to replace instances of backup->uuid with backup_log_uuid for consistency in container naming.
- Ensured that all related Docker commands and processes reference the updated backup_log_uuid, improving clarity and reducing potential errors during backup operations.
- Changed the .env file reference to use a build-time .env file located in /artifacts, preventing it from being included in Docker images.
- Introduced a new method to wrap Docker build commands with environment variable exports, enhancing the handling of build-time variables.
- Updated logging messages for clarity regarding the creation and usage of the build-time .env file.
- Replaced the use of a dynamic env_filename with a consistent .env file reference across deployment methods.
- Simplified the generation and saving of build-time and runtime environment variables, ensuring they are always written to the .env file.
- Enhanced clarity in the deployment process by removing redundant logic and ensuring environment variables are handled uniformly.
- Removed redundant logic for merging COOLIFY_* variables into env_args.
- Simplified the process of adding environment variables by directly incorporating generated COOLIFY environment variables.
- Enhanced clarity and maintainability of the generate_env_variables method.
- Added a new method to restart the builder container with the actual commit value, ensuring accurate deployment.
- Improved the generation of environment variables by consolidating user-defined and Coolify-specific variables.
- Updated Dockerfile modification logic to handle environment variables more effectively, including support for multiline variables.
- Enhanced logging for better visibility during deployment processes.
- Introduced new helper functions to generate Docker build arguments and environment flags, accommodating multiline variables with proper escaping.
- Updated the ApplicationDeploymentJob to utilize these new functions, improving the handling of environment variables during deployment.
- Added comprehensive tests to ensure correct behavior for multiline variables and special characters.
- Introduced functionality to add Coolify variables as ARGs in the Dockerfile during the build process.
- Enhanced the existing method to handle both standard environment variables and Coolify-specific variables, improving deployment flexibility.
- Introduced logic to filter user-defined build time variables from the database based on the pull request context.
- Improved handling of build time variables to ensure only relevant variables are analyzed, enhancing the deployment process.
- Added logic to escape single quotes in build arguments to ensure proper execution in bash -c context used by executeInDocker, preventing potential command errors.
- Added retry configuration with a maximum of 3 attempts and backoff intervals of 10, 30, and 60 seconds to improve job resilience and handling of transient failures.