Build #2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| #push: | |
| # branches: | |
| # - main | |
| # paths-ignore: | |
| # - 'README.md' | |
| workflow_dispatch: | |
| inputs: | |
| windows_runner: | |
| description: 'Windows Runner' | |
| required: true | |
| default: 'windows-latest' | |
| type: choice | |
| options: | |
| - windows-latest | |
| - self-hosted | |
| retention_days_artifacts: | |
| description: 'Retention Days for Artifacts' | |
| required: false | |
| default: "1" | |
| type: string | |
| env: | |
| MAJOR_VERSION: ${{vars.MAJOR_VERSION}} | |
| MINOR_VERSION: ${{vars.MINOR_VERSION}} | |
| RETENTION_DAYS_ARTIFACTS: ${{ inputs.retention_days_artifacts || '1' }} | |
| jobs: | |
| set-version: | |
| name: Set Current Version | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| version: ${{ steps.setver.outputs.version }} | |
| steps: | |
| - name: Compute Build Version (run number only) | |
| id: setver | |
| run: | | |
| MAJOR=${{ env.MAJOR_VERSION }} | |
| MINOR=${{ env.MINOR_VERSION }} | |
| BUILD=${{ github.run_number }} | |
| VERSION="${MAJOR}.${MINOR}.${BUILD}.0" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Computed version (run number): $VERSION" | |
| mac-build: | |
| name: Apple Build | |
| runs-on: macos-latest | |
| needs: set-version | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 # Fetch all history and tags | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.x' | |
| - name: Publish DesktopClient + Agent (ARM64) | |
| run: | | |
| # Clean Resources folder | |
| rm -f "./ControlR.Agent.Common/Resources/*.zip" | |
| # Build DesktopClient | |
| dotnet publish "./ControlR.DesktopClient/" -c Release -r osx-arm64 --self-contained -o "./ControlR.DesktopClient/bin/publish/osx-arm64/" -p:Version=$VERSION -p:FileVersion=$VERSION | |
| sudo codesign --force --deep --entitlements "./.build/Mac/ControlR.entitlements" --sign - "./ControlR.DesktopClient/bin/publish/osx-arm64/ControlR.DesktopClient" | |
| pwsh "./.build/Mac/CreateMacApp.ps1" -OutputDir "./ControlR.DesktopClient/bin/publish/osx-arm64/" | |
| ditto -c -k --sequesterRsrc "./ControlR.DesktopClient/bin/publish/osx-arm64/" "./ControlR.DesktopClient/bin/publish/osx-arm64/ControlR.app.zip" | |
| # Copy DesktopClient ZIP to Agent Resources | |
| mkdir -p "./ControlR.Agent.Common/Resources" | |
| cp "./ControlR.DesktopClient/bin/publish/osx-arm64/ControlR.app.zip" "./ControlR.Agent.Common/Resources/ControlR.app.zip" | |
| # Build Agent | |
| dotnet publish "./ControlR.Agent/" -c Release -r osx-arm64 --self-contained -o "./ControlR.Agent/bin/publish/osx-arm64/" -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$VERSION -p:FileVersion=$VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| sudo codesign --force --deep --entitlements "./.build/Mac/ControlR.entitlements" --sign - "./ControlR.Agent/bin/publish/osx-arm64/ControlR.Agent" | |
| - name: Publish DesktopClient + Agent (x64) | |
| run: | | |
| # Clean Resources folder | |
| rm -f "./ControlR.Agent.Common/Resources/*.zip" | |
| # Build DesktopClient | |
| dotnet publish "./ControlR.DesktopClient/" -c Release -r osx-x64 --self-contained -o "./ControlR.DesktopClient/bin/publish/osx-x64/" -p:Version=$VERSION -p:FileVersion=$VERSION | |
| sudo codesign --force --deep --entitlements "./.build/Mac/ControlR.entitlements" --sign - "./ControlR.DesktopClient/bin/publish/osx-x64/ControlR.DesktopClient" | |
| pwsh "./.build/Mac/CreateMacApp.ps1" -OutputDir "./ControlR.DesktopClient/bin/publish/osx-x64/" | |
| ditto -c -k --sequesterRsrc "./ControlR.DesktopClient/bin/publish/osx-x64/" "./ControlR.DesktopClient/bin/publish/osx-x64/ControlR.app.zip" | |
| # Copy DesktopClient ZIP to Agent Resources | |
| mkdir -p "./ControlR.Agent.Common/Resources" | |
| mv "./ControlR.DesktopClient/bin/publish/osx-x64/ControlR.app.zip" "./ControlR.Agent.Common/Resources/ControlR.app.zip" | |
| # Build Agent | |
| dotnet publish "./ControlR.Agent/" -c Release -r osx-x64 --self-contained -o "./ControlR.Agent/bin/publish/osx-x64/" -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$VERSION -p:FileVersion=$VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| sudo codesign --force --deep --entitlements "./.build/Mac/ControlR.entitlements" --sign - "./ControlR.Agent/bin/publish/osx-x64/ControlR.Agent" | |
| - name: Upload Agent (macOS ARM64) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Agent-macOS-ARM64 | |
| path: ControlR.Agent/bin/publish/osx-arm64/ControlR.Agent | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| - name: Upload Agent (macOS x64) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Agent-macOS-x64 | |
| path: ControlR.Agent/bin/publish/osx-x64/ControlR.Agent | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| windows-build: | |
| name: Windows Build | |
| runs-on: ${{ inputs.windows_runner || 'windows-latest' }} | |
| environment: secure-signing | |
| needs: [set-version, mac-build] | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| permissions: | |
| id-token: write | |
| contents: read | |
| steps: | |
| - name: Install SSH Key | |
| uses: webfactory/ssh-agent@v0.9.0 | |
| with: | |
| ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 # Fetch all history and tags for version tagging | |
| submodules: recursive | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.x' | |
| - name: Run Tests | |
| run: dotnet test -c Release | |
| - name: Download macOS ARM64 Agent | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-macOS-ARM64 | |
| path: ControlR.Web.Server\wwwroot\downloads\osx-arm64\ | |
| - name: Download macOS x64 Agent | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-macOS-x64 | |
| path: ControlR.Web.Server\wwwroot\downloads\osx-x64\ | |
| - name: Pack ControlR.ApiClient (Release) | |
| run: dotnet build ControlR.ApiClient/ControlR.ApiClient.csproj -c Release -p:Version=${{ env.VERSION }} | |
| - name: Find ApiClient nupkg | |
| id: find-nupkg | |
| shell: pwsh | |
| run: | | |
| $searchDir = 'ControlR.ApiClient\bin\Release' | |
| Write-Host "Searching for nupkg in $searchDir" | |
| if (!(Test-Path $searchDir)) { | |
| Write-Error "Directory $searchDir not found" | |
| exit 1 | |
| } | |
| $pkg = Get-ChildItem -Path $searchDir -Filter 'ControlR.ApiClient*.nupkg' -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | |
| if (-not $pkg) { | |
| Write-Error 'ApiClient nupkg not found in Release folder.' | |
| exit 1 | |
| } | |
| Write-Host "Found package: $($pkg.FullName)" | |
| echo "APICLIENT_NUPKG=$($pkg.FullName)" >> $env:GITHUB_OUTPUT | |
| - name: Upload ApiClient NuGet | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ApiClientNuGet | |
| path: ${{ steps.find-nupkg.outputs.APICLIENT_NUPKG }} | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| # ===== Azure Login with OIDC ===== | |
| - name: Azure Login | |
| uses: azure/login@v2 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| # ===== Install AzureSignTool ===== | |
| - name: Install AzureSignTool | |
| shell: pwsh | |
| run: | | |
| dotnet tool install --global AzureSignTool | |
| # ===== Build Windows x86 ===== | |
| - name: Build DesktopClient (win-x86) | |
| shell: pwsh | |
| run: | | |
| # Clean Resources folder | |
| Remove-Item -Path "ControlR.Agent.Common\Resources\*.zip" -Force -ErrorAction SilentlyContinue | |
| # Build DesktopClient | |
| dotnet publish ControlR.DesktopClient\ -c Release -r win-x86 --self-contained -o ControlR.DesktopClient\bin\publish\win-x86\ -p:Version=$env:VERSION -p:FileVersion=$env:VERSION | |
| - name: Sign DesktopClient (win-x86) | |
| shell: pwsh | |
| run: | | |
| AzureSignTool sign ` | |
| --du="${{ vars.SIGNING_DESCRIPTION_URL }}" ` | |
| --fd=sha256 ` | |
| --kvu="${{ secrets.AZURE_KEY_VAULT_URI }}" ` | |
| --kvc="${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }}" ` | |
| --kvm ` | |
| --tr=http://timestamp.digicert.com ` | |
| --td=sha256 ` | |
| "${{ github.workspace }}\ControlR.DesktopClient\bin\publish\win-x86\ControlR.DesktopClient.exe" | |
| - name: Package and Prepare DesktopClient (win-x86) | |
| shell: pwsh | |
| run: | | |
| # Create staging directory | |
| New-Item -Path ".build\staging-desktop\win-x86" -ItemType Directory -Force | Out-Null | |
| # Create ZIP | |
| Compress-Archive -Path "ControlR.DesktopClient\bin\publish\win-x86\*" -DestinationPath ".build\staging-desktop\win-x86\ControlR.DesktopClient.zip" -Force | |
| # Copy to Agent Resources | |
| New-Item -Path "ControlR.Agent.Common\Resources" -ItemType Directory -Force | Out-Null | |
| Copy-Item ".build\staging-desktop\win-x86\ControlR.DesktopClient.zip" "ControlR.Agent.Common\Resources\ControlR.DesktopClient.zip" -Force | |
| - name: Build Agent (win-x86) | |
| shell: pwsh | |
| run: | | |
| New-Item -Path "ControlR.Web.Server\wwwroot\downloads\win-x86" -ItemType Directory -Force | Out-Null | |
| dotnet publish ControlR.Agent\ -c Release -r win-x86 -o ControlR.Web.Server\wwwroot\downloads\win-x86\ -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$env:VERSION -p:FileVersion=$env:VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| - name: Sign Agent (win-x86) | |
| shell: pwsh | |
| run: | | |
| AzureSignTool sign ` | |
| --du="${{ vars.SIGNING_DESCRIPTION_URL }}" ` | |
| --fd=sha256 ` | |
| --kvu="${{ secrets.AZURE_KEY_VAULT_URI }}" ` | |
| --kvc="${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }}" ` | |
| --kvm ` | |
| --tr=http://timestamp.digicert.com ` | |
| --td=sha256 ` | |
| "${{ github.workspace }}\ControlR.Web.Server\wwwroot\downloads\win-x86\ControlR.Agent.exe" | |
| # ===== Build Windows x64 ===== | |
| - name: Build DesktopClient (win-x64) | |
| shell: pwsh | |
| run: | | |
| # Clean Resources folder | |
| Remove-Item -Path "ControlR.Agent.Common\Resources\*.zip" -Force -ErrorAction SilentlyContinue | |
| # Build DesktopClient | |
| dotnet publish ControlR.DesktopClient\ -c Release -r win-x64 --self-contained -o ControlR.DesktopClient\bin\publish\win-x64\ -p:Version=$env:VERSION -p:FileVersion=$env:VERSION | |
| - name: Sign DesktopClient (win-x64) | |
| shell: pwsh | |
| run: | | |
| AzureSignTool sign ` | |
| --du="${{ vars.SIGNING_DESCRIPTION_URL }}" ` | |
| --fd=sha256 ` | |
| --kvu="${{ secrets.AZURE_KEY_VAULT_URI }}" ` | |
| --kvc="${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }}" ` | |
| --kvm ` | |
| --tr=http://timestamp.digicert.com ` | |
| --td=sha256 ` | |
| "${{ github.workspace }}\ControlR.DesktopClient\bin\publish\win-x64\ControlR.DesktopClient.exe" | |
| - name: Package and Prepare DesktopClient (win-x64) | |
| shell: pwsh | |
| run: | | |
| # Create staging directory | |
| New-Item -Path ".build\staging-desktop\win-x64" -ItemType Directory -Force | Out-Null | |
| # Create ZIP | |
| Compress-Archive -Path "ControlR.DesktopClient\bin\publish\win-x64\*" -DestinationPath ".build\staging-desktop\win-x64\ControlR.DesktopClient.zip" -Force | |
| # Copy to Agent Resources | |
| New-Item -Path "ControlR.Agent.Common\Resources" -ItemType Directory -Force | Out-Null | |
| Copy-Item ".build\staging-desktop\win-x64\ControlR.DesktopClient.zip" "ControlR.Agent.Common\Resources\ControlR.DesktopClient.zip" -Force | |
| - name: Build Agent (win-x64) | |
| shell: pwsh | |
| run: | | |
| New-Item -Path "ControlR.Web.Server\wwwroot\downloads\win-x64" -ItemType Directory -Force | Out-Null | |
| dotnet publish ControlR.Agent\ -c Release -r win-x64 -o ControlR.Web.Server\wwwroot\downloads\win-x64\ -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$env:VERSION -p:FileVersion=$env:VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| - name: Sign Agent (win-x64) | |
| shell: pwsh | |
| run: | | |
| AzureSignTool sign ` | |
| --du="${{ vars.SIGNING_DESCRIPTION_URL }}" ` | |
| --fd=sha256 ` | |
| --kvu="${{ secrets.AZURE_KEY_VAULT_URI }}" ` | |
| --kvc="${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }}" ` | |
| --kvm ` | |
| --tr=http://timestamp.digicert.com ` | |
| --td=sha256 ` | |
| "${{ github.workspace }}\ControlR.Web.Server\wwwroot\downloads\win-x64\ControlR.Agent.exe" | |
| # ===== Build Linux x64 ===== | |
| - name: Build DesktopClient + Agent (linux-x64) | |
| shell: pwsh | |
| run: | | |
| # Clean Resources folder | |
| Remove-Item -Path "ControlR.Agent.Common\Resources\*.zip" -Force -ErrorAction SilentlyContinue | |
| # Build DesktopClient | |
| dotnet publish ControlR.DesktopClient\ -c Release -r linux-x64 --self-contained -o ControlR.DesktopClient\bin\publish\linux-x64\ -p:Version=$env:VERSION -p:FileVersion=$env:VERSION | |
| # Create staging directory | |
| New-Item -Path ".build\staging-desktop\linux-x64" -ItemType Directory -Force | Out-Null | |
| # Create ZIP | |
| Compress-Archive -Path "ControlR.DesktopClient\bin\publish\linux-x64\*" -DestinationPath ".build\staging-desktop\linux-x64\ControlR.DesktopClient.zip" -Force | |
| # Copy to Agent Resources | |
| New-Item -Path "ControlR.Agent.Common\Resources" -ItemType Directory -Force | Out-Null | |
| Copy-Item ".build\staging-desktop\linux-x64\ControlR.DesktopClient.zip" "ControlR.Agent.Common\Resources\ControlR.DesktopClient.zip" -Force | |
| # Build Agent | |
| New-Item -Path "ControlR.Web.Server\wwwroot\downloads\linux-x64" -ItemType Directory -Force | Out-Null | |
| dotnet publish ControlR.Agent\ -c Release -r linux-x64 -o ControlR.Web.Server\wwwroot\downloads\linux-x64\ -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$env:VERSION -p:FileVersion=$env:VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| # ===== Create AgentVersion.txt ===== | |
| - name: Create AgentVersion.txt | |
| shell: pwsh | |
| run: | | |
| Set-Content -Path "ControlR.Web.Server\wwwroot\downloads\AgentVersion.txt" -Value $env:VERSION -Force -Encoding UTF8 | |
| # ===== Build Web Server ===== | |
| - name: Build Web Server | |
| shell: pwsh | |
| run: | | |
| New-Item -Path "ControlR.Server\bin\publish" -ItemType Directory -Force | Out-Null | |
| dotnet publish ControlR.Web.Server\ -p:ExcludeApp_Data=true --runtime linux-x64 --configuration Release -p:Version=$env:VERSION -p:FileVersion=$env:VERSION --output ControlR.Server\bin\publish --self-contained true | |
| - name: Verify Agent Binaries | |
| shell: pwsh | |
| run: | | |
| $TestPaths = @( | |
| "ControlR.Server\bin\publish\wwwroot\downloads\AgentVersion.txt", | |
| "ControlR.Server\bin\publish\wwwroot\downloads\win-x86\ControlR.Agent.exe", | |
| "ControlR.Server\bin\publish\wwwroot\downloads\win-x64\ControlR.Agent.exe", | |
| "ControlR.Server\bin\publish\wwwroot\downloads\linux-x64\ControlR.Agent", | |
| "ControlR.Server\bin\publish\wwwroot\downloads\osx-arm64\ControlR.Agent", | |
| "ControlR.Server\bin\publish\wwwroot\downloads\osx-x64\ControlR.Agent", | |
| "ControlR.Server\bin\publish\novnc\vnc.html" | |
| ) | |
| foreach ($TestPath in $TestPaths) { | |
| if (!(Test-Path $TestPath)) { | |
| Write-Error "$TestPath not found." | |
| exit 1 | |
| } | |
| } | |
| - name: Upload Server | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Server | |
| path: ControlR.Server\bin\publish | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| - name: Upload docker-compose | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: DockerCompose | |
| path: docker-compose\ | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} |