Build v0.16.28.0 #24
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 | |
| run-name: Build v${{ inputs.version || vars.CURRENT_VERSION }} | |
| on: | |
| #push: | |
| # branches: | |
| # - main | |
| # paths-ignore: | |
| # - 'README.md' | |
| workflow_dispatch: | |
| inputs: | |
| use_self_hosted_runners: | |
| description: "Use Self-Hosted Runners" | |
| required: true | |
| default: false | |
| type: boolean | |
| retention_days_artifacts: | |
| description: "Retention Days for Artifacts" | |
| required: false | |
| default: 1 | |
| type: number | |
| version: | |
| description: "Version number (leave empty for auto)" | |
| required: false | |
| default: "" | |
| type: string | |
| env: | |
| VERSION: ${{ inputs.version || vars.CURRENT_VERSION }} | |
| RETENTION_DAYS_ARTIFACTS: ${{ inputs.retention_days_artifacts || 1 }} | |
| jobs: | |
| set-version: | |
| name: Increment Version | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }} | |
| permissions: | |
| contents: read | |
| actions: write | |
| outputs: | |
| version: ${{ steps.setver.outputs.version }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_VARIABLES_PAT }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| - name: Set Next Version | |
| id: setver | |
| shell: pwsh | |
| run: | | |
| # Use supplied version if provided, otherwise fall back to the repo variable | |
| Write-Host "Using source version: $env:VERSION" | |
| $CurrentVersion = [System.Version]::Parse("$env:VERSION") | |
| Write-Host "Resolved current version: $CurrentVersion" | |
| $NextVersion = "$($CurrentVersion.Major).$($CurrentVersion.Minor).$($CurrentVersion.Build + 1).0" | |
| Write-Host "Next version will be: $NextVersion" | |
| # Persist next version to GH Variables for future runs | |
| gh variable set CURRENT_VERSION --body $NextVersion | |
| # Expose the next version as a step output for the job | |
| echo "version=$NextVersion" >> $GITHUB_OUTPUT | |
| run-tests: | |
| name: Run Tests | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: set-version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.x" | |
| - name: Run Tests | |
| run: | | |
| dotnet test -c Release | |
| build-mac-binaries: | |
| name: Apple Build | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","macOS"]') || fromJson('["macos-latest"]') }} | |
| needs: set-version | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| - 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 }} | |
| build-windows-binaries: | |
| name: Windows Build (${{ matrix.arch }}) | |
| # When using self-hosted Windows runners, require both the self-hosted label and OS label. | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Windows"]') || fromJson('["windows-latest"]') }} | |
| environment: secure-signing | |
| needs: set-version | |
| permissions: | |
| id-token: write | |
| contents: read | |
| strategy: | |
| matrix: | |
| arch: [win-x86, win-x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.x" | |
| - 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 | |
| if: matrix.arch == 'win-x64' | |
| 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 ===== | |
| - name: Build DesktopClient (${{ matrix.arch }}) | |
| 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 ${{ matrix.arch }} --self-contained -o ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\ -p:Version=$env:VERSION -p:FileVersion=$env:VERSION | |
| - name: Sign DesktopClient (${{ matrix.arch }}) | |
| 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\${{ matrix.arch }}\ControlR.DesktopClient.exe" | |
| - name: Package and Prepare DesktopClient (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| # Create staging directory | |
| New-Item -Path ".build\staging-desktop\${{ matrix.arch }}" -ItemType Directory -Force | Out-Null | |
| # Create ZIP | |
| Compress-Archive -Path "ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\*" -DestinationPath ".build\staging-desktop\${{ matrix.arch }}\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\${{ matrix.arch }}\ControlR.DesktopClient.zip" "ControlR.Agent.Common\Resources\ControlR.DesktopClient.zip" -Force | |
| - name: Build Agent (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| New-Item -Path "ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}" -ItemType Directory -Force | Out-Null | |
| dotnet publish ControlR.Agent\ -c Release -r ${{ matrix.arch }} -o ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\ -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 (${{ matrix.arch }}) | |
| 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\${{ matrix.arch }}\ControlR.Agent.exe" | |
| - name: Upload Agent (${{ matrix.arch }}) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Agent-${{ matrix.arch }} | |
| path: ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\ControlR.Agent.exe | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| build-linux-binaries: | |
| name: Linux Build | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: [set-version] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.x" | |
| - name: Build DesktopClient (linux-x64) | |
| run: | | |
| # Clean Resources folder | |
| rm -f "./ControlR.Agent.Common/Resources/*.zip" | |
| # Build DesktopClient | |
| dotnet publish ./ControlR.DesktopClient/ -c Release -r linux-x64 --self-contained -o ./ControlR.DesktopClient/bin/publish/linux-x64/ -p:Version=$VERSION -p:FileVersion=$VERSION | |
| # Create staging directory | |
| mkdir -p ".build/staging-desktop/linux-x64" | |
| # Create ZIP | |
| cd ./ControlR.DesktopClient/bin/publish/linux-x64/ | |
| zip -r ../../../../.build/staging-desktop/linux-x64/ControlR.DesktopClient.zip . | |
| cd ../../../.. | |
| # Copy to Agent Resources | |
| mkdir -p "./ControlR.Agent.Common/Resources" | |
| cp ".build/staging-desktop/linux-x64/ControlR.DesktopClient.zip" "./ControlR.Agent.Common/Resources/ControlR.DesktopClient.zip" | |
| - name: Build Agent (linux-x64) | |
| run: | | |
| mkdir -p "./ControlR.Web.Server/wwwroot/downloads/linux-x64" | |
| 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=$VERSION -p:FileVersion=$VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true | |
| - name: Upload Agent (linux-x64) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Agent-linux-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/linux-x64/ControlR.Agent | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| build-web-server: | |
| name: Build Web Server | |
| runs-on: ${{ fromJson(inputs.use_self_hosted_runners) && fromJson('["self-hosted","Windows"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: | |
| [ | |
| build-windows-binaries, | |
| build-linux-binaries, | |
| build-mac-binaries, | |
| run-tests, | |
| ] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.x" | |
| - name: Download Agent (win-x86) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-win-x86 | |
| path: ControlR.Web.Server/wwwroot/downloads/win-x86/ | |
| - name: Download Agent (win-x64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-win-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/win-x64/ | |
| - name: Download Agent (linux-x64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-linux-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/linux-x64/ | |
| - name: Download Agent (macOS ARM64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-macOS-ARM64 | |
| path: ControlR.Web.Server/wwwroot/downloads/osx-arm64/ | |
| - name: Download Agent (macOS x64) | |
| uses: actions/download-artifact@v6 | |
| with: | |
| name: Agent-macOS-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/osx-x64/ | |
| - name: Create Version.txt | |
| shell: pwsh | |
| run: | | |
| Set-Content -Path "ControlR.Web.Server/wwwroot/downloads/Version.txt" -Value $env:VERSION -Force -Encoding UTF8 | |
| - name: Build Web Server | |
| shell: pwsh | |
| run: | | |
| New-Item -Path "ControlR.Web.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.Web.Server/bin/publish --self-contained true | |
| - name: Verify Agent Binaries | |
| shell: pwsh | |
| run: | | |
| $TestPaths = @( | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/Version.txt", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x86/ControlR.Agent.exe", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x64/ControlR.Agent.exe", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/linux-x64/ControlR.Agent", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-arm64/ControlR.Agent", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-x64/ControlR.Agent", | |
| "ControlR.Web.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.Web.Server/bin/publish | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| - name: Upload docker-compose | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: DockerCompose | |
| path: docker-compose/docker-compose.yml | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} |