All checks were successful
Build and Deploy LSFE Frontend / build-and-deploy (push) Successful in 2m36s
148 lines
5.1 KiB
YAML
148 lines
5.1 KiB
YAML
name: Build and Deploy LSFE Frontend
|
|
|
|
on:
|
|
push:
|
|
branches: [ main ]
|
|
|
|
jobs:
|
|
build-and-deploy:
|
|
runs-on: lsfe-server
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "20"
|
|
|
|
- name: Clean previous build output
|
|
shell: pwsh
|
|
run: |
|
|
Remove-Item -Recurse -Force ".\dist" -ErrorAction SilentlyContinue
|
|
|
|
- name: Install dependencies
|
|
shell: pwsh
|
|
run: npm ci
|
|
|
|
# ---- Inject VITE_API_BASE_URL from a Gitea secret so the API URL never has to be
|
|
# hand-edited/committed again - only this secret needs updating when the API moves.
|
|
# This OVERWRITES .env.production before the build; Vite bakes it into the bundle
|
|
# at build time (Vite env vars are compile-time, not runtime), so nothing needs
|
|
# to change on the IIS/deploy side.
|
|
- name: Write production env - Frontend
|
|
shell: pwsh
|
|
env:
|
|
API_BASE_URL: ${{ secrets.LSFE_FRONTEND_VITE_API_BASE_URL }}
|
|
run: |
|
|
"VITE_API_BASE_URL=$env:API_BASE_URL" | Out-File -FilePath ".\.env.production" -Encoding utf8 -NoNewline
|
|
Write-Host "Wrote .env.production (value not echoed)"
|
|
|
|
- name: Build (Vite production build)
|
|
shell: pwsh
|
|
run: npm run build
|
|
|
|
- name: Verify build output exists
|
|
shell: pwsh
|
|
run: |
|
|
if (-not (Test-Path ".\dist\index.html")) {
|
|
throw "Vite build did not produce dist\index.html - aborting before touching live site"
|
|
}
|
|
|
|
# ---- 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-frontend\$stamp" | Out-Null
|
|
|
|
if (Test-Path "C:\inetpub\LSFE-Frontend") {
|
|
robocopy "C:\inetpub\LSFE-Frontend" "C:\backups-frontend\$stamp\frontend" /MIR /R:2 /W:3 | Out-Null
|
|
}
|
|
|
|
$stamp | Out-File -FilePath "C:\backups-frontend\latest.txt" -Encoding ascii -NoNewline
|
|
|
|
# Keep only the last 5 backups to avoid filling the disk
|
|
$all = Get-ChildItem "C:\backups-frontend" -Directory | Sort-Object Name -Descending
|
|
if ($all.Count -gt 5) {
|
|
$all | Select-Object -Skip 5 | Remove-Item -Recurse -Force
|
|
}
|
|
|
|
Write-Host "Backed up current frontend deployment to C:\backups-frontend\$stamp"
|
|
exit 0
|
|
|
|
- name: Stop app pool
|
|
shell: pwsh
|
|
run: |
|
|
Import-Module WebAdministration
|
|
Stop-WebAppPool -Name "LSFE-Frontend" -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 3
|
|
|
|
- name: Deploy frontend files
|
|
id: deploy_frontend
|
|
shell: pwsh
|
|
run: |
|
|
# Mirrors the built dist folder into the live IIS site path.
|
|
# No content/uploads folder to protect here (that's a backend concept) -
|
|
# if you later add one under the frontend site, add /XD <folder> here too.
|
|
robocopy ".\dist" "C:\inetpub\LSFE-Frontend" /MIR /R:3 /W:5
|
|
$rc = $LASTEXITCODE
|
|
Write-Host "ROBOCOPY EXIT CODE: $rc"
|
|
if ($rc -ge 8) {
|
|
throw "robocopy failed for frontend with exit code $rc"
|
|
}
|
|
exit 0
|
|
|
|
- name: Start app pool
|
|
shell: pwsh
|
|
run: |
|
|
Import-Module WebAdministration
|
|
Start-WebAppPool -Name "LSFE-Frontend"
|
|
|
|
- name: Verify app pool is running
|
|
shell: pwsh
|
|
run: |
|
|
Start-Sleep -Seconds 3
|
|
Import-Module WebAdministration
|
|
$fe = Get-WebAppPoolState -Name "LSFE-Frontend"
|
|
Write-Host "LSFE-Frontend: $($fe.Value)"
|
|
if ($fe.Value -ne "Started") {
|
|
throw "Frontend app pool 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-frontend\latest.txt" -Raw).Trim()
|
|
$backupPath = "C:\backups-frontend\$stamp"
|
|
Write-Host "Deployment failed - rolling back to backup: $backupPath"
|
|
|
|
Import-Module WebAdministration
|
|
Stop-WebAppPool -Name "LSFE-Frontend" -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 3
|
|
|
|
if (Test-Path "$backupPath\frontend") {
|
|
robocopy "$backupPath\frontend" "C:\inetpub\LSFE-Frontend" /MIR /R:3 /W:5 | Out-Null
|
|
}
|
|
|
|
Start-WebAppPool -Name "LSFE-Frontend"
|
|
|
|
Write-Host "Rollback complete. Restored from $backupPath"
|
|
exit 0
|
|
|
|
- name: ROLLBACK - verify pool after restore
|
|
if: failure()
|
|
shell: pwsh
|
|
run: |
|
|
Start-Sleep -Seconds 3
|
|
Import-Module WebAdministration
|
|
$fe = Get-WebAppPoolState -Name "LSFE-Frontend"
|
|
|
|
Write-Host "After rollback - LSFE-Frontend: $($fe.Value)"
|
|
|
|
if ($fe.Value -ne "Started") {
|
|
Write-Host "WARNING: frontend app pool still not running after rollback. Manual intervention needed."
|
|
} |