Skip to content

Publish Release To NuGet #39

Publish Release To NuGet

Publish Release To NuGet #39

name: Publish Release To NuGet
on:
release:
types: [ published ] # Trigger on published pre-releases and releases
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (e.g., v4.2.0)'
required: true
type: string
jobs:
variables:
name: Set Variables
runs-on: ubuntu-latest
env:
TAG: ${{ github.event.release.tag_name || inputs.tag }}
steps:
- name: Extract semantic version from tag
id: set_version
run: |
if [ -z "${TAG}" ]; then
echo "Error: No release tag available. Please provide a tag when manually triggering the workflow."
exit 1
fi
echo "Processing tag: ${TAG}"
# Remove the "v" prefix if it exists and extract the semantic version number
SEMANTIC_VERSION=$(echo "${TAG}" | grep -Po "(?<=^|[^0-9])([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?(-[a-zA-Z]+[0-9]*)?)")
SEMANTIC_VERSION=${SEMANTIC_VERSION#"v"}
if [ -z "${SEMANTIC_VERSION}" ]; then
echo "Error: Tag '${TAG}' does not start with a valid semantic version number (e.g., #.#.#; #.#.#.#; #.#.#.#-beta)"
exit 1
fi
echo "Extracted semantic version: ${SEMANTIC_VERSION}"
echo "Resolved git ref: ${TAG}"
echo "tag=${TAG}" >> $GITHUB_OUTPUT
echo "semantic_version=${SEMANTIC_VERSION}" >> $GITHUB_OUTPUT
outputs:
tag: ${{ steps.set_version.outputs.tag }}
semanticVersion: ${{ steps.set_version.outputs.semantic_version }}
buildFrameworkVersions:
name: Build Framework versions
needs: [ variables ]
runs-on: windows-2022
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ needs.variables.outputs.tag }}
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
- name: Setup NuGet
uses: nuget/setup-nuget@v2
- name: Download and Extract .NET Framework Reference Assemblies
run: |
# Create temp directory
New-Item -ItemType Directory -Path "temp_ref_assemblies" -Force
# Download .NET 4.0 Reference Assemblies
echo "Downloading .NET 4.0 Reference Assemblies..."
Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.NETFramework.ReferenceAssemblies.net40/1.0.3" -OutFile "temp_ref_assemblies/net40_ref.zip"
# Download .NET 4.5 Reference Assemblies
echo "Downloading .NET 4.5 Reference Assemblies..."
Invoke-WebRequest -Uri "https://www.nuget.org/api/v2/package/Microsoft.NETFramework.ReferenceAssemblies.net45/1.0.3" -OutFile "temp_ref_assemblies/net45_ref.zip"
# Extract .NET 4.0 Reference Assemblies
echo "Extracting .NET 4.0 Reference Assemblies..."
Expand-Archive -Path "temp_ref_assemblies/net40_ref.zip" -DestinationPath "temp_ref_assemblies/net40" -Force
if (Test-Path "temp_ref_assemblies/net40/build/.NETFramework/v4.0") {
echo "✓ .NET 4.0 Reference Assemblies extracted to workspace"
}
# Extract .NET 4.5 Reference Assemblies
echo "Extracting .NET 4.5 Reference Assemblies..."
Expand-Archive -Path "temp_ref_assemblies/net45_ref.zip" -DestinationPath "temp_ref_assemblies/net45" -Force
if (Test-Path "temp_ref_assemblies/net45/build/.NETFramework/v4.5") {
echo "✓ .NET 4.5 Reference Assemblies extracted to workspace"
}
- name: Restore NuGet packages
run: nuget restore ./OptimizelySDK.NETFramework.sln
- name: Build and strongly name assemblies
run: |
# Build with workspace-relative reference assembly paths
$Net40RefPath = "$(pwd)\temp_ref_assemblies\net40\build\.NETFramework\v4.0"
$Net45RefPath = "$(pwd)\temp_ref_assemblies\net45\build\.NETFramework\v4.5"
echo "Using .NET 4.0 Reference Assemblies from: $Net40RefPath"
echo "Using .NET 4.5 Reference Assemblies from: $Net45RefPath"
msbuild /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=$(pwd)/keypair.snk /p:Configuration=Release /p:FrameworkPathOverride="$Net45RefPath" ./OptimizelySDK.NETFramework.sln
- name: Cleanup reference assemblies
run: Remove-Item -Path "temp_ref_assemblies" -Recurse -Force
- name: Upload Framework artifacts
uses: actions/upload-artifact@v4
with:
name: unsigned-dlls-framework
if-no-files-found: error
path: ./**/bin/Release/**/Optimizely*.dll
buildStandard16:
name: Build Standard 1.6 version
needs: [ variables ]
runs-on: windows-2022
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ needs.variables.outputs.tag }}
- name: Setup .NET
uses: actions/setup-dotnet@v4
- name: Restore dependencies
run: dotnet restore OptimizelySDK.NetStandard16/OptimizelySDK.NetStandard16.csproj
- name: Build and strongly name assemblies
run: dotnet build OptimizelySDK.NetStandard16/OptimizelySDK.NetStandard16.csproj /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=$(pwd)/keypair.snk -c Release
- name: Upload Standard 1.6 artifact
uses: actions/upload-artifact@v4
with:
name: unsigned-dlls-netstandard16
if-no-files-found: error
path: ./**/bin/Release/**/Optimizely*.dll
buildStandard20:
name: Build Standard 2.0 version
needs: [ variables ]
runs-on: windows-2022
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ needs.variables.outputs.tag }}
- name: Setup .NET
uses: actions/setup-dotnet@v4
- name: Restore dependencies
run: dotnet restore OptimizelySDK.NetStandard20/OptimizelySDK.NetStandard20.csproj
- name: Build and strongly name Standard 2.0 project
run: dotnet build OptimizelySDK.NetStandard20/OptimizelySDK.NetStandard20.csproj /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=$(pwd)/keypair.snk -c Release
- name: Upload Standard 2.0 artifacts
uses: actions/upload-artifact@v4
with:
name: unsigned-dlls-netstandard20
if-no-files-found: error
path: ./**/bin/Release/**/Optimizely*.dll
pack:
name: Pack NuGet package
needs: [ variables, buildFrameworkVersions, buildStandard16, buildStandard20 ]
runs-on: ubuntu-latest
env:
VERSION: ${{ needs.variables.outputs.semanticVersion }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ needs.variables.outputs.tag }}
- name: Install mono
run: |
sudo apt update
sudo apt install -y mono-devel
- name: Setup NuGet
uses: nuget/setup-nuget@v2
- name: Download Framework DLLs
uses: actions/download-artifact@v4
with:
name: unsigned-dlls-framework
path: ./dlls
- name: Download NetStandard 1.6 DLLs
uses: actions/download-artifact@v4
with:
name: unsigned-dlls-netstandard16
path: ./dlls
- name: Download NetStandard 2.0 DLLs
uses: actions/download-artifact@v4
with:
name: unsigned-dlls-netstandard20
path: ./dlls
- name: Organize files
run: |
pushd ./dlls
# Move all dlls to the root directory
find . -type f -name "*.dll" -exec mv {} . \;
popd
# Create directories
mkdir -p nuget/lib/net35/ nuget/lib/net40/ nuget/lib/net45/ nuget/lib/netstandard1.6/ nuget/lib/netstandard2.0/
pushd ./nuget
# Move files to directories
mv ../dlls/OptimizelySDK.Net35.dll lib/net35/
mv ../dlls/OptimizelySDK.Net40.dll lib/net40/
mv ../dlls/OptimizelySDK.dll lib/net45/
mv ../dlls/OptimizelySDK.NetStandard16.dll lib/netstandard1.6/
mv ../dlls/OptimizelySDK.NetStandard20.dll lib/netstandard2.0/
popd
- name: Create nuspec
# Uses env.VERSION in OptimizelySDK.nuspec.template
run: |
chmod +x ./OptimizelySDK.nuspec.template
./OptimizelySDK.nuspec.template
- name: Pack NuGet package
run: |
pushd ./nuget
nuget pack OptimizelySDK.nuspec
popd
- name: Upload nupkg artifact
uses: actions/upload-artifact@v4
with:
name: nuget-package
if-no-files-found: error
path: ./nuget/Optimizely.SDK.${{ env.VERSION }}.nupkg
publish:
name: Publish package to NuGet after reviewing the artifact
needs: [ variables, pack ]
runs-on: ubuntu-latest
permissions:
id-token: write
# Review the `nuget-package` artifact ensuring the dlls are
# organized before approving.
environment: 'i-reviewed-nuget-package-artifact'
env:
VERSION: ${{ needs.variables.outputs.semanticVersion }}
steps:
- name: Download NuGet files
uses: actions/download-artifact@v4
with:
name: nuget-package
path: ./nuget
- name: Setup .NET
uses: actions/setup-dotnet@v4
- name: NuGet login
uses: NuGet/login@v1
id: nuget-login
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish NuGet package
run: |
dotnet nuget push ./nuget/Optimizely.SDK.${{ env.VERSION }}.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }}