From 56b737378fd169289648154b5029560f88e5d391 Mon Sep 17 00:00:00 2001 From: Borislav Traykov Date: Fri, 30 Jan 2026 16:09:38 +0200 Subject: [PATCH 1/2] Enhance CI workflow with manual trigger and updates Added workflow_dispatch trigger and updated versioning and signing parameters. --- .github/workflows/build-and-publish.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index 5f943cb..0380d06 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -4,7 +4,8 @@ on: push: tags: - '*' - + workflow_dispatch: + env: BUILD_CONFIGURATION: Release DOTNET_VERSION: '9.x' @@ -33,6 +34,7 @@ jobs: shell: pwsh run: | $version = "${{ github.ref_name }}" + $version = "99.99.99" Write-Host "Version: $version" echo "version=$version" >> $env:GITHUB_OUTPUT @@ -130,10 +132,11 @@ jobs: dotnet nuget sign $nupkgPath ` --certificate-path $certPath ` - --certificate-password $env:CERT_PASS ` - --timestamper $env:TIMESTAMP_URL ` + --certificate-password "$env:SIGNING_CERTIFICATE_PASSWORD" ` + --timestamper "$env:SIGNING_CERTIFICATE_TIMESTAMP_URL" ` --overwrite + - name: NuGet login (OIDC Trusted Publishing) uses: nuget/login@v1 id: nuget-login @@ -141,6 +144,7 @@ jobs: user: ${{ secrets.NUGET_ORG_USER }} - name: Publish to NuGet.org + if: false # This step will never run run: | dotnet nuget push "${{ github.workspace }}\nupkg\*.nupkg" ` --api-key ${{ steps.nuget-login.outputs.nuget-api-key }} ` From 345e1ebf18e82a0971d4a0c9de55fc973279f9cd Mon Sep 17 00:00:00 2001 From: Borislav Traykov Date: Fri, 30 Jan 2026 16:14:01 +0200 Subject: [PATCH 2/2] Add GitHub Actions workflow for build and publish This workflow builds, signs, and publishes a .NET project as a NuGet package. --- .github/workflows/signing.yml | 151 ++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 .github/workflows/signing.yml diff --git a/.github/workflows/signing.yml b/.github/workflows/signing.yml new file mode 100644 index 0000000..c286634 --- /dev/null +++ b/.github/workflows/signing.yml @@ -0,0 +1,151 @@ +name: Build and Publish + +on: + workflow_dispatch: + +env: + BUILD_CONFIGURATION: Release + DOTNET_VERSION: '9.x' + +jobs: + build-sign-publish: + runs-on: windows-latest + environment: nuget-org-publish + permissions: + id-token: write + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Get version from tag + id: version + shell: pwsh + run: | + $version = "${{ github.ref_name }}" + $version = "99.99.99" + Write-Host "Version: $version" + echo "version=$version" >> $env:GITHUB_OUTPUT + + - name: Build + run: | + dotnet build Infragistics.QueryBuilder.Executor.csproj ` + -c ${{ env.BUILD_CONFIGURATION }} ` + /p:Version=${{ steps.version.outputs.version }} + + - name: Setup Code Signing Certificate + run: | + Write-Host "Setting up code signing certificate from GitHub secrets..." + + # Create certificate file from secret (base64 encoded) + $certBytes = [Convert]::FromBase64String("${{ secrets.SIGNING_CERTIFICATE_2023_2026 }}") + [System.IO.File]::WriteAllBytes("${{ runner.temp }}\certificate.pfx", $certBytes) + Write-Host "Certificate written to: $certPath" + shell: pwsh + + - name: Sign all DLL files + if: false # This step will never run + shell: pwsh + env: + CERT_PASS: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }} + TIMESTAMP_URL: ${{ vars.SIGNING_CERTIFICATE_TIMESTAMP_URL }} + run: | + $dllFolder = "${{ github.workspace }}\bin\${{ env.BUILD_CONFIGURATION }}\net9.0" + $certPath = "${{ runner.temp }}\certificate.pfx" + Write-Host "Signing DLLs in folder: $dllFolder" + + # Find the latest signtool.exe + Write-Host "##[section]Starting search for signtool.exe at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff')" + + $signtoolPath = $null + $searchPaths = @( + "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe", + "C:\Program Files (x86)\Windows Kits\10\bin\*\x86\signtool.exe", + "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\*\signtool.exe", + "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\signtool.exe" + ) + + foreach ($searchPath in $searchPaths) { + $foundPaths = Get-ChildItem -Path $searchPath -ErrorAction SilentlyContinue | Sort-Object -Property FullName -Descending + if ($foundPaths) { + $signtoolPath = $foundPaths[0].FullName + break + } + } + + if (-not $signtoolPath) { + Write-Error "signtool.exe not found in any of the well-known locations" + exit 1 + } + + Write-Host "##[section]Found signtool.exe at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff')" + Write-Host "Using signtool at: $signtoolPath" + + $dllFiles = Get-ChildItem -Path $dllFolder -Filter *.dll -Recurse + foreach ($dll in $dllFiles) { + Write-Host "Signing $($dll.FullName)..." + & $signtoolPath sign /f $certPath /p $env:CERT_PASS /tr $env:TIMESTAMP_URL /td sha256 /fd sha256 $dll.FullName + + if ($LASTEXITCODE -ne 0) { + Write-Error "Signing failed for $($dll.FullName)" + exit 1 + } + } + + - name: Pack NuGet package + shell: pwsh + run: | + $packageOutputDir = "${{ github.workspace }}\nupkg" + $packageVersion = "${{ steps.version.outputs.version }}" + + Write-Host "Packing project from existing build output..." + dotnet pack ./Infragistics.QueryBuilder.Executor.csproj ` + --no-build ` + --configuration ${{ env.BUILD_CONFIGURATION }} ` + -p:PackageVersion=$packageVersion ` + -o $packageOutputDir + + if ($LASTEXITCODE -ne 0) { + Write-Error "dotnet pack failed" + exit 1 + } + + - name: Sign NuGet package + shell: pwsh + env: + SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }} + SIGNING_CERTIFICATE_TIMESTAMP_URL: ${{ vars.SIGNING_CERTIFICATE_TIMESTAMP_URL }} + run: | + $certPath = "${{ runner.temp }}\certificate.pfx" + $nupkgPath = "${{ github.workspace }}\nupkg\*.nupkg" + + dotnet nuget sign $nupkgPath ` + --certificate-path $certPath ` + --certificate-password "$env:SIGNING_CERTIFICATE_PASSWORD" ` + --timestamper "$env:SIGNING_CERTIFICATE_TIMESTAMP_URL" ` + --overwrite + + + - name: NuGet login (OIDC Trusted Publishing) + uses: nuget/login@v1 + id: nuget-login + with: + user: ${{ secrets.NUGET_ORG_USER }} + + - name: Clean up certificate + if: always() + shell: pwsh + run: | + $certPath = "${{ runner.temp }}\certificate.pfx" + if (Test-Path $certPath) { + Remove-Item $certPath -Force + Write-Host "Certificate cleaned up" + }