diff --git a/.github/workflows/build-and-sign-sequential.yml b/.github/workflows/build-and-sign-sequential.yml index 3c9c060..5a1ddf1 100644 --- a/.github/workflows/build-and-sign-sequential.yml +++ b/.github/workflows/build-and-sign-sequential.yml @@ -23,6 +23,10 @@ on: env: BUILD_CONFIGURATION: Release +permissions: + contents: read + actions: write + jobs: # Single Sequential Job - Build everything in specified order build-sequential: @@ -34,101 +38,15 @@ jobs: # Setup build environment - name: Setup MSBuild - uses: microsoft/setup-msbuild@v1 + uses: microsoft/setup-msbuild@v2 - - name: Install Visual Studio 2022 dependencies - run: | - Write-Output "Installing Visual Studio 2022 dependencies..." - choco install visualstudio2022-workload-manageddesktop -y - if ($LASTEXITCODE -ne 0) { exit 1 } - - choco install visualstudio2022-workload-nativedesktop -y - if ($LASTEXITCODE -ne 0) { exit 1 } - - choco install visualstudio2022-workload-vctools -y - if ($LASTEXITCODE -ne 0) { exit 1 } - - choco install innosetup -y - if ($LASTEXITCODE -ne 0) { exit 1 } - - - name: Install Windows SDK + WDK (required for WDF/UMDF headers) + - name: Install Windows Driver Kit (WDK) for WDF/UMDF headers shell: pwsh run: | $ErrorActionPreference = "Stop" - - function Ensure-WingetPackage([string]$Id) { - Write-Output "Checking $Id..." - $listed = (winget list --id $Id -e | Out-String) - if ($listed -match [regex]::Escape($Id)) { - Write-Output "✅ $Id already installed" - return - } - - Write-Output "Installing $Id via winget..." - winget install --source winget --exact --id $Id --accept-package-agreements --accept-source-agreements --silent - if ($LASTEXITCODE -ne 0) { - Write-Error "❌ winget install failed for $Id (exit code $LASTEXITCODE)" - exit $LASTEXITCODE - } - Write-Output "✅ Installed $Id" - } - - winget --version - - # Install matching SDK + WDK (per Microsoft guidance). - # Update these IDs if you intentionally move to another kit version. - Ensure-WingetPackage "Microsoft.WindowsSDK.10.0.26100" - Ensure-WingetPackage "Microsoft.WindowsWDK.10.0.26100" - - - name: Detect Windows Kits version (WDF/UMDF headers) - shell: pwsh - run: | - $kitsRoot = $null - try { - $kitsRoot = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots" -Name "KitsRoot10" -ErrorAction Stop).KitsRoot10 - } catch { - $kitsRoot = Join-Path ${env:ProgramFiles(x86)} "Windows Kits\10\" - } - - if (-not $kitsRoot -or -not (Test-Path $kitsRoot)) { - Write-Error "Windows Kits root not found: $kitsRoot" - exit 1 - } - - $includeRoots = - @((Join-Path $kitsRoot "Include")) | Where-Object { Test-Path $_ } - - if (-not $includeRoots -or $includeRoots.Count -eq 0) { - Write-Error "No Windows Kits Include directories found under: $kitsRoot" - exit 1 - } - - $candidates = foreach ($includeRoot in $includeRoots) { - Get-ChildItem -Path $includeRoot -Directory -ErrorAction SilentlyContinue | - Where-Object { Test-Path (Join-Path $_.FullName "wdf\umdf\wudfwdm.h") } | - ForEach-Object { - [PSCustomObject]@{ - Version = $_.Name - IncludeRoot = $includeRoot - } - } - } - - $best = $candidates | Sort-Object -Property Version -Descending | Select-Object -First 1 - $kitVersion = $best.Version - - if (-not $kitVersion) { - Write-Error "Could not find any Windows Kits version containing wdf\umdf\wudfwdm.h under: $kitsRoot" - Write-Output "Discovered Include roots:" - $includeRoots | ForEach-Object { Write-Output ("- " + $_) } - exit 1 - } - - $windowsSdkDir = (Split-Path $best.IncludeRoot -Parent) + "\" - Write-Output "Using WindowsTargetPlatformVersion: $kitVersion" - Write-Output "Using WindowsSdkDir: $windowsSdkDir" - "WINDOWS_TARGET_PLATFORM_VERSION=$kitVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - "WINDOWS_SDK_DIR=$windowsSdkDir" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + Write-Output "Ensuring Windows Driver Kit is installed (Chocolatey: windowsdriverkit11)..." + choco install windowsdriverkit11 -y --no-progress + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } - name: Setup .NET uses: actions/setup-dotnet@v4 @@ -147,7 +65,7 @@ jobs: $vddSln = "Virtual Display Driver (HDR)/MTTVDD.sln" if (Test-Path $vddSln) { Write-Output "Found VDD solution: $vddSln" - msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /p:WindowsSdkDir=$env:WINDOWS_SDK_DIR /p:WindowsTargetPlatformVersion=$env:WINDOWS_TARGET_PLATFORM_VERSION /verbosity:minimal + msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /verbosity:minimal if ($LASTEXITCODE -eq 0) { Write-Output "✅ ARM64 VDD build completed successfully" @@ -181,7 +99,7 @@ jobs: Write-Output "Building ARM64 VAD with validation disabled..." # Build with validation disabled to avoid x86 tool conflicts with ARM64 outputs - msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /p:WindowsSdkDir=$env:WINDOWS_SDK_DIR /p:WindowsTargetPlatformVersion=$env:WINDOWS_TARGET_PLATFORM_VERSION /p:EnableInfVerif=false /p:RunApiValidator=false /verbosity:minimal + msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=ARM64 /p:EnableInfVerif=false /p:RunApiValidator=false /verbosity:minimal if ($LASTEXITCODE -eq 0) { Write-Output "✅ ARM64 VAD build completed successfully!" @@ -209,7 +127,7 @@ jobs: $vddSln = "Virtual Display Driver (HDR)/MTTVDD.sln" if (Test-Path $vddSln) { Write-Output "Found VDD solution: $vddSln" - msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /p:WindowsSdkDir=$env:WINDOWS_SDK_DIR /p:WindowsTargetPlatformVersion=$env:WINDOWS_TARGET_PLATFORM_VERSION /verbosity:minimal + msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal if ($LASTEXITCODE -eq 0) { Write-Output "✅ x64 VDD build completed successfully" @@ -238,7 +156,7 @@ jobs: $vadSln = "Virtual-Audio-Driver (Latest Stable)/VirtualAudioDriver.sln" if (Test-Path $vadSln) { Write-Output "Found VAD solution: $vadSln" - msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /p:WindowsSdkDir=$env:WINDOWS_SDK_DIR /p:WindowsTargetPlatformVersion=$env:WINDOWS_TARGET_PLATFORM_VERSION /verbosity:minimal + msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal if ($LASTEXITCODE -eq 0) { Write-Output "✅ x64 VAD build completed successfully" @@ -266,6 +184,7 @@ jobs: New-Item -ItemType Directory -Path "final-build\ARM64" -Force New-Item -ItemType Directory -Path "final-build\x64" -Force New-Item -ItemType Directory -Path "final-build\ControlApp" -Force + New-Item -ItemType Directory -Path "final-build\ControlApp-ARM64" -Force # Checkout Virtual Driver Control Repository - name: Checkout Virtual Driver Control Repository @@ -390,6 +309,13 @@ jobs: $installerPath = "installer-repo" if (Test-Path $installerPath) { Push-Location $installerPath + + # Ensure Inno Setup is available for iscc + if (-not (Get-Command iscc -ErrorAction SilentlyContinue)) { + Write-Output "Installing Inno Setup..." + choco install innosetup -y --no-progress + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + } # Generate release tag $releaseTag = (Get-Date).ToString('yy.MM.dd') @@ -510,7 +436,7 @@ jobs: # STEP 8: Submit to SignPath - name: "Step 8: Submit to SignPath" - if: github.event.inputs.skip_signing != 'true' && steps.upload_for_signpath.outputs.artifact-id != '' + if: github.event.inputs.skip_signing != 'true' && secrets.SIGNPATH_API_TOKEN != '' && vars.SIGNPATH_ORG_ID != '' && vars.SIGNPATH_PROJECT_SLUG != '' && vars.SIGNPATH_POLICY_SLUG != '' && steps.upload_for_signpath.outputs.artifact-id != '' id: signpath_request uses: signpath/github-action-submit-signing-request@v1 with: diff --git a/.github/workflows/build-installer.yml b/.github/workflows/build-installer.yml new file mode 100644 index 0000000..f4f52bc --- /dev/null +++ b/.github/workflows/build-installer.yml @@ -0,0 +1,124 @@ +name: Build Installer Only + +on: + workflow_dispatch: + inputs: + installer_variant: + description: 'Installer variant to build' + required: true + default: 'mixed' + type: choice + options: + - mixed + - x64-only + - arm64-only + version_override: + description: 'Override version (format: YY.MM.DD)' + required: false + type: string + schedule: + - cron: '0 6 * * 1' # Weekly on Monday morning + +env: + BUILD_CONFIGURATION: Release + +permissions: + contents: read + actions: write + +jobs: + build-installer: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Version + shell: pwsh + run: | + $version = "${{ github.event.inputs.version_override }}" + if ([string]::IsNullOrEmpty($version)) { + $version = (Get-Date).ToString('yy.MM.dd') + } + "INSTALLER_VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + Write-Output "Using version: $version" + + $variant = "${{ github.event.inputs.installer_variant }}" + if ([string]::IsNullOrEmpty($variant)) { $variant = "mixed" } + "INSTALLER_VARIANT=$variant" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + Write-Output "Building installer variant: $variant" + + - name: Checkout Virtual Driver Installer Repository + uses: actions/checkout@v4 + with: + repository: 'VirtualDrivers/Virtual-Driver-Installer' + path: 'installer-repo' + token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + + - name: Build Installer + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + Write-Output "=== Building Virtual Driver Installer ===" + Write-Output "Variant: $env:INSTALLER_VARIANT" + Write-Output "Version: $env:INSTALLER_VERSION" + + if (-not (Test-Path "installer-repo")) { + throw "Installer repository checkout not found (installer-repo)." + } + + Push-Location installer-repo + + if (-not (Get-Command iscc -ErrorAction SilentlyContinue)) { + Write-Output "Installing Inno Setup..." + choco install innosetup -y --no-progress + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + } + + if (Test-Path "Setup.iss") { + $setupContent = Get-Content "Setup.iss" + $setupContent = $setupContent -replace '#define MyAppVersion ".*"', "#define MyAppVersion `"$env:INSTALLER_VERSION`"" + + switch ($env:INSTALLER_VARIANT) { + "x64-only" { + $setupContent = $setupContent -replace 'OutputBaseFilename=.*', "OutputBaseFilename=Virtual-Driver-Control-v$env:INSTALLER_VERSION-setup-x64-only" + } + "arm64-only" { + $setupContent = $setupContent -replace 'OutputBaseFilename=.*', "OutputBaseFilename=Virtual-Driver-Control-v$env:INSTALLER_VERSION-setup-arm64-only" + } + default { + $setupContent = $setupContent -replace 'OutputBaseFilename=.*', "OutputBaseFilename=Virtual-Driver-Control-v$env:INSTALLER_VERSION-setup-mixed-platform" + } + } + + $setupContent | Set-Content "Setup.iss" + } else { + throw "Setup.iss not found in installer repo." + } + + if (Test-Path "build-installer.ps1") { + Write-Output "Running installer preparation script..." + .\build-installer.ps1 + } + + Write-Output "Compiling installer with Inno Setup..." + iscc Setup.iss + + if ($LASTEXITCODE -ne 0) { throw "Inno Setup compilation failed." } + if (-not (Test-Path "output\\*.exe")) { throw "No installer EXE found under output\\." } + + $installerFile = Get-ChildItem "output\\*.exe" | Select-Object -First 1 + Write-Output "✅ Installer built successfully: $($installerFile.Name)" + "INSTALLER_NAME=$($installerFile.Name)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + Pop-Location + + - name: Upload Installer + uses: actions/upload-artifact@v4 + with: + name: Virtual-Driver-Installer-${{ env.INSTALLER_VERSION }}-${{ env.INSTALLER_VARIANT }} + path: installer-repo/output/*.exe + retention-days: 30 + diff --git a/.github/workflows/ci-validation.yml b/.github/workflows/ci-validation.yml new file mode 100644 index 0000000..2d60ee5 --- /dev/null +++ b/.github/workflows/ci-validation.yml @@ -0,0 +1,110 @@ +name: Fast CI Validation + +on: + pull_request: + branches: [ main, master ] + push: + branches: [ main, master ] + paths-ignore: + - '**.md' + - 'docs/**' + - 'LICENSE*' + +env: + BUILD_CONFIGURATION: Release + +permissions: + contents: read + +jobs: + validate: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup MSBuild + uses: microsoft/setup-msbuild@v2 + + - name: Install Windows Driver Kit (WDK) + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + choco install windowsdriverkit11 -y --no-progress + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '6.0.x' + + - name: Quick VDD Compilation Check + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + Write-Output "Performing quick VDD compilation check..." + $vddSln = "Virtual Display Driver (HDR)/MTTVDD.sln" + if (-not (Test-Path $vddSln)) { throw "VDD solution file not found at: $vddSln" } + msbuild $vddSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal /target:Build + + - name: Quick VAD Compilation Check + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + Write-Output "Performing quick VAD compilation check..." + $vadSln = "Virtual-Audio-Driver (Latest Stable)/VirtualAudioDriver.sln" + if (-not (Test-Path $vadSln)) { throw "VAD solution file not found at: $vadSln" } + msbuild $vadSln /p:Configuration=$env:BUILD_CONFIGURATION /p:Platform=x64 /verbosity:minimal /target:Build + + - name: Checkout Virtual Driver Control Repository + uses: actions/checkout@v4 + with: + repository: 'VirtualDrivers/Virtual-Driver-Control' + path: 'control-app-repo' + token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + + - name: Control App Dependencies and Lint Check + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + $controlAppPath = "" + + if (Test-Path "control-app-repo/VirtualDriverControl/package.json") { + $controlAppPath = "control-app-repo/VirtualDriverControl" + Write-Output "Found control app in separate repository" + } + + if ($controlAppPath -eq "") { + Write-Output "⚠️ Control App not found - skipping validation" + exit 0 + } + + Push-Location $controlAppPath + npm ci + + $packageJson = Get-Content "package.json" | ConvertFrom-Json + if ($packageJson.scripts.lint) { + npm run lint + } else { + Write-Output "No lint script found, skipping lint check" + } + + Pop-Location + + - name: CI Validation Summary + if: always() + shell: pwsh + run: | + Write-Output "=== Fast CI Validation Summary ===" + Write-Output "Configuration: $env:BUILD_CONFIGURATION" + Write-Output "Event: ${{ github.event_name }}" + Write-Output "Branch: ${{ github.ref }}" + Write-Output "Commit: ${{ github.sha }}" +