<# .SYNOPSIS Re-deploy a Coolify application from a previous commit SHA. .DESCRIPTION Implements the rollback path: 1. Force-push the target commit SHA to a new branch `rollback/` on the origin remote (does NOT touch the main branch). 2. PATCH the Coolify application to point at the rollback branch + SHA, OR update only git_commit_sha if the SHA is reachable from the currently configured branch. 3. Trigger a fresh deploy. This script does NOT rewrite public history. To avoid surprises, it always asks for confirmation before pushing or deploying unless -Force is given. .PARAMETER AppPath Local path of the project Git repo. Defaults to current directory. .PARAMETER CommitSha Target commit SHA to roll back to (full or short). If omitted, prints the last 10 commits so you can choose. .PARAMETER ApplicationUuid Coolify application UUID to update and redeploy. .PARAMETER Branch Branch currently configured in Coolify for this app. Default: 'main'. .PARAMETER Force Skip confirmation prompts. .EXAMPLE .\Invoke-CoolifyRollback.ps1 -ApplicationUuid og88wk4 -CommitSha a1b2c3d #> param( [string]$AppPath = ".", [string]$CommitSha, [Parameter(Mandatory = $true)] [string]$ApplicationUuid, [string]$Branch = "main", [switch]$Force ) $ErrorActionPreference = "Stop" $here = Split-Path -Parent $MyInvocation.MyCommand.Path $coolifyApi = Join-Path $here "..\..\coolify_skill\scripts\Invoke-CoolifyApi.ps1" if (-not (Test-Path -LiteralPath $coolifyApi)) { throw "Invoke-CoolifyApi.ps1 not found at: $coolifyApi" } $appPath = (Resolve-Path -LiteralPath $AppPath).Path function Confirm-Step([string]$Action) { if ($Force) { return $true } $r = Read-Host "Confirm: $Action`nProceed? (y/N)" return ($r -match '^(y|yes|s|si|sí)$') } Write-Host "Recent commits in $appPath :" -ForegroundColor Cyan $commits = git -C $appPath log --oneline -10 $commits | ForEach-Object { Write-Host " $_" } if (-not $CommitSha) { $CommitSha = Read-Host "`nEnter commit SHA to roll back to" } if (-not $CommitSha) { throw "No commit SHA provided." } $fullSha = git -C $appPath rev-parse $CommitSha 2>$null if (-not $fullSha) { throw "Could not resolve commit: $CommitSha" } Write-Host "`nResolved SHA: $fullSha" -ForegroundColor Green $originUrl = git -C $appPath remote get-url origin 2>$null if (-not $originUrl) { throw "No 'origin' remote configured in $appPath" } Write-Host "Origin: $originUrl" $rollbackBranch = "rollback/$($fullSha.Substring(0,8))" if (-not (Confirm-Step "Push commit $fullSha to new branch '$rollbackBranch' on origin")) { throw "Aborted by user." } git -C $appPath branch -f $rollbackBranch $fullSha | Out-Null git -C $appPath push origin $rollbackBranch 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor DarkGray } if ($LASTEXITCODE -ne 0) { throw "git push failed." } Write-Host "Pushed $rollbackBranch." -ForegroundColor Green if (-not (Confirm-Step "PATCH /applications/$ApplicationUuid (git_branch=$rollbackBranch, git_commit_sha=$fullSha)")) { throw "Aborted by user." } $body = @{ git_branch = $rollbackBranch git_commit_sha = $fullSha } | ConvertTo-Json -Compress & $coolifyApi -Method PATCH -Path "/applications/$ApplicationUuid" -BodyJson $body -ErrorAction Stop | Out-Null Write-Host "Application updated." -ForegroundColor Green if (-not (Confirm-Step "Trigger DEPLOY of $ApplicationUuid at $fullSha")) { Write-Host "Skipping deploy trigger." -ForegroundColor Yellow return } $deployBody = @{ uuid = $ApplicationUuid } | ConvertTo-Json -Compress & $coolifyApi -Method POST -Path "/deploy" -BodyJson $deployBody -ErrorAction Stop Write-Host "`nRollback deploy triggered." -ForegroundColor Green Write-Host "Note: main branch on GitHub is untouched. To make this the new HEAD of main, do it explicitly:" -ForegroundColor Yellow Write-Host " git -C `"$appPath`" checkout main && git -C `"$appPath`" reset --hard $fullSha && git push --force-with-lease origin main" -ForegroundColor DarkGray