11# This workflow will build, test, sign and pack the release branches for EPPlus.
2- # It will also generate and publish an SBOM
2+ # It will also generate and publish an SBOM per target framework.
33# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
44
55name : Build Release Branches
@@ -19,49 +19,27 @@ jobs:
1919 - name : Setup .NET
2020 uses : actions/setup-dotnet@v4
2121 with :
22- dotnet-version : ' 10.0.x'
23- - name : Restore dependencies
24- run : dotnet restore ./src/EPPlus.sln
22+ dotnet-version : ' 9.0.x'
2523
26- # --- SBOM ---
27- - name : Install CycloneDX
28- run : dotnet tool install --global CycloneDX
29- - name : Read version from csproj
30- id : read_version
24+ # --- Read version and TFMs from csproj ---
25+ - name : Read version and target frameworks from csproj
26+ id : read_csproj
3127 run : |
32- $version = ([xml](Get-Content ./src/EPPlus/EPPlus.csproj)).Project.PropertyGroup.Version | Where-Object { $_ } | Select-Object -First 1
33- $tfms = ([xml](Get-Content ./src/EPPlus/EPPlus.csproj)).Project.PropertyGroup.TargetFrameworks | Where-Object { $_ } | Select-Object -First 1
28+ $xml = [xml](Get-Content ./src/EPPlus/EPPlus.csproj)
29+ $version = $xml.Project.PropertyGroup.Version | Where-Object { $_ } | Select-Object -First 1
30+ $tfms = $xml.Project.PropertyGroup.TargetFrameworks | Where-Object { $_ } | Select-Object -First 1
3431 echo "VERSION=$version" >> $env:GITHUB_ENV
3532 echo "TFMS=$tfms" >> $env:GITHUB_ENV
3633 shell : pwsh
37- - name : Generate combined SBOM
38- run : dotnet CycloneDX ./src/EPPlus/EPPlus.csproj -o ./sbom -F Json -st Library -sv ${{ env.VERSION }} -fn epplus-${{ env.VERSION }}.sbom.json -imp ./src/EPPlus/sbom-metadata-template.xml --spec-version 1.6
39- - name : Generate per-TFM SBOMs
40- run : |
41- $tfms = "${{ env.TFMS }}" -split ";"
42- foreach ($tfm in $tfms) {
43- $tfm = $tfm.Trim()
44- if ([string]::IsNullOrEmpty($tfm)) { continue }
45- Write-Host "Generating SBOM for $tfm"
46- dotnet CycloneDX ./src/EPPlus/EPPlus.csproj -o ./sbom -F Json -st Library -sv ${{ env.VERSION }} -fn "epplus-${{ env.VERSION }}.$tfm.sbom.json" -imp ./src/EPPlus/sbom-metadata-template.xml --framework $tfm --spec-version 1.6
47- }
48- shell : pwsh
49- - name : Generate SHA-256 checksums for all SBOMs
50- run : |
51- Get-ChildItem -Path "./sbom" -Filter "*.sbom.json" | ForEach-Object {
52- $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash.ToLower()
53- "$hash $($_.Name)" | Out-File -FilePath "$($_.FullName).sha256" -Encoding utf8NoBOM
54- Write-Host "Checksum generated for $($_.Name): $hash"
55- }
56- shell : pwsh
57- # --- SBOM ---
5834
35+ - name : Restore dependencies
36+ run : dotnet restore ./src/EPPlus.sln
5937 - name : Build
6038 run : dotnet build ./src/EPPlus.sln --no-restore --configuration Release
6139 - name : Test
6240 run : dotnet test ./src/EPPlus.sln --no-build --verbosity normal --configuration Release
6341 - name : Install AzureSignTool
64- run : dotnet tool install --global AzureSignTool --version 6.0.0
42+ run : dotnet tool install --global AzureSignTool --version 6.0.0
6543 - name : Install NuGetKeyVaultSignTool
6644 run : dotnet tool install --global NuGetKeyVaultSignTool
6745
@@ -71,14 +49,17 @@ jobs:
7149 uses : Azure/login@v2
7250 with :
7351 creds : ' {"clientId":"${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }}","clientSecret":"${{ secrets.EPPLUS_CODE_SIGNING_SECRET }}","subscriptionId":"${{ secrets.EPPLUS_CODE_SIGNING_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }}"}'
52+
53+ # --- Sign DLLs ---
7454 - name : Sign EPPlus.dll with AzureSignTool
7555 run : |
7656 $tfms = "${{ env.TFMS }}" -split ";"
7757 foreach ($tfm in $tfms) {
7858 $tfm = $tfm.Trim()
7959 if ([string]::IsNullOrEmpty($tfm)) { continue }
80- Write-Host "Signing EPPlus.dll for $tfm"
81- azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL}} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 ".\src\EPPlus\bin\Release\$tfm\EPPlus.dll"
60+ $dll = ".\src\EPPlus\bin\Release\$tfm\EPPlus.dll"
61+ Write-Host "Signing $dll"
62+ azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL }} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 "$dll"
8263 }
8364 shell : pwsh
8465 - name : Sign EPPlus.Interfaces.dll with AzureSignTool
8768 foreach ($tfm in $tfms) {
8869 $tfm = $tfm.Trim()
8970 if ([string]::IsNullOrEmpty($tfm)) { continue }
90- Write-Host "Signing EPPlus.Interfaces.dll for $tfm"
91- azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL}} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 ".\src\EPPlus.Interfaces\bin\Release\$tfm\EPPlus.Interfaces.dll"
71+ $dll = ".\src\EPPlus.Interfaces\bin\Release\$tfm\EPPlus.Interfaces.dll"
72+ Write-Host "Signing $dll"
73+ azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL }} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 "$dll"
9274 }
9375 shell : pwsh
9476 - name : Sign EPPlus.System.Drawing.dll with AzureSignTool
@@ -97,21 +79,47 @@ jobs:
9779 foreach ($tfm in $tfms) {
9880 $tfm = $tfm.Trim()
9981 if ([string]::IsNullOrEmpty($tfm)) { continue }
100- Write-Host "Signing EPPlus.System.Drawing.dll for $tfm"
101- azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL}} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 ".\src\EPPlus.System.Drawing\bin\Release\$tfm\EPPlus.System.Drawing.dll"
82+ $dll = ".\src\EPPlus.System.Drawing\bin\Release\$tfm\EPPlus.System.Drawing.dll"
83+ Write-Host "Signing $dll"
84+ azuresigntool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL }} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -tr http://timestamp.globalsign.com/tsa/advanced -td sha256 "$dll"
10285 }
10386 shell : pwsh
87+ # --- Sign DLLs ---
88+
10489 - name : Pack NuGet package
10590 run : dotnet pack ./src/EPPlus.sln --configuration Release --output ./output
10691 - name : Sign NuGet package
10792 run : |
108- NuGetKeyVaultSignTool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL}} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -tr http://timestamp.globalsign.com/tsa/advanced -fd sha256 -td sha256 -own EPPlusSoftware ".\output\*.nupkg"
93+ NuGetKeyVaultSignTool.exe sign -kvu ${{ secrets.EPPLUS_CODE_SIGNING_KEY_VAULT_URL }} -kvc ${{ secrets.EPPLUS_CODE_SIGNING_CERTIFICATE_NAME }} -kvi ${{ secrets.EPPLUS_CODE_SIGNING_APPLICATION_ID }} -kvs ${{ secrets.EPPLUS_CODE_SIGNING_SECRET }} -kvt ${{ secrets.EPPLUS_CODE_SIGNING_TENENT_ID }} -tr http://timestamp.globalsign.com/tsa/advanced -fd sha256 -td sha256 -own EPPlusSoftware ".\output\*.nupkg"
10994 - name : Upload NuGet package as artifact
11095 uses : actions/upload-artifact@v4
11196 with :
112- name : signed-nuget-package
113- path : ./output/*.nupkg
114- # --- SBOM ---
97+ name : signed-nuget-package
98+ path : ./output/*.nupkg
99+
100+ # --- SBOM (after build to avoid CycloneDX overwriting project.assets.json) ---
101+ - name : Install CycloneDX
102+ run : dotnet tool install --global CycloneDX
103+ - name : Generate combined SBOM
104+ run : dotnet CycloneDX ./src/EPPlus/EPPlus.csproj -o ./sbom -F Json -st Library -sv ${{ env.VERSION }} -fn epplus-${{ env.VERSION }}.sbom.json -imp ./src/EPPlus/sbom-metadata-template.xml --spec-version 1.7
105+ - name : Generate per-TFM SBOMs
106+ run : |
107+ $tfms = "${{ env.TFMS }}" -split ";"
108+ foreach ($tfm in $tfms) {
109+ $tfm = $tfm.Trim()
110+ if ([string]::IsNullOrEmpty($tfm)) { continue }
111+ Write-Host "Generating SBOM for $tfm"
112+ dotnet CycloneDX ./src/EPPlus/EPPlus.csproj -o ./sbom -F Json -st Library -sv ${{ env.VERSION }} -fn "epplus-${{ env.VERSION }}.$tfm.sbom.json" -imp ./src/EPPlus/sbom-metadata-template.xml --framework $tfm --spec-version 1.7
113+ }
114+ shell : pwsh
115+ - name : Generate SHA-256 checksums for all SBOMs
116+ run : |
117+ Get-ChildItem -Path "./sbom" -Filter "*.sbom.json" | ForEach-Object {
118+ $hash = (Get-FileHash -Path $_.FullName -Algorithm SHA256).Hash.ToLower()
119+ "$hash $($_.Name)" | Out-File -FilePath "$($_.FullName).sha256" -Encoding utf8NoBOM
120+ Write-Host "Checksum generated for $($_.Name): $hash"
121+ }
122+ shell : pwsh
115123 - name : Upload all SBOMs to Azure Blob Storage
116124 run : |
117125 Get-ChildItem -Path "./sbom" | ForEach-Object {
@@ -125,9 +133,9 @@ jobs:
125133 --overwrite
126134 }
127135 shell : pwsh
128- - name : Upload SBOM as artifact
136+ - name : Upload all SBOMs as artifact
129137 uses : actions/upload-artifact@v4
130138 with :
131- name : sbom
132- path : ./sbom/
139+ name : sbom
140+ path : ./sbom/
133141 # --- SBOM ---
0 commit comments