Repository navigation
Build v0.28.1.0 #56
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: | |
| workflow_dispatch: | |
| inputs: | |
| use_self_hosted_runners: | |
| description: "Use self-hosted runners" | |
| required: true | |
| default: true | |
| type: boolean | |
| use_local_storage: | |
| description: "Use local storage for artifacts" | |
| required: false | |
| default: true | |
| 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 | |
| server_runtime: | |
| description: "Server target runtime/OS" | |
| required: false | |
| default: linux-x64 | |
| type: choice | |
| options: | |
| - linux-x64 | |
| - win-x64 | |
| - linux-arm64 | |
| notarize_mac_bundle: | |
| description: "Notarize macOS bundle" | |
| required: false | |
| default: true | |
| type: boolean | |
| build_nugets: | |
| description: "Build NuGet packages" | |
| required: false | |
| default: true | |
| type: boolean | |
| prerelease: | |
| description: "Is prerelease?" | |
| required: false | |
| default: false | |
| type: boolean | |
| run_tests: | |
| description: "Run tests" | |
| required: false | |
| default: false | |
| type: boolean | |
| customization_config_url: | |
| description: "URL to JSON customization config (empty for default branding)" | |
| required: false | |
| default: "" | |
| type: string | |
| skip_version_increment: | |
| description: "Use the supplied version as-is without incrementing CURRENT_VERSION" | |
| required: false | |
| default: false | |
| type: boolean | |
| workflow_call: | |
| inputs: | |
| use_self_hosted_runners: | |
| description: "Use self-hosted runners" | |
| required: false | |
| default: true | |
| type: boolean | |
| use_local_storage: | |
| description: "Use local storage for artifacts" | |
| required: false | |
| default: true | |
| type: boolean | |
| retention_days_artifacts: | |
| description: "Retention days for artifacts" | |
| required: false | |
| default: 1 | |
| type: number | |
| version: | |
| description: "Version number" | |
| required: true | |
| type: string | |
| server_runtime: | |
| description: "Server target runtime/OS" | |
| required: false | |
| default: linux-x64 | |
| type: string | |
| notarize_mac_bundle: | |
| description: "Notarize macOS bundle" | |
| required: false | |
| default: true | |
| type: boolean | |
| build_nugets: | |
| description: "Build NuGet packages" | |
| required: false | |
| default: true | |
| type: boolean | |
| prerelease: | |
| description: "Is prerelease?" | |
| required: false | |
| default: false | |
| type: boolean | |
| run_tests: | |
| description: "Run tests" | |
| required: false | |
| default: false | |
| type: boolean | |
| customization_config_url: | |
| description: "URL to JSON customization config (empty for default branding)" | |
| required: false | |
| default: "" | |
| type: string | |
| ref: | |
| description: "Git ref (branch or tag) to build. Defaults to the default branch." | |
| required: false | |
| default: "" | |
| type: string | |
| skip_version_increment: | |
| description: "Use the supplied version without incrementing or setting the current version." | |
| required: false | |
| default: false | |
| type: boolean | |
| env: | |
| VERSION: ${{ inputs.version || vars.CURRENT_VERSION }} | |
| RETENTION_DAYS_ARTIFACTS: ${{ inputs.retention_days_artifacts || 1 }} | |
| jobs: | |
| set-version: | |
| name: Increment Version | |
| runs-on: ${{ 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@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Validate local storage configuration | |
| uses: ./.github/actions/validate-local-storage | |
| with: | |
| use_local_storage: ${{ inputs.use_local_storage }} | |
| artifact_host: ${{ vars.ARTIFACT_HOST }} | |
| artifact_base_path: ${{ vars.ARTIFACT_BASE_PATH }} | |
| - name: Set Next Version | |
| id: setver | |
| shell: pwsh | |
| run: | | |
| # Use supplied version if provided, otherwise fall back to the repo variable | |
| if (-not $env:VERSION) { | |
| Write-Error "VERSION is empty. Provide workflow input version or set CURRENT_VERSION repository variable." | |
| exit 1 | |
| } | |
| Write-Host "Using source version: $env:VERSION" | |
| try { | |
| $CurrentVersion = [System.Version]::Parse("$env:VERSION") | |
| } | |
| catch { | |
| Write-Error "VERSION '$env:VERSION' is invalid. Expected numeric format like 1.2.3 or 1.2.3.0." | |
| exit 1 | |
| } | |
| if ($CurrentVersion.Revision -eq -1) { | |
| $CurrentVersion = [System.Version]::new($CurrentVersion.Major, $CurrentVersion.Minor, $CurrentVersion.Build, 0) | |
| } | |
| Write-Host "Resolved current version: $CurrentVersion" | |
| if ("${{ inputs.skip_version_increment }}" -eq "true") { | |
| Write-Host "skip_version_increment is set. Using version as-is without bumping CURRENT_VERSION." | |
| $NextVersion = $null | |
| } | |
| else { | |
| $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 | |
| if ($IsLinux) { | |
| /usr/bin/gh variable set CURRENT_VERSION --body $NextVersion | |
| } | |
| elseif ($IsMacOS) { | |
| /opt/homebrew/bin/gh variable set CURRENT_VERSION --body $NextVersion | |
| } | |
| else { | |
| gh variable set CURRENT_VERSION --body $NextVersion | |
| } | |
| } | |
| # Expose the current version as a step output for this run | |
| echo "version=$CurrentVersion" >> $env:GITHUB_OUTPUT | |
| download-customization: | |
| name: Download Customization Config | |
| runs-on: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: [set-version] | |
| permissions: | |
| contents: read | |
| actions: write | |
| outputs: | |
| has_config: ${{ steps.download.outputs.has_config || 'false' }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Download Customization Config | |
| id: download | |
| if: inputs.customization_config_url != '' | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $configUrl = '${{ inputs.customization_config_url }}' | |
| $configPath = Join-Path $env:RUNNER_TEMP 'customization.json' | |
| Write-Host "Downloading customization config from: $configUrl" | |
| Invoke-WebRequest -Uri $configUrl -OutFile $configPath -UseBasicParsing | |
| if (-not (Test-Path $configPath)) { | |
| Write-Error "Failed to download customization config." | |
| exit 1 | |
| } | |
| Write-Host "Downloaded customization config to $configPath" | |
| echo "has_config=true" >> $env:GITHUB_OUTPUT | |
| - name: Upload Customization Config | |
| if: inputs.customization_config_url != '' | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: CustomizationConfig | |
| path: ${{ runner.temp }}/customization.json | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| run-tests: | |
| name: Run Tests | |
| needs: set-version | |
| if: inputs.run_tests | |
| uses: ./.github/workflows/run-tests.yml | |
| with: | |
| use_self_hosted_runners: ${{ inputs.use_self_hosted_runners }} | |
| build-nugets: | |
| name: Build NuGet Packages | |
| needs: [set-version] | |
| if: inputs.build_nugets | |
| uses: ./.github/workflows/build-sign-pack-nugets.yml | |
| with: | |
| version: ${{ needs.set-version.outputs.version }} | |
| retention-days: ${{ fromJson(inputs.retention_days_artifacts) }} | |
| prerelease: ${{ inputs.prerelease }} | |
| use_self_hosted_runners: ${{ inputs.use_self_hosted_runners }} | |
| use_local_storage: ${{ inputs.use_local_storage }} | |
| secrets: inherit | |
| permissions: | |
| id-token: write | |
| contents: read | |
| build-mac-binaries: | |
| name: Apple Build (${{ matrix.arch }}) | |
| runs-on: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","macOS"]') || fromJson('["macos-26"]') }} | |
| needs: [set-version, download-customization] | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| strategy: | |
| matrix: | |
| arch: [osx-arm64, osx-x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Setup .NET | |
| if: inputs.use_self_hosted_runners == false | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Install macOS workload | |
| if: inputs.use_self_hosted_runners == false | |
| run: dotnet workload install macos | |
| - name: Setup Xcode | |
| if: inputs.use_self_hosted_runners == false | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: '26.5' | |
| - name: Setup Code Signing Keychain | |
| env: | |
| APPLE_P12_BASE64: ${{ secrets.APPLE_P12_BASE64 }} | |
| APPLE_P12_PASSWORD: ${{ secrets.APPLE_P12_PASSWORD }} | |
| APPLE_DEVELOPER_ID: ${{ secrets.APPLE_DEVELOPER_ID }} | |
| shell: bash | |
| run: | | |
| # Create temporary keychain | |
| KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain" | |
| KEYCHAIN_PASSWORD=$(openssl rand -base64 32) | |
| echo "Creating temporary keychain..." | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| echo "Configuring keychain settings..." | |
| security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" | |
| echo "Unlocking keychain..." | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| ORIGINAL_KEYCHAINS=$(security list-keychains -d user | xargs) | |
| echo "ORIGINAL_KEYCHAINS=$ORIGINAL_KEYCHAINS" >> "$GITHUB_ENV" | |
| echo "Adding temporary keychain to search list..." | |
| security list-keychains -d user -s "$KEYCHAIN_PATH" $ORIGINAL_KEYCHAINS | |
| echo "Decoding and importing certificate..." | |
| P12_PATH="$RUNNER_TEMP/certificate.p12" | |
| echo "$APPLE_P12_BASE64" | base64 --decode > "$P12_PATH" | |
| security import "$P12_PATH" \ | |
| -k "$KEYCHAIN_PATH" \ | |
| -P "$APPLE_P12_PASSWORD" \ | |
| -T /usr/bin/codesign \ | |
| -T /usr/bin/productsign | |
| echo "Setting partition list..." | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| echo "Verifying certificate import..." | |
| security find-identity -v -p codesigning "$KEYCHAIN_PATH" | |
| # Extract the unique SHA-1 hash for the identity in the temporary keychain | |
| IDENTITY_HASH=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" | grep "$APPLE_DEVELOPER_ID" | head -n 1 | awk '{print $2}') | |
| if [ -z "$IDENTITY_HASH" ]; then | |
| echo "ERROR: No signing identity found for APPLE_DEVELOPER_ID in temporary keychain." | |
| exit 1 | |
| fi | |
| echo "IDENTITY_HASH=$IDENTITY_HASH" >> "$GITHUB_ENV" | |
| - name: Download Customization Config | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: CustomizationConfig | |
| path: ${{ runner.temp }}/customization | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Apply Customization | |
| id: customize | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| shell: pwsh | |
| run: ./.scripts/Invoke-Customize.ps1 -ConfigPath '${{ runner.temp }}/customization/customization.json' -Version '${{ needs.set-version.outputs.version }}' | |
| - name: Set Default Branding | |
| if: needs.download-customization.outputs.has_config != 'true' | |
| shell: pwsh | |
| run: | | |
| echo "BRAND_KEY=ControlR" >> $env:GITHUB_ENV | |
| echo "UNIX_BRAND_KEY=controlr" >> $env:GITHUB_ENV | |
| - name: Validate Brand Keys | |
| shell: pwsh | |
| run: | | |
| if ([string]::IsNullOrEmpty($env:BRAND_KEY)) { throw "BRAND_KEY is empty" } | |
| if ([string]::IsNullOrEmpty($env:UNIX_BRAND_KEY)) { throw "UNIX_BRAND_KEY is empty" } | |
| Write-Host "BRAND_KEY=$env:BRAND_KEY UNIX_BRAND_KEY=$env:UNIX_BRAND_KEY" | |
| - name: Publish DesktopClient Bundle (${{ matrix.arch }}) | |
| run: | | |
| PUBLISH_DIR="${{github.workspace}}/ControlR.DesktopClient/bin/publish/${{ matrix.arch }}" | |
| DOWNLOADS_DIR="${{github.workspace}}/ControlR.Web.Server/wwwroot/downloads/${{ matrix.arch }}" | |
| mkdir -p "$DOWNLOADS_DIR" | |
| mkdir -p "$PUBLISH_DIR" | |
| echo "Publishing version $VERSION for macOS ${{ matrix.arch }}..." | |
| dotnet publish "./ControlR.DesktopClient/" \ | |
| -c Release \ | |
| -r ${{ matrix.arch }} \ | |
| -f net10.0-macos \ | |
| --self-contained \ | |
| -p:CreatePackage=false \ | |
| -p:EnableCodeSigning=false \ | |
| -p:AppBundleDir="$PUBLISH_DIR/${BRAND_KEY}.DesktopClient.app" \ | |
| -p:Version="$VERSION" \ | |
| -p:FileVersion="$VERSION" | |
| if [ ! -f "$PUBLISH_DIR/${BRAND_KEY}.DesktopClient.app/Contents/MacOS/${BRAND_KEY}.DesktopClient" ]; then | |
| ls -la "$PUBLISH_DIR/" || true | |
| echo "ERROR: DesktopClient publish output missing: $PUBLISH_DIR/${BRAND_KEY}.DesktopClient.app/Contents/MacOS/${BRAND_KEY}.DesktopClient" | |
| exit 1 | |
| fi | |
| mv "$PUBLISH_DIR/${BRAND_KEY}.DesktopClient.app" "$PUBLISH_DIR/${BRAND_KEY}.app" | |
| - name: Publish Agent (${{ matrix.arch }}) | |
| run: | | |
| AGENT_PUBLISH_DIR="${{ github.workspace }}/ControlR.Agent/bin/publish/${{ matrix.arch }}" | |
| dotnet publish "./ControlR.Agent/" \ | |
| -c Release \ | |
| -r ${{ matrix.arch }} \ | |
| --self-contained \ | |
| -p:PublishSingleFile=true \ | |
| -p:UseAppHost=true \ | |
| -p:Version=$VERSION \ | |
| -p:FileVersion=$VERSION \ | |
| -p:IncludeAllContentForSelfExtract=true \ | |
| -p:EnableCompressionInSingleFile=true \ | |
| -p:IncludeAppSettingsInSingleFile=true \ | |
| -o "$AGENT_PUBLISH_DIR" | |
| if [ ! -f "$AGENT_PUBLISH_DIR/${BRAND_KEY}.Agent" ]; then | |
| ls -la "$AGENT_PUBLISH_DIR/" || true | |
| echo "ERROR: Agent publish output missing: $AGENT_PUBLISH_DIR/${BRAND_KEY}.Agent" | |
| exit 1 | |
| fi | |
| - name: Stage and Sign Bundle (${{ matrix.arch }}) | |
| run: | | |
| PUBLISH_DIR="${{github.workspace}}/ControlR.DesktopClient/bin/publish/${{ matrix.arch }}" | |
| AGENT_PUBLISH_DIR="${{ github.workspace }}/ControlR.Agent/bin/publish/${{ matrix.arch }}" | |
| EMBEDDED_AGENT_PATH="$PUBLISH_DIR/${BRAND_KEY}.app/Contents/Library/LaunchServices/${BRAND_KEY}.Agent" | |
| echo "Embedding agent helper inside app bundle..." | |
| mkdir -p "$PUBLISH_DIR/${BRAND_KEY}.app/Contents/Library/LaunchServices" | |
| cp "$AGENT_PUBLISH_DIR/${BRAND_KEY}.Agent" "$EMBEDDED_AGENT_PATH" | |
| echo "Code signing embedded helper for macOS ${{ matrix.arch }}..." | |
| codesign \ | |
| --force \ | |
| --options runtime \ | |
| --timestamp \ | |
| --entitlements "./ControlR.Agent/Entitlements.plist" \ | |
| --keychain "$RUNNER_TEMP/build.keychain" \ | |
| --sign "$IDENTITY_HASH" \ | |
| "$EMBEDDED_AGENT_PATH" | |
| shopt -s nullglob | |
| for lib in "$PUBLISH_DIR/${BRAND_KEY}.app/Contents/MonoBundle/"*.dylib; do | |
| codesign \ | |
| --force \ | |
| --options runtime \ | |
| --timestamp \ | |
| --keychain "$RUNNER_TEMP/build.keychain" \ | |
| --sign "$IDENTITY_HASH" \ | |
| "$lib" | |
| done | |
| echo "Code signing DesktopClient bundle for macOS ${{ matrix.arch }}..." | |
| codesign \ | |
| --force \ | |
| --options runtime \ | |
| --timestamp \ | |
| --entitlements "./ControlR.DesktopClient/Entitlements.plist" \ | |
| --keychain "$RUNNER_TEMP/build.keychain" \ | |
| --sign "$IDENTITY_HASH" \ | |
| "$PUBLISH_DIR/${BRAND_KEY}.app" | |
| echo "Verifying signed app bundle..." | |
| codesign --verify --deep --strict --verbose=2 "$PUBLISH_DIR/${BRAND_KEY}.app" | |
| - name: Package Bundle (${{ matrix.arch }}) | |
| env: | |
| APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| APPLE_API_KEY_ISSUER_ID: ${{ secrets.APPLE_API_KEY_ISSUER_ID }} | |
| APPLE_API_KEY_P8: ${{ secrets.APPLE_API_KEY_P8 }} | |
| run: | | |
| PUBLISH_DIR="${{github.workspace}}/ControlR.DesktopClient/bin/publish/${{ matrix.arch }}" | |
| DOWNLOADS_DIR="${{github.workspace}}/ControlR.Web.Server/wwwroot/downloads/${{ matrix.arch }}" | |
| BUNDLE_ZIP="$DOWNLOADS_DIR/${BRAND_KEY}.Agent.bundle.zip" | |
| if [ "${{ inputs.notarize_mac_bundle }}" = "true" ]; then | |
| API_KEY_PATH="$RUNNER_TEMP/apple_api_key.p8" | |
| SUBMISSION_ZIP="$RUNNER_TEMP/${BRAND_KEY}.Agent.bundle.${{ matrix.arch }}.zip" | |
| echo "$APPLE_API_KEY_P8" | base64 --decode > "$API_KEY_PATH" | |
| rm -f "$SUBMISSION_ZIP" | |
| ditto -c -k --sequesterRsrc --keepParent "$PUBLISH_DIR/${BRAND_KEY}.app" "$SUBMISSION_ZIP" | |
| echo "Submitting bundle for notarization (${{ matrix.arch }})..." | |
| xcrun notarytool submit "$SUBMISSION_ZIP" \ | |
| --key "$API_KEY_PATH" \ | |
| --key-id "$APPLE_API_KEY_ID" \ | |
| --issuer "$APPLE_API_KEY_ISSUER_ID" \ | |
| --wait | |
| echo "Stapling notarization ticket to app bundle..." | |
| xcrun stapler staple "$PUBLISH_DIR/${BRAND_KEY}.app" | |
| rm -f "$SUBMISSION_ZIP" | |
| rm -f "$API_KEY_PATH" | |
| fi | |
| echo "Creating final bundle ZIP for macOS ${{ matrix.arch }}..." | |
| rm -f "$BUNDLE_ZIP" | |
| ditto -c -k --sequesterRsrc --keepParent "$PUBLISH_DIR/${BRAND_KEY}.app" "$BUNDLE_ZIP" | |
| - name: Publish Installer (${{ matrix.arch }}) | |
| run: | | |
| DOWNLOADS_DIR="${{github.workspace}}/ControlR.Web.Server/wwwroot/downloads/${{ matrix.arch }}" | |
| dotnet publish "./ControlR.Agent.Installer/" \ | |
| -c Release \ | |
| -r ${{ matrix.arch }} \ | |
| --self-contained \ | |
| -p:PublishSingleFile=true \ | |
| -p:UseAppHost=true \ | |
| -p:EnableCompressionInSingleFile=true \ | |
| -p:Version=$VERSION \ | |
| -p:FileVersion=$VERSION \ | |
| -p:DebugType=none \ | |
| -o "$DOWNLOADS_DIR" | |
| if [ ! -f "$DOWNLOADS_DIR/${BRAND_KEY}.Agent.Installer" ]; then | |
| ls -la "$DOWNLOADS_DIR" || true | |
| echo "ERROR: Installer publish output missing: $DOWNLOADS_DIR/${BRAND_KEY}.Agent.Installer" | |
| exit 1 | |
| fi | |
| - name: Sign Installer (${{ matrix.arch }}) | |
| run: | | |
| DOWNLOADS_DIR="${{github.workspace}}/ControlR.Web.Server/wwwroot/downloads/${{ matrix.arch }}" | |
| INSTALLER_PATH="$DOWNLOADS_DIR/${BRAND_KEY}.Agent.Installer" | |
| echo "Code signing Installer for macOS ${{ matrix.arch }}..." | |
| codesign \ | |
| --force \ | |
| --options runtime \ | |
| --timestamp \ | |
| --entitlements "./ControlR.Agent/Entitlements.plist" \ | |
| --keychain "$RUNNER_TEMP/build.keychain" \ | |
| --sign "$IDENTITY_HASH" \ | |
| "$INSTALLER_PATH" | |
| codesign --verify --strict --verbose=2 "$INSTALLER_PATH" | |
| - name: Upload Downloads (${{ matrix.arch }}) | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: Downloads-${{ matrix.arch }} | |
| path: ControlR.Web.Server/wwwroot/downloads/${{ matrix.arch }}/ | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Cleanup Keychain | |
| if: always() | |
| run: | | |
| KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain" | |
| if [ -n "$ORIGINAL_KEYCHAINS" ]; then | |
| echo "Restoring original keychain search list..." | |
| security list-keychains -d user -s $ORIGINAL_KEYCHAINS | |
| fi | |
| if [ -f "$KEYCHAIN_PATH" ]; then | |
| echo "Removing temporary keychain..." | |
| security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true | |
| fi | |
| 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: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","Windows"]') || fromJson('["windows-latest"]') }} | |
| environment: ${{ github.repository == 'bitbound/ControlR' && 'production' || 'development' }} | |
| needs: [set-version, download-customization] | |
| permissions: | |
| id-token: write | |
| contents: read | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| strategy: | |
| matrix: | |
| arch: [win-x86, win-x64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Setup .NET | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Download Customization Config | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: CustomizationConfig | |
| path: ${{ runner.temp }}/customization | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Apply Customization | |
| id: customize | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| shell: pwsh | |
| run: ./.scripts/Invoke-Customize.ps1 -ConfigPath '${{ runner.temp }}/customization/customization.json' -Version '${{ needs.set-version.outputs.version }}' | |
| - name: Set Default Branding | |
| if: needs.download-customization.outputs.has_config != 'true' | |
| shell: pwsh | |
| run: | | |
| echo "BRAND_KEY=ControlR" >> $env:GITHUB_ENV | |
| echo "UNIX_BRAND_KEY=controlr" >> $env:GITHUB_ENV | |
| - name: Validate Brand Keys | |
| shell: pwsh | |
| run: | | |
| if ([string]::IsNullOrEmpty($env:BRAND_KEY)) { throw "BRAND_KEY is empty" } | |
| if ([string]::IsNullOrEmpty($env:UNIX_BRAND_KEY)) { throw "UNIX_BRAND_KEY is empty" } | |
| Write-Host "BRAND_KEY=$env:BRAND_KEY UNIX_BRAND_KEY=$env:UNIX_BRAND_KEY" | |
| # ===== Build Windows ===== | |
| - name: Build DesktopClient (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| # Build DesktopClient | |
| dotnet publish ControlR.DesktopClient\ -c Release -f net10.0-windows8.0 -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 }}) | |
| uses: ./.github/actions/windows-code-sign | |
| with: | |
| file-patterns: | | |
| ${{ github.workspace }}\ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\*.exe | |
| ${{ github.workspace }}\ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\*.dll | |
| azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| azure-subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| azure-key-vault-uri: ${{ secrets.AZURE_KEY_VAULT_URI }} | |
| azure-key-vault-certificate-name: ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} | |
| signing-description-url: ${{ vars.SIGNING_DESCRIPTION_URL }} | |
| - name: Package and Prepare DesktopClient (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| # Create staging directory | |
| $stagingDir = Join-Path $env:RUNNER_TEMP "staging-desktop/${{ matrix.arch }}" | |
| New-Item -Path $stagingDir -ItemType Directory -Force | Out-Null | |
| # Create ZIP | |
| Compress-Archive -Path "ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\*" -DestinationPath (Join-Path $stagingDir "$env:BRAND_KEY.DesktopClient.zip") -Force | |
| - name: Azure Login For Agent Publish (${{ matrix.arch }}) | |
| uses: azure/login@v3 | |
| with: | |
| client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| - name: Install AzureSignTool For Agent Publish (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| dotnet tool update --global AzureSignTool | |
| if ($LASTEXITCODE -ne 0) { | |
| dotnet tool install --global AzureSignTool | |
| if ($LASTEXITCODE -ne 0) { | |
| exit $LASTEXITCODE | |
| } | |
| } | |
| - name: Build Agent (${{ matrix.arch }}) | |
| shell: pwsh | |
| env: | |
| AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} | |
| AZURE_KEY_VAULT_CERTIFICATE_NAME: ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} | |
| SIGNING_DESCRIPTION_URL: ${{ vars.SIGNING_DESCRIPTION_URL }} | |
| TIMESTAMP_URL: http://timestamp.digicert.com | |
| run: | | |
| $agentPublishDir = "ControlR.Agent\bin\publish\${{ matrix.arch }}\" | |
| New-Item -Path $agentPublishDir -ItemType Directory -Force | Out-Null | |
| 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 $agentPublishDir -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$env:VERSION -p:FileVersion=$env:VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true -p:DebugType=none | |
| - name: Sign Agent (${{ matrix.arch }}) | |
| uses: ./.github/actions/windows-code-sign | |
| env: | |
| BRAND_KEY: ${{ env.BRAND_KEY }} | |
| with: | |
| file-patterns: ${{ github.workspace }}\ControlR.Agent\bin\publish\${{ matrix.arch }}\${{ env.BRAND_KEY }}.Agent.exe | |
| azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| azure-subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| azure-key-vault-uri: ${{ secrets.AZURE_KEY_VAULT_URI }} | |
| azure-key-vault-certificate-name: ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} | |
| signing-description-url: ${{ vars.SIGNING_DESCRIPTION_URL }} | |
| - name: Build Installer (${{ matrix.arch }}) | |
| shell: pwsh | |
| env: | |
| AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} | |
| AZURE_KEY_VAULT_CERTIFICATE_NAME: ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} | |
| SIGNING_DESCRIPTION_URL: ${{ vars.SIGNING_DESCRIPTION_URL }} | |
| TIMESTAMP_URL: http://timestamp.digicert.com | |
| run: | | |
| dotnet publish ControlR.Agent.Installer\ -c Release -r ${{ matrix.arch }} --self-contained -o ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\ -p:PublishSingleFile=true -p:UseAppHost=true -p:EnableCompressionInSingleFile=true -p:Version=$env:VERSION -p:FileVersion=$env:VERSION -p:DebugType=none | |
| - name: Sign Installer (${{ matrix.arch }}) | |
| uses: ./.github/actions/windows-code-sign | |
| env: | |
| BRAND_KEY: ${{ env.BRAND_KEY }} | |
| with: | |
| file-patterns: ${{ github.workspace }}\ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\${{ env.BRAND_KEY }}.Agent.Installer.exe | |
| azure-client-id: ${{ secrets.AZURE_CLIENT_ID }} | |
| azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }} | |
| azure-subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} | |
| azure-key-vault-uri: ${{ secrets.AZURE_KEY_VAULT_URI }} | |
| azure-key-vault-certificate-name: ${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }} | |
| signing-description-url: ${{ vars.SIGNING_DESCRIPTION_URL }} | |
| - name: Create Bundle ZIP (${{ matrix.arch }}) | |
| shell: pwsh | |
| run: | | |
| $agentPublishDir = "ControlR.Agent\bin\publish\${{ matrix.arch }}\" | |
| $bundleDir = Join-Path $env:RUNNER_TEMP "bundle/${{ matrix.arch }}" | |
| $desktopDir = Join-Path $bundleDir "DesktopClient" | |
| Remove-Item -Path $bundleDir -Recurse -Force -ErrorAction SilentlyContinue | |
| New-Item -Path $desktopDir -ItemType Directory -Force | Out-Null | |
| Copy-Item (Join-Path $agentPublishDir "$env:BRAND_KEY.Agent.exe") (Join-Path $bundleDir "$env:BRAND_KEY.Agent.exe") -Force | |
| Copy-Item "ControlR.DesktopClient\bin\publish\${{ matrix.arch }}\*" $desktopDir -Recurse -Force | |
| Compress-Archive -Path "$bundleDir\*" -DestinationPath "ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\$env:BRAND_KEY.Agent.bundle.zip" -Force | |
| - name: Upload Downloads (${{ matrix.arch }}) | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: Downloads-${{ matrix.arch }} | |
| path: ControlR.Web.Server\wwwroot\downloads\${{ matrix.arch }}\ | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| build-linux-binaries: | |
| name: Linux Build | |
| runs-on: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","Linux"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: [set-version, download-customization] | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Setup .NET | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Install macOS workload | |
| run: dotnet workload install macos | |
| - name: Download Customization Config | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: CustomizationConfig | |
| path: ${{ runner.temp }}/customization | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Apply Customization | |
| id: customize | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| shell: pwsh | |
| run: ./.scripts/Invoke-Customize.ps1 -ConfigPath '${{ runner.temp }}/customization/customization.json' -Version '${{ needs.set-version.outputs.version }}' | |
| - name: Set Default Branding | |
| if: needs.download-customization.outputs.has_config != 'true' | |
| shell: pwsh | |
| run: | | |
| echo "BRAND_KEY=ControlR" >> $env:GITHUB_ENV | |
| echo "UNIX_BRAND_KEY=controlr" >> $env:GITHUB_ENV | |
| - name: Validate Brand Keys | |
| shell: pwsh | |
| run: | | |
| if ([string]::IsNullOrEmpty($env:BRAND_KEY)) { throw "BRAND_KEY is empty" } | |
| if ([string]::IsNullOrEmpty($env:UNIX_BRAND_KEY)) { throw "UNIX_BRAND_KEY is empty" } | |
| Write-Host "BRAND_KEY=$env:BRAND_KEY UNIX_BRAND_KEY=$env:UNIX_BRAND_KEY" | |
| - name: Build DesktopClient (linux-x64) | |
| run: | | |
| # Build DesktopClient | |
| dotnet publish ./ControlR.DesktopClient/ -c Release -f net10.0 -r linux-x64 --self-contained -o ./ControlR.DesktopClient/bin/publish/linux-x64/ -p:Version=$VERSION -p:FileVersion=$VERSION | |
| # Create staging directory | |
| mkdir -p "$RUNNER_TEMP/staging-desktop/linux-x64" | |
| # Create ZIP | |
| cd ./ControlR.DesktopClient/bin/publish/linux-x64 | |
| zip -r "$RUNNER_TEMP/staging-desktop/linux-x64/${BRAND_KEY}.DesktopClient.zip" . | |
| cd ${{ github.workspace}} | |
| - name: Build Agent (linux-x64) | |
| run: | | |
| mkdir -p "./ControlR.Agent/bin/publish/linux-x64" | |
| mkdir -p "./ControlR.Web.Server/wwwroot/downloads/linux-x64" | |
| dotnet publish ./ControlR.Agent/ -c Release -r linux-x64 -o ./ControlR.Agent/bin/publish/linux-x64/ -p:PublishSingleFile=true -p:UseAppHost=true -p:Version=$VERSION -p:FileVersion=$VERSION -p:IncludeAllContentForSelfExtract=true -p:EnableCompressionInSingleFile=true -p:IncludeAppSettingsInSingleFile=true -p:DebugType=none | |
| - name: Build Installer (linux-x64) | |
| run: | | |
| dotnet publish ./ControlR.Agent.Installer/ -c Release -r linux-x64 --self-contained -o ./ControlR.Web.Server/wwwroot/downloads/linux-x64/ -p:PublishSingleFile=true -p:UseAppHost=true -p:EnableCompressionInSingleFile=true -p:Version=$VERSION -p:FileVersion=$VERSION -p:DebugType=none | |
| - name: Create Bundle ZIP (linux-x64) | |
| run: | | |
| rm -rf "$RUNNER_TEMP/bundle/linux-x64" | |
| mkdir -p "$RUNNER_TEMP/bundle/linux-x64/DesktopClient" | |
| cp "./ControlR.Agent/bin/publish/linux-x64/${BRAND_KEY}.Agent" "$RUNNER_TEMP/bundle/linux-x64/${BRAND_KEY}.Agent" | |
| cp -R ./ControlR.DesktopClient/bin/publish/linux-x64/. "$RUNNER_TEMP/bundle/linux-x64/DesktopClient/" | |
| cd "$RUNNER_TEMP/bundle/linux-x64" | |
| zip -r "${{ github.workspace }}/ControlR.Web.Server/wwwroot/downloads/linux-x64/${BRAND_KEY}.Agent.bundle.zip" . | |
| cd "${{ github.workspace }}" | |
| - name: Upload Downloads (linux-x64) | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: Downloads-linux-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/linux-x64/ | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| build-web-server: | |
| name: Build Web Server | |
| runs-on: ${{ inputs.use_self_hosted_runners && fromJson('["self-hosted","Windows"]') || fromJson('["ubuntu-latest"]') }} | |
| needs: | |
| [ | |
| set-version, | |
| download-customization, | |
| build-windows-binaries, | |
| build-linux-binaries, | |
| build-mac-binaries, | |
| ] | |
| env: | |
| VERSION: ${{ needs.set-version.outputs.version }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| submodules: recursive | |
| ref: ${{ inputs.ref || '' }} | |
| - name: Setup .NET | |
| uses: ./.github/actions/setup-dotnet | |
| - name: Download Customization Config | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: CustomizationConfig | |
| path: ${{ runner.temp }}/customization | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Apply Customization | |
| id: customize | |
| if: needs.download-customization.outputs.has_config == 'true' | |
| shell: pwsh | |
| run: ./.scripts/Invoke-Customize.ps1 -ConfigPath '${{ runner.temp }}/customization/customization.json' -Version '${{ env.VERSION }}' | |
| - name: Set Default Branding | |
| if: needs.download-customization.outputs.has_config != 'true' | |
| shell: pwsh | |
| run: | | |
| echo "BRAND_KEY=ControlR" >> $env:GITHUB_ENV | |
| echo "UNIX_BRAND_KEY=controlr" >> $env:GITHUB_ENV | |
| - name: Validate Brand Keys | |
| shell: pwsh | |
| run: | | |
| if ([string]::IsNullOrEmpty($env:BRAND_KEY)) { throw "BRAND_KEY is empty" } | |
| if ([string]::IsNullOrEmpty($env:UNIX_BRAND_KEY)) { throw "UNIX_BRAND_KEY is empty" } | |
| Write-Host "BRAND_KEY=$env:BRAND_KEY UNIX_BRAND_KEY=$env:UNIX_BRAND_KEY" | |
| - name: Download Runtime Artifacts (win-x86) | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: Downloads-win-x86 | |
| path: ControlR.Web.Server/wwwroot/downloads/win-x86/ | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Download Runtime Artifacts (win-x64) | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: Downloads-win-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/win-x64/ | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Download Runtime Artifacts (linux-x64) | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: Downloads-linux-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/linux-x64/ | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Download Runtime Artifacts (macOS ARM64) | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: Downloads-osx-arm64 | |
| path: ControlR.Web.Server/wwwroot/downloads/osx-arm64/ | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Download Runtime Artifacts (macOS x64) | |
| uses: ./.github/actions/download-artifact | |
| with: | |
| name: Downloads-osx-x64 | |
| path: ControlR.Web.Server/wwwroot/downloads/osx-x64/ | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Create Version.txt | |
| shell: pwsh | |
| run: | | |
| Set-Content -Path "ControlR.Web.Server/wwwroot/downloads/Version.txt" -Value $env:VERSION -Force -Encoding UTF8 | |
| - name: Copy Release Notes | |
| shell: pwsh | |
| run: | | |
| if (Test-Path ".release-notes/current.md") { | |
| Copy-Item -Path ".release-notes/current.md" -Destination "ControlR.Web.Server/wwwroot/downloads/release-notes.md" -Force | |
| } else { | |
| Write-Host "No .release-notes/current.md found. Creating placeholder." | |
| @" | |
| ## $env:VERSION | |
| _No release notes available yet._ | |
| "@ | Set-Content -Path "ControlR.Web.Server/wwwroot/downloads/release-notes.md" -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 ${{ inputs.server_runtime }} --configuration Release -p:Version=$env:VERSION -p:FileVersion=$env:VERSION --output ControlR.Web.Server/bin/publish --self-contained true | |
| - name: Create Dockerfile | |
| shell: pwsh | |
| run: | | |
| @" | |
| FROM mcr.microsoft.com/dotnet/aspnet:10.0 | |
| RUN apt update | |
| RUN apt -y install curl | |
| USER `$APP_UID | |
| WORKDIR /app | |
| EXPOSE 8080 | |
| EXPOSE 8081 | |
| COPY . /app | |
| ENTRYPOINT ["dotnet", "ControlR.Web.Server.dll"] | |
| HEALTHCHECK \ | |
| CMD curl -f http://localhost:8080/health || exit 1 | |
| "@ | Set-Content -Path "ControlR.Web.Server/bin/publish/Dockerfile" -Encoding UTF8 | |
| - name: Verify Download Artifacts | |
| shell: pwsh | |
| run: | | |
| $TestPaths = @( | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/Version.txt", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/release-notes.md", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x86/$env:BRAND_KEY.Agent.Installer.exe", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x64/$env:BRAND_KEY.Agent.Installer.exe", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x86/$env:BRAND_KEY.Agent.bundle.zip", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/win-x64/$env:BRAND_KEY.Agent.bundle.zip", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/linux-x64/$env:BRAND_KEY.Agent.Installer", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/linux-x64/$env:BRAND_KEY.Agent.bundle.zip", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-arm64/$env:BRAND_KEY.Agent.Installer", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-arm64/$env:BRAND_KEY.Agent.bundle.zip", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-x64/$env:BRAND_KEY.Agent.Installer", | |
| "ControlR.Web.Server/bin/publish/wwwroot/downloads/osx-x64/$env:BRAND_KEY.Agent.bundle.zip", | |
| "ControlR.Web.Server/bin/publish/wwwroot/lib/monaco-editor/min/vs/editor/editor.main.js", | |
| "ControlR.Web.Server/bin/publish/novnc/vnc.html", | |
| "ControlR.Web.Server/bin/publish/Dockerfile" | |
| ) | |
| foreach ($TestPath in $TestPaths) { | |
| if (!(Test-Path $TestPath)) { | |
| Write-Error "$TestPath not found." | |
| exit 1 | |
| } | |
| } | |
| - name: Upload Server | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: Server | |
| path: ControlR.Web.Server/bin/publish | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Upload docker-compose | |
| uses: ./.github/actions/upload-artifact | |
| with: | |
| name: DockerCompose | |
| path: docker-compose/docker-compose.yml | |
| retention-days: ${{ env.RETENTION_DAYS_ARTIFACTS }} | |
| artifact-host: ${{ inputs.use_local_storage && vars.ARTIFACT_HOST || '' }} | |
| artifact-base-path: ${{ inputs.use_local_storage && vars.ARTIFACT_BASE_PATH || '' }} | |
| - name: Print Build Summary | |
| shell: pwsh | |
| env: | |
| VERSION: ${{ env.VERSION }} | |
| run: | | |
| echo "## Build Summary" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Version:** v${{ env.VERSION }}" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Git Ref:** ${{ github.ref }}" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Use Self-Hosted Runners:** ${{ inputs.use_self_hosted_runners }}" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Use Local Storage for Artifacts:** ${{ inputs.use_local_storage }}" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Customization Config URL:** ${{ inputs.customization_config_url }}" >> $env:GITHUB_STEP_SUMMARY | |
| echo "**Pre-release:** ${{ inputs.prerelease }}" >> $env:GITHUB_STEP_SUMMARY |