name: Build and Deploy on: push: branches: - master workflow_dispatch: inputs: environment: description: 'Environment to deploy to' required: true default: 'prod' type: choice options: - prod - dev - test restart_iis: description: 'Restart IIS after deployment' required: true default: true type: boolean create_release: description: 'Create release' required: true default: true type: boolean jobs: build: runs-on: self-hosted environment: ${{ github.event.inputs.environment || 'prod' }} steps: - name: Get Current User run: | $env:USERNAME - name: Checkout Repository uses: actions/checkout@v2 with: fetch-depth: 0 # Fetches all history and tags for versioning - name: Set up .NET uses: actions/setup-dotnet@v2 with: dotnet-version: '9.0' - name: Restore .NET Dependencies run: dotnet restore ./HomeApi.sln - name: Build .NET Project run: dotnet build --configuration Release ./HomeApi/HomeApi.csproj - name: Publish .NET Project run: | dotnet publish ./HomeApi/HomeApi.csproj --configuration Release --output ./output/dotnet --self-contained false --no-restore /p:PublishTrimmed=false /p:CopyOutputSymbolsToPublishDirectory=false # Verify wwwroot was published if (Test-Path -Path "./output/dotnet/wwwroot") { Write-Host "wwwroot folder was published successfully" } else { Write-Host "WARNING: wwwroot folder was not found in published output!" } # Check for Chrome-related files if (Test-Path -Path "./output/dotnet/Chrome") { Write-Host "Chrome folder was published successfully" } else { Write-Host "Chrome folder not found in published output" } if (Test-Path -Path "./output/dotnet/ChromeHeadlessShell") { Write-Host "ChromeHeadlessShell was published successfully" } else { Write-Host "ChromeHeadlessShell not found in published output" } # Check wwwroot and manually copy if missing - name: Ensure wwwroot is Included run: | if (-not (Test-Path -Path "./output/dotnet/wwwroot")) { Write-Host "wwwroot folder not found in published output, manually copying..." # Check if wwwroot exists in project directory $sourceWwwroot = "./HomeApi/wwwroot" if (Test-Path -Path $sourceWwwroot) { Write-Host "Found wwwroot directory in source, copying..." New-Item -ItemType Directory -Path "./output/dotnet/wwwroot" -Force Copy-Item -Path "$sourceWwwroot/*" -Destination "./output/dotnet/wwwroot" -Recurse -Force } else { Write-Host "WARNING: Could not find wwwroot in source directory!" } } - name: Generate SemVer version if: ${{ github.event.inputs.create_release != 'false' }} id: semver uses: ietf-tools/semver-action@v1 with: token: ${{ secrets.GITHUB_TOKEN }} branch: master patchAll: true - name: Create GitHub Release if: ${{ github.event.inputs.create_release != 'false' }} id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ steps.semver.outputs.next }} release_name: Release ${{ steps.semver.outputs.next }} draft: false prerelease: false - name: Create placeholder appsettings for release if: ${{ github.event.inputs.create_release != 'false' }} run: | $appSettings = @{ Logging = @{ LogLevel = @{ Default = "Information" "Microsoft.AspNetCore" = "Warning" } } Seq = @{ ServerUrl = "https://log.azaaxin.com" ApiKey = "KEY" MinimumLevel = "Trace" LevelOverride = @{ Microsoft: "Warning" } } ApiConfiguration = @{ EspConfiguration = @{ InformationBoardImageUrl = "http://server_ip:port/home/default.jpg" UpdateIntervalMinutes = [int]"${{ vars.ESP_UPDATE_INTERVAL }}" BlackTextThreshold = [int]"${{ vars.ESP_BLACK_TEXT_THRESHOLD }}" EnableDithering = [System.Convert]::ToBoolean("${{ vars.ESP_ENABLE_DITHERING }}") DitheringStrength = [int]"${{ vars.ESP_DITHERING_STRENGTH }}" EnhanceContrast = [System.Convert]::ToBoolean("${{ vars.ESP_ENHANCE_CONTRAST }}") ContrastStrength = [int]"${{ vars.ESP_CONTRAST_STRENGTH }}" IsHighContrastMode = [System.Convert]::ToBoolean("${{ vars.ESP_HIGH_CONTRAST_MODE }}") } Keys = @{ Weather = "SET THIS TO YOUR KEY" ResRobot = "SET THIS TO YOUR KEY" } BaseUrls = @{ Nominatim = "${{ vars.NOMINATIM_URL }}" Aurora = "${{ vars.AURORA_URL }}" Weather = "${{ vars.WEATHER_URL }}" ResRobot = "${{ vars.RES_ROBOT_URL }}" } DefaultCity = "CITY ADDRESS" DefaultStation = "YOUR STATION" } AllowedHosts = "*" } $appSettings | ConvertTo-Json -Depth 10 | Set-Content -Path "./output/dotnet/appsettings.json" Write-Host "Created placeholder appsettings.json successfully" - name: Zip the build for github release if: ${{ github.event.inputs.create_release != 'false' }} run: Compress-Archive -Path './output/*' -DestinationPath './output/HomeScreen_Build_${{ steps.semver.outputs.next }}.zip' -CompressionLevel Optimal -Force - name: Upload Release Asset if: ${{ github.event.inputs.create_release != 'false' }} uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./output/HomeScreen_Build_${{ steps.semver.outputs.next }}.zip asset_name: HomeScreen_Build_${{ steps.semver.outputs.next }}.zip asset_content_type: application/zip - name: Generate appsettings.json run: | $appSettings = @{ Logging = @{ LogLevel = @{ Default = "Information" "Microsoft.AspNetCore" = "Warning" } } Seq = @{ ServerUrl = ${{ vars.SEQ_URL }} ApiKey = ${{ secrets.seq_api_key }} MinimumLevel = "Trace" LevelOverride = @{ Microsoft: "Warning" } } ApiConfiguration = @{ EspConfiguration = @{ InformationBoardImageUrl = "${{ vars.ESP_IMAGE_URL }}" UpdateIntervalMinutes = [int]"${{ vars.ESP_UPDATE_INTERVAL }}" BlackTextThreshold = [int]"${{ vars.ESP_BLACK_TEXT_THRESHOLD }}" EnableDithering = [System.Convert]::ToBoolean("${{ vars.ESP_ENABLE_DITHERING }}") DitheringStrength = [int]"${{ vars.ESP_DITHERING_STRENGTH }}" EnhanceContrast = [System.Convert]::ToBoolean("${{ vars.ESP_ENHANCE_CONTRAST }}") ContrastStrength = [int]"${{ vars.ESP_CONTRAST_STRENGTH }}" IsHighContrastMode = [System.Convert]::ToBoolean("${{ vars.ESP_HIGH_CONTRAST_MODE }}") } Keys = @{ Weather = "${{ secrets.WEATHER_API_KEY }}" ResRobot = "${{ secrets.RES_ROBOT_API_KEY }}" } BaseUrls = @{ Nominatim = "${{ vars.NOMINATIM_URL }}" Aurora = "${{ vars.AURORA_URL }}" Weather = "${{ vars.WEATHER_URL }}" ResRobot = "${{ vars.RES_ROBOT_URL }}" } DefaultCity = "${{ vars.DEFAULT_CITY }}" DefaultStation = "${{ vars.DEFAULT_STATION }}" } AllowedHosts = "*" } $appSettings | ConvertTo-Json -Depth 10 | Set-Content -Path "./output/dotnet/appsettings.json" Write-Host "Generated appsettings.json successfully" - name: Upload Artifacts uses: actions/upload-artifact@v4 with: name: dotnet-artifacts path: ./output/dotnet deploy: runs-on: self-hosted needs: build environment: ${{ github.event.inputs.environment || 'prod' }} steps: - name: Download .NET Artifacts uses: actions/download-artifact@v4 with: name: dotnet-artifacts path: ./output/dotnet - name: Stop IIS Application Pool run: | Import-Module WebAdministration $appPoolName = "${{ vars.IIS_APP_POOL_NAME }}" if ([string]::IsNullOrEmpty($appPoolName)) { $appPoolName = "HomeApi" } Write-Host "Stopping application pool: $appPoolName" # Check if app pool exists if (Test-Path "IIS:\AppPools\$appPoolName") { # Stop app pool if ((Get-WebAppPoolState -Name $appPoolName).Value -ne "Stopped") { Stop-WebAppPool -Name $appPoolName Start-Sleep -Seconds 5 # Give it time to fully stop Write-Host "Application pool stopped successfully" } else { Write-Host "Application pool was already stopped" } } else { Write-Host "Warning: Application pool '$appPoolName' not found. Will attempt to copy files anyway." } - name: Copy .NET Publish Files to IIS Server run: | # Ensure destination directory exists if (-not (Test-Path "C:\inetpub\applications\HomeApi")) { New-Item -ItemType Directory -Path "C:\inetpub\applications\HomeApi" -Force Write-Host "Created destination directory" } # Copy files Write-Host "Copying files to destination..." Copy-Item -Path ".\output\dotnet\*" -Destination "C:\inetpub\applications\HomeApi" -Recurse -Force Write-Host "Files copied successfully" - name: Restart IIS Application Pool if: ${{ github.event.inputs.restart_iis != 'false' }} run: | Import-Module WebAdministration $appPoolName = "${{ vars.IIS_APP_POOL_NAME }}" if ([string]::IsNullOrEmpty($appPoolName)) { $appPoolName = "HomeApi" } Write-Host "Starting application pool: $appPoolName" # Check if app pool exists if (Test-Path "IIS:\AppPools\$appPoolName") { # Start app pool Start-WebAppPool -Name $appPoolName Write-Host "Application pool started successfully" } else { Write-Host "Warning: Application pool '$appPoolName' not found. Using IISReset instead." iisreset /restart Write-Host "IIS restarted successfully" }