name: Publish NuGet package on: workflow_dispatch: inputs: dry-run: description: 'Dry run' required: true type: boolean default: true version: description: 'Package version' default: "latest" required: true schedule: - cron: '21 3 * * 1' # 3:21 AM UTC every Monday jobs: preflight: name: Preflight runs-on: ubuntu-latest outputs: dry-run: ${{ steps.get-dry-run.outputs.dry-run }} package-version: ${{ steps.info.outputs.package-version }} steps: - name: Get dry run id: get-dry-run shell: pwsh run: | Set-PSDebug -Trace 1 $IsDryRun = '${{ github.event.inputs.dry-run }}' -Eq 'true' -Or '${{ github.event_name }}' -Eq 'schedule' if ($IsDryRun) { echo "dry-run=true" >> $Env:GITHUB_OUTPUT } else { echo "dry-run=false" >> $Env:GITHUB_OUTPUT } - name: Package information id: info shell: pwsh run: | $PackageVersion = '${{ inputs.version }}' if ([string]::IsNullOrEmpty($PackageVersion) -or $PackageVersion -eq 'latest') { $PackageVersion = (Get-Date -Format "yyyy.MM.dd") + ".0" } if ($PackageVersion -NotMatch '^\d+\.\d+\.\d+\.\d+$') { throw "invalid version format: $PackageVersion, expected: 1.2.3.4" } echo "package-version=$PackageVersion" >> $Env:GITHUB_OUTPUT echo "::notice::Version: $PackageVersion" build-native: uses: ./.github/workflows/build-native.yml build-managed: name: Managed build runs-on: windows-2022 needs: [ preflight, build-native ] steps: - name: Check out ${{ github.repository }} uses: actions/checkout@v6 - name: Prepare dependencies shell: pwsh run: | New-Item -ItemType Directory -Path "dependencies/runtimes" | Out-Null - name: Download native components uses: actions/download-artifact@v8 with: path: dependencies/runtimes - name: Rename dependencies shell: pwsh run: | Set-PSDebug -Trace 1 Set-Location "dependencies/runtimes" $(Get-Item ".\sspi-*-release") | ForEach-Object { Rename-Item $_ $_.Name.Replace("-release", "") } $(Get-Item ".\sspi-*") | ForEach-Object { Rename-Item $_ $_.Name.Replace("sspi-", "") } Get-ChildItem * -Recurse - name: Set package version shell: pwsh run: | $PackageVersion = '${{ needs.preflight.outputs.package-version }}' $csprojPath = "ffi\dotnet\Devolutions.Sspi\Devolutions.Sspi.csproj" $csprojContent = Get-Content $csprojPath -Raw $csprojContent = $csprojContent -Replace '().*?()', "$PackageVersion" Set-Content -Path $csprojPath -Value $csprojContent -Encoding UTF8 - name: Build sspi (managed) shell: pwsh run: | dotnet build .\ffi\dotnet\Devolutions.Sspi\Devolutions.Sspi.csproj -o package - name: Upload managed components uses: actions/upload-artifact@v7 with: name: sspi-nupkg path: package/*.nupkg publish: name: Publish NuGet package runs-on: ubuntu-latest environment: nuget-publish if: needs.preflight.outputs.dry-run == 'false' needs: - preflight - build-managed permissions: id-token: write steps: - name: Download NuGet package artifact uses: actions/download-artifact@v8 with: name: sspi-nupkg path: package - name: NuGet login (OIDC) uses: NuGet/login@v1 id: nuget-login with: user: ${{ secrets.NUGET_BOT_USERNAME }} - name: Publish to nuget.org shell: pwsh run: | Set-PSDebug -Trace 1 $Files = Get-ChildItem -Recurse package/*.nupkg foreach ($File in $Files) { $PushCmd = @( 'dotnet', 'nuget', 'push', "$File", '--api-key', '${{ steps.nuget-login.outputs.NUGET_API_KEY }}', '--source', 'https://api.nuget.org/v3/index.json', '--skip-duplicate' ) Write-Host "Publishing $($File.Name)..." $PushCmd = $PushCmd -Join ' ' Invoke-Expression $PushCmd } package-symbols: name: Package debug symbols runs-on: ubuntu-latest needs: [ preflight, build-native ] steps: - name: Download all symbol artifacts uses: actions/download-artifact@v8 with: path: artifacts pattern: sspi-*-release-symbols - name: Package symbols into zip shell: pwsh run: | Set-PSDebug -Trace 1 $PackageVersion = '${{ needs.preflight.outputs.package-version }}' $SymbolsDir = "symbols" New-Item -ItemType Directory -Path $SymbolsDir -Force | Out-Null # Organize symbols by RID $SymbolArtifacts = Get-ChildItem -Directory "artifacts" -Filter "sspi-*-release-symbols" foreach ($Artifact in $SymbolArtifacts) { # Extract RID from artifact name (e.g., sspi-win-x64-release-symbols -> win-x64) $Rid = $Artifact.Name -Replace '^sspi-(.+)-release-symbols$', '$1' $DestDir = Join-Path $SymbolsDir $Rid New-Item -ItemType Directory -Path $DestDir -Force | Out-Null # Copy all contents from the artifact Get-ChildItem -Path $Artifact.FullName -Recurse | ForEach-Object { if (-not $_.PSIsContainer) { $RelativePath = $_.FullName.Substring($Artifact.FullName.Length + 1) $DestPath = Join-Path $DestDir $RelativePath $DestParent = Split-Path $DestPath -Parent if (-not (Test-Path $DestParent)) { New-Item -ItemType Directory -Path $DestParent -Force | Out-Null } Copy-Item $_.FullName $DestPath } } } Write-Host "Symbol directory structure:" Get-ChildItem -Recurse $SymbolsDir | ForEach-Object { Write-Host $_.FullName } # Create the zip file $ZipName = "Devolutions.Sspi.$PackageVersion.symbols.zip" Compress-Archive -Path "$SymbolsDir/*" -DestinationPath $ZipName -Force Write-Host "Created symbols archive: $ZipName" - name: Upload symbols zip uses: actions/upload-artifact@v7 with: name: sspi-symbols-zip path: Devolutions.Sspi.*.symbols.zip create-release: name: Create GitHub Release runs-on: ubuntu-latest if: needs.preflight.outputs.dry-run == 'false' needs: - preflight - build-managed - package-symbols - publish permissions: contents: write steps: - name: Download NuGet package uses: actions/download-artifact@v8 with: name: sspi-nupkg path: release-assets - name: Download symbols zip uses: actions/download-artifact@v8 with: name: sspi-symbols-zip path: release-assets - name: Create GitHub Release env: GH_TOKEN: ${{ github.token }} GH_REPO: ${{ github.repository }} shell: pwsh run: | Set-PSDebug -Trace 1 $PackageVersion = '${{ needs.preflight.outputs.package-version }}' $TagName = "v$PackageVersion" $ReleaseName = "Devolutions.Sspi $PackageVersion" # Get the list of assets to upload $Assets = Get-ChildItem -Path "release-assets" -File Write-Host "Release assets:" $Assets | ForEach-Object { Write-Host " - $($_.Name)" } # Build the release notes $ReleaseNotes = @" ## Devolutions.Sspi $PackageVersion ### NuGet Package - [Devolutions.Sspi on NuGet.org](https://www.nuget.org/packages/Devolutions.Sspi/$PackageVersion) ### Included Platforms - Windows (x64, arm64) - macOS (x64, arm64, universal) - Linux (x64, arm64) - iOS device (arm64) - iOS Simulator (arm64) - Android (x86, x64, arm, arm64) ### Debug Symbols The `Devolutions.Sspi.$PackageVersion.symbols.zip` archive contains debug symbols for all platforms: - Windows: `.pdb` files - macOS/iOS: `.dSYM` bundles - Linux/Android: `.debug` or `.dwp` files "@ # Create the release with assets $AssetArgs = @() foreach ($Asset in $Assets) { $AssetArgs += $Asset.FullName } gh release create $TagName ` --title $ReleaseName ` --notes $ReleaseNotes ` --target ${{ github.sha }} ` @AssetArgs Write-Host "Created release: $ReleaseName with tag $TagName" notify: name: Notify failure runs-on: ubuntu-latest if: ${{ always() && contains(needs.*.result, 'failure') && github.event_name == 'schedule' }} needs: - preflight - build-native - build-managed - package-symbols env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_ARCHITECTURE }} SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK steps: - name: Send slack notification id: slack uses: slackapi/slack-github-action@v1.26.0 with: payload: | { "blocks": [ { "type": "section", "text": { "type": "mrkdwn", "text": "*${{ github.repository }}* :fire::fire::fire::fire::fire: \n The scheduled build for *${{ github.repository }}* is <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|broken>" } } ] }