Publish Release To NuGet #26
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish Release To NuGet | |
on: | |
release: | |
types: [ published ] # Trigger on published pre-releases and releases | |
workflow_dispatch: | |
inputs: | |
tag: | |
description: 'Tag name' | |
required: true | |
default: 'v4.1.0' | |
jobs: | |
variables: | |
name: Set Variables | |
runs-on: ubuntu-latest | |
env: | |
TAG: ${{ github.event.release.tag_name || github.event.inputs.tag }} | |
steps: | |
- name: Extract semantic version from tag | |
id: set_version | |
run: | | |
# 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 "semantic_version=${SEMANTIC_VERSION}" >> $GITHUB_OUTPUT | |
outputs: | |
tag: ${{ env.TAG }} | |
semanticVersion: ${{ steps.set_version.outputs.semantic_version }} | |
buildFrameworkVersions: | |
name: Build .NET Framework versions | |
needs: [ variables ] | |
runs-on: windows-2019 # required version for Framework 4.0 | |
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: Restore NuGet packages | |
run: nuget restore ./OptimizelySDK.NETFramework.sln | |
- name: Build and strongly name assemblies | |
run: msbuild /p:SignAssembly=true /p:AssemblyOriginatorKeyFile=$(pwd)/keypair.snk /p:Configuration=Release ./OptimizelySDK.NETFramework.sln | |
- 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 .NET 1.6 version | |
needs: [ variables ] | |
runs-on: windows-latest | |
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-standard16 | |
if-no-files-found: error | |
path: ./**/bin/Release/**/Optimizely*.dll | |
buildStandard20: | |
name: Build .NET 2.0 version | |
needs: [ variables ] | |
runs-on: windows-latest | |
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: Build and strongly name assemblies | |
uses: actions/upload-artifact@v4 | |
with: | |
name: unsigned-dlls-standard20 | |
if-no-files-found: error | |
path: ./**/bin/Release/**/Optimizely*.dll | |
combineArtifacts: | |
name: Combine artifacts | |
needs: [ variables, buildFrameworkVersions, buildStandard16, buildStandard20 ] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download Framework artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: unsigned-dlls-framework | |
path: ./unsigned-dlls-framework | |
- name: Download Standard 1.6 artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: unsigned-dlls-standard16 | |
path: ./unsigned-dlls-standard16 | |
- name: Download Standard 2.0 artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: unsigned-dlls-standard20 | |
path: ./unsigned-dlls-standard20 | |
- name: List all downloaded artifacts | |
run: ls -R ./ | |
- name: Combine artifacts | |
run: | | |
mkdir -p ./unsigned-dlls | |
find ./unsigned-dlls-framework -type f -name 'Optimizely*.dll' ! -path '*/OptimizelySDK.Tests/*' -exec mv {} ./unsigned-dlls/ \; | |
find ./unsigned-dlls-standard16 -type f -name 'Optimizely*.dll' -exec mv {} ./unsigned-dlls/ \; | |
find ./unsigned-dlls-standard20 -type f -name 'Optimizely*.dll' -exec mv {} ./unsigned-dlls/ \; | |
- name: Upload combined artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: unsigned-dlls | |
if-no-files-found: error | |
path: ./unsigned-dlls | |
sign: | |
name: Send DLLs for signing | |
needs: [ combineArtifacts ] | |
runs-on: ubuntu-latest | |
env: | |
# TODO: Replace actual values | |
SIGNING_SERVER_PRIVATE_KEY: ${{ secrets.SIGNING_SERVER_PRIVATE_KEY }} | |
SIGNING_SERVER_HOST: ${{ secrets.SIGNING_SERVER_HOST }} | |
SIGNING_SERVER_UPLOAD_PATH: /path/to/UPLOAD/directory | |
SIGNING_SERVER_DOWNLOAD_PATH: /path/to/DOWNLOAD/directory | |
steps: | |
# TODO: Remove this when we're ready to automate | |
- name: Temporarily halt progress | |
run: exit 1 | |
- name: Download the unsigned files | |
uses: actions/download-artifact@v4 | |
with: | |
name: unsigned-dlls | |
path: ./unsigned-dlls | |
- name: Setup SSH | |
uses: shimataro/ssh-key-action@v2 | |
with: | |
key: $SIGNING_SERVER_PRIVATE_KEY | |
- name: Send files to signing server | |
run: scp -r ./unsigned-dlls $SIGNING_SERVER_HOST:$SIGNING_SERVER_UPLOAD_PATH | |
- name: Wait for artifact to be published | |
run: | | |
for i in {1..60}; do | |
# Replace with actual path | |
if ssh $SIGNING_SERVER_HOST "ls $SIGNING_SERVER_DOWNLOAD_PATH"; then | |
exit 0 | |
fi | |
sleep 10 | |
done | |
exit 1 | |
- name: Download signed files | |
run: | | |
mkdir ./signed-dlls | |
scp -r $SIGNING_SERVER_HOST:$SIGNING_SERVER_DOWNLOAD_PATH ./signed-dlls | |
- name: Delete signed files from server | |
run: ssh $SIGNING_SERVER_HOST "rm -rf $SIGNING_SERVER_DOWNLOAD_PATH/*" | |
- name: Upload signed files | |
uses: actions/upload-artifact@v4 | |
with: | |
name: signed-dlls | |
if-no-files-found: error | |
path: ./signed-dlls | |
pack: | |
name: Pack NuGet package | |
needs: [ sign ] | |
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: Download NuGet files | |
uses: actions/download-artifact@v4 | |
with: | |
name: signed-dlls | |
path: ./signed-dlls | |
- name: Organize files | |
run: | | |
pushd ./signed-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 ../signed-dlls/OptimizelySDK.Net35.dll lib/net35/ | |
mv ../signed-dlls/OptimizelySDK.Net40.dll lib/net40/ | |
mv ../signed-dlls/OptimizelySDK.dll lib/net45/ | |
mv ../signed-dlls/OptimizelySDK.NetStandard16.dll lib/netstandard1.6/ | |
mv ../signed-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: [ pack ] | |
runs-on: ubuntu-latest | |
# Review the `nuget-package` artifact ensuring the dlls are | |
# organized and signed 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: Publish NuGet package | |
run: | | |
dotnet nuget push ./nuget/Optimizely.SDK.${{ env.VERSION }}.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} |