name: Build and Deploy CPRNIMS on: push: branches: [ main ] jobs: build-and-deploy: runs-on: windows steps: - name: Checkout uses: actions/checkout@v4 - name: Clean previous publish output shell: pwsh run: | Remove-Item -Recurse -Force "C:\ci-output\webapi" -ErrorAction SilentlyContinue Remove-Item -Recurse -Force "C:\ci-output\webapps" -ErrorAction SilentlyContinue - name: Publish WebApi shell: pwsh run: dotnet publish .\CPRNIMS.WebApi\CPRNIMS.WebApi.csproj -c Release -o C:\ci-output\webapi - name: Publish WebApps shell: pwsh run: dotnet publish .\CPRNIMS.WebApps\CPRNIMS.WebApps.csproj -c Release -o C:\ci-output\webapps # ---- Backup current live deployment before touching anything ---- - name: Backup current live files shell: pwsh run: | $stamp = Get-Date -Format "yyyyMMdd-HHmmss" New-Item -ItemType Directory -Force -Path "C:\backups\$stamp" | Out-Null # Mirror current live folders into the backup location (only if they exist / aren't empty) if (Test-Path "C:\inetpub\cprnims-api") { robocopy "C:\inetpub\cprnims-api" "C:\backups\$stamp\webapi" /MIR /R:2 /W:3 | Out-Null } if (Test-Path "C:\inetpub\cprnims-web") { robocopy "C:\inetpub\cprnims-web" "C:\backups\$stamp\webapps" /MIR /R:2 /W:3 | Out-Null } # Record this backup's timestamp so later steps know where it lives $stamp | Out-File -FilePath "C:\backups\latest.txt" -Encoding ascii -NoNewline # Keep only the last 5 backups to avoid filling the disk $all = Get-ChildItem "C:\backups" -Directory | Sort-Object Name -Descending if ($all.Count -gt 5) { $all | Select-Object -Skip 5 | Remove-Item -Recurse -Force } Write-Host "Backed up current deployment to C:\backups\$stamp" exit 0 - name: Stop app pools shell: pwsh run: | Import-Module WebAdministration Stop-WebAppPool -Name "CPRNIMS-Api" -ErrorAction SilentlyContinue Stop-WebAppPool -Name "CPRNIMS-Web" -ErrorAction SilentlyContinue Start-Sleep -Seconds 3 - name: Deploy WebApi files id: deploy_api shell: pwsh run: | robocopy "C:\ci-output\webapi" "C:\inetpub\cprnims-api" /MIR /R:3 /W:5 $rc = $LASTEXITCODE Write-Host "ROBOCOPY EXIT CODE: $rc" if ($rc -ge 8) { throw "robocopy failed for WebApi with exit code $rc" } exit 0 - name: Deploy WebApps files id: deploy_web shell: pwsh run: | robocopy "C:\ci-output\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 $rc = $LASTEXITCODE Write-Host "ROBOCOPY EXIT CODE: $rc" if ($rc -ge 8) { throw "robocopy failed for WebApps with exit code $rc" } exit 0 - name: Start app pools shell: pwsh run: | Import-Module WebAdministration Start-WebAppPool -Name "CPRNIMS-Api" Start-WebAppPool -Name "CPRNIMS-Web" - name: Verify app pools are running shell: pwsh run: | Start-Sleep -Seconds 3 Import-Module WebAdministration $api = Get-WebAppPoolState -Name "CPRNIMS-Api" $web = Get-WebAppPoolState -Name "CPRNIMS-Web" Write-Host "CPRNIMS-Api: $($api.Value)" Write-Host "CPRNIMS-Web: $($web.Value)" if ($api.Value -ne "Started" -or $web.Value -ne "Started") { throw "One or more app pools failed to start" } # ---- Rollback path: only runs if any prior step in this job failed ---- - name: ROLLBACK - restore previous backup if: failure() shell: pwsh run: | $stamp = Get-Content "C:\backups\latest.txt" -Raw $backupPath = "C:\backups\$stamp" Write-Host "Deployment failed - rolling back to backup: $backupPath" Import-Module WebAdministration Stop-WebAppPool -Name "CPRNIMS-Api" -ErrorAction SilentlyContinue Stop-WebAppPool -Name "CPRNIMS-Web" -ErrorAction SilentlyContinue Start-Sleep -Seconds 3 if (Test-Path "$backupPath\webapi") { robocopy "$backupPath\webapi" "C:\inetpub\cprnims-api" /MIR /R:3 /W:5 | Out-Null } if (Test-Path "$backupPath\webapps") { robocopy "$backupPath\webapps" "C:\inetpub\cprnims-web" /MIR /R:3 /W:5 | Out-Null } Start-WebAppPool -Name "CPRNIMS-Api" Start-WebAppPool -Name "CPRNIMS-Web" Write-Host "Rollback complete. Restored from $backupPath" exit 0 - name: ROLLBACK - verify pools after restore if: failure() shell: pwsh run: | Start-Sleep -Seconds 3 Import-Module WebAdministration $api = Get-WebAppPoolState -Name "CPRNIMS-Api" $web = Get-WebAppPoolState -Name "CPRNIMS-Web" Write-Host "After rollback - CPRNIMS-Api: $($api.Value)" Write-Host "After rollback - CPRNIMS-Web: $($web.Value)" if ($api.Value -ne "Started" -or $web.Value -ne "Started") { Write-Host "WARNING: app pools still not running after rollback. Manual intervention needed." }