docker composer
Some checks failed
Build and Deploy LSFE / build-and-deploy (push) Has been cancelled
Some checks failed
Build and Deploy LSFE / build-and-deploy (push) Has been cancelled
This commit is contained in:
parent
405c7b3a6d
commit
61eac6c6f8
156
.gitea/workflows/deploy.yml
Normal file
156
.gitea/workflows/deploy.yml
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
name: Build and Deploy LSFE
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- name: Publish WebApi
|
||||||
|
shell: pwsh
|
||||||
|
run: dotnet publish .\LSFE.API\LSFE.API.csproj -c Release -o C:\ci-output\webapi
|
||||||
|
|
||||||
|
# ---- Generate production config from Gitea Actions secrets (never committed to git) ----
|
||||||
|
- name: Write production appsettings - WebApi
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
GROQ_KEY: ${{ secrets.LLI_SFE_PROD_GROQ_API_KEY }}
|
||||||
|
JWT_SECRET: ${{ secrets.LLI_SFE_PROD_JWT_SECRET }}
|
||||||
|
DB_CONN: ${{ secrets.LLI_SFE_PROD_DB_CONNECTION }}
|
||||||
|
run: |
|
||||||
|
$config = @{
|
||||||
|
Groq = @{
|
||||||
|
ApiKey = $env:GROQ_KEY
|
||||||
|
ApiUrl = "https://api.groq.com/openai/v1/chat/completions"
|
||||||
|
Model = "llama-3.1-8b-instant"
|
||||||
|
}
|
||||||
|
JWT = @{
|
||||||
|
ValidAudience = "https://lloydwebapi.lloydlab.com:2021"
|
||||||
|
ValidIssuer = "https://lloydwebapi.lloydlab.com:2021"
|
||||||
|
Secret = $env:JWT_SECRET
|
||||||
|
}
|
||||||
|
ConnectionStrings = @{
|
||||||
|
DefaultConnection = $env:DB_CONN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$json = $config | ConvertTo-Json -Depth 5
|
||||||
|
$json | Out-File -FilePath "C:\ci-output\webapi\appsettings.Production.json" -Encoding utf8
|
||||||
|
Write-Host "Wrote appsettings.Production.json to webapi output (secret values not echoed)"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
# ---- Backup current live deployment before touching anything ----
|
||||||
|
# NOTE: this backs up Content too (harmless - it's just a point-in-time copy
|
||||||
|
# and is never used to restore Content, see rollback step below).
|
||||||
|
- 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
|
||||||
|
|
||||||
|
if (Test-Path "C:\inetpub\LSFE-api") {
|
||||||
|
robocopy "C:\inetpub\LSFE-api" "C:\backups\$stamp\webapi" /MIR /R:2 /W:3 /XD Content | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 (Content excluded - never backed up or restored)"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: Stop app pools
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Import-Module WebAdministration
|
||||||
|
Stop-WebAppPool -Name "LSFE-Api" -ErrorAction SilentlyContinue
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
|
||||||
|
- name: Deploy WebApi files
|
||||||
|
id: deploy_api
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
# Deploy everything EXCEPT the Content folder (and its subfolders, Images/Uploads).
|
||||||
|
# /XD Content excludes the directory by NAME, which robocopy matches reliably
|
||||||
|
# against the source tree it walks, at any depth - so wwwroot\Content and
|
||||||
|
# everything under it (Images, Uploads) is never copied over or deleted.
|
||||||
|
# This prevents /MIR from purging/replacing the live C:\inetpub\LSFE-api\wwwroot\Content folder.
|
||||||
|
robocopy "C:\ci-output\webapi" "C:\inetpub\LSFE-api" /MIR /R:3 /W:5 /XD Content
|
||||||
|
$rc = $LASTEXITCODE
|
||||||
|
Write-Host "ROBOCOPY EXIT CODE: $rc"
|
||||||
|
if ($rc -ge 8) {
|
||||||
|
throw "robocopy failed for WebApi with exit code $rc"
|
||||||
|
}
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: Start app pools
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Import-Module WebAdministration
|
||||||
|
Start-WebAppPool -Name "LSFE-Api"
|
||||||
|
|
||||||
|
- name: Verify app pools are running
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Import-Module WebAdministration
|
||||||
|
$api = Get-WebAppPoolState -Name "LSFE-Api"
|
||||||
|
Write-Host "LSFE-Api: $($api.Value)"
|
||||||
|
if ($api.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).Trim()
|
||||||
|
$backupPath = "C:\backups\$stamp"
|
||||||
|
Write-Host "Deployment failed - rolling back to backup: $backupPath"
|
||||||
|
|
||||||
|
Import-Module WebAdministration
|
||||||
|
Stop-WebAppPool -Name "LSFE-Api" -ErrorAction SilentlyContinue
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
|
||||||
|
if (Test-Path "$backupPath\webapi") {
|
||||||
|
# /XD Content here is critical: the backup was taken BEFORE this deploy
|
||||||
|
# attempt, so it holds a stale snapshot of Content. Without this exclusion,
|
||||||
|
# rolling back would blow away any files/uploads written to Content since
|
||||||
|
# the backup was made. Content must never be touched by CI/CD, including rollback.
|
||||||
|
robocopy "$backupPath\webapi" "C:\inetpub\LSFE-api" /MIR /R:3 /W:5 /XD Content | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-WebAppPool -Name "LSFE-Api"
|
||||||
|
|
||||||
|
Write-Host "Rollback complete. Restored from $backupPath (Content left untouched)"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
- name: ROLLBACK - verify pools after restore
|
||||||
|
if: failure()
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Import-Module WebAdministration
|
||||||
|
$api = Get-WebAppPoolState -Name "LSFE-Api"
|
||||||
|
|
||||||
|
Write-Host "After rollback - LSFE-Api: $($api.Value)"
|
||||||
|
|
||||||
|
if ($api.Value -ne "Started") {
|
||||||
|
Write-Host "WARNING: app pool still not running after rollback. Manual intervention needed."
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user