Skip to content

Commit 206dabf

Browse files
Add build and publish workflow for NuGet package (#13)
This workflow builds a .NET project, signs the DLLs and NuGet package, and publishes the package to NuGet.org.
1 parent dafda3b commit 206dabf

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
name: Build and Publish
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
env:
9+
BUILD_CONFIGURATION: Release
10+
DOTNET_VERSION: '9.x'
11+
12+
jobs:
13+
build-sign-publish:
14+
runs-on: windows-latest
15+
environment: nuget-org-publish
16+
permissions:
17+
id-token: write
18+
contents: read
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Setup .NET
27+
uses: actions/setup-dotnet@v4
28+
with:
29+
dotnet-version: ${{ env.DOTNET_VERSION }}
30+
31+
- name: Get version from tag
32+
id: version
33+
shell: pwsh
34+
run: |
35+
$version = "${{ github.ref_name }}"
36+
Write-Host "Version: $version"
37+
echo "version=$version" >> $env:GITHUB_OUTPUT
38+
39+
- name: Build
40+
run: |
41+
dotnet build Infragistics.QueryBuilder.Executor.csproj `
42+
-c ${{ env.BUILD_CONFIGURATION }} `
43+
/p:Version=${{ steps.version.outputs.version }}
44+
45+
- name: Debug - List build output contents
46+
shell: pwsh
47+
run: |
48+
$outputDir = "${{ github.workspace }}\bin\${{ env.BUILD_CONFIGURATION }}\net9.0"
49+
Write-Host "Listing contents of: $outputDir"
50+
if (-Not (Test-Path $outputDir)) {
51+
Write-Error "Output folder not found: $outputDir"
52+
exit 1
53+
}
54+
Get-ChildItem $outputDir -Recurse | ForEach-Object {
55+
Write-Host $_.FullName
56+
}
57+
58+
- name: Decode signing certificate
59+
shell: pwsh
60+
run: |
61+
$certBytes = [Convert]::FromBase64String("${{ secrets.SIGNING_CERTIFICATE_BASE64 }}")
62+
$certPath = "${{ runner.temp }}\certificate.pfx"
63+
[IO.File]::WriteAllBytes($certPath, $certBytes)
64+
Write-Host "Certificate written to: $certPath"
65+
66+
- name: Sign all DLL files
67+
shell: pwsh
68+
env:
69+
CERT_PASS: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
70+
TIMESTAMP_URL: ${{ vars.SIGNING_CERTIFICATE_TIMESTAMP_URL }}
71+
run: |
72+
$dllFolder = "${{ github.workspace }}\bin\${{ env.BUILD_CONFIGURATION }}\net9.0"
73+
$certPath = "${{ runner.temp }}\certificate.pfx"
74+
Write-Host "Signing DLLs in folder: $dllFolder"
75+
76+
# Find the latest signtool.exe
77+
Write-Host "##[section]Starting search for signtool.exe at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff')"
78+
79+
$signtoolPath = $null
80+
$searchPaths = @(
81+
"C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe",
82+
"C:\Program Files (x86)\Windows Kits\10\bin\*\x86\signtool.exe",
83+
"C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\*\signtool.exe",
84+
"C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\signtool.exe"
85+
)
86+
87+
foreach ($searchPath in $searchPaths) {
88+
$foundPaths = Get-ChildItem -Path $searchPath -ErrorAction SilentlyContinue | Sort-Object -Property FullName -Descending
89+
if ($foundPaths) {
90+
$signtoolPath = $foundPaths[0].FullName
91+
break
92+
}
93+
}
94+
95+
if (-not $signtoolPath) {
96+
Write-Error "signtool.exe not found in any of the well-known locations"
97+
exit 1
98+
}
99+
100+
Write-Host "##[section]Found signtool.exe at $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff')"
101+
Write-Host "Using signtool at: $signtoolPath"
102+
103+
$dllFiles = Get-ChildItem -Path $dllFolder -Filter *.dll -Recurse
104+
foreach ($dll in $dllFiles) {
105+
Write-Host "Signing $($dll.FullName)..."
106+
& $signtoolPath sign /f $certPath /p $env:CERT_PASS /tr $env:TIMESTAMP_URL /td sha256 /fd sha256 $dll.FullName
107+
108+
if ($LASTEXITCODE -ne 0) {
109+
Write-Error "Signing failed for $($dll.FullName)"
110+
exit 1
111+
}
112+
}
113+
114+
- name: Pack NuGet package
115+
shell: pwsh
116+
run: |
117+
$packageOutputDir = "${{ github.workspace }}\nupkg"
118+
$packageVersion = "${{ steps.version.outputs.version }}"
119+
120+
Write-Host "Packing project from existing build output..."
121+
dotnet pack ./Infragistics.QueryBuilder.Executor.csproj `
122+
--no-build `
123+
--configuration ${{ env.BUILD_CONFIGURATION }} `
124+
-p:PackageVersion=$packageVersion `
125+
-o $packageOutputDir
126+
127+
if ($LASTEXITCODE -ne 0) {
128+
Write-Error "dotnet pack failed"
129+
exit 1
130+
}
131+
132+
- name: Sign NuGet package
133+
shell: pwsh
134+
env:
135+
CERT_PASS: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
136+
TIMESTAMP_URL: ${{ vars.SIGNING_CERTIFICATE_TIMESTAMP_URL }}
137+
run: |
138+
$certPath = "${{ runner.temp }}\certificate.pfx"
139+
$nupkgPath = "${{ github.workspace }}\nupkg\*.nupkg"
140+
141+
dotnet nuget sign $nupkgPath `
142+
--certificate-path $certPath `
143+
--certificate-password $env:CERT_PASS `
144+
--timestamper $env:TIMESTAMP_URL `
145+
--overwrite
146+
147+
- name: NuGet login (OIDC Trusted Publishing)
148+
uses: nuget/login@v1
149+
id: nuget-login
150+
with:
151+
user: ${{ secrets.NUGET_ORG_USER }}
152+
153+
- name: Publish to NuGet.org
154+
run: |
155+
dotnet nuget push "${{ github.workspace }}\nupkg\*.nupkg" `
156+
--api-key ${{ steps.nuget-login.outputs.nuget-api-key }} `
157+
--source https://api.nuget.org/v3/index.json
158+
159+
- name: Clean up certificate
160+
if: always()
161+
shell: pwsh
162+
run: |
163+
$certPath = "${{ runner.temp }}\certificate.pfx"
164+
if (Test-Path $certPath) {
165+
Remove-Item $certPath -Force
166+
Write-Host "Certificate cleaned up"
167+
}

0 commit comments

Comments
 (0)