#3416·stride

NuGet upload loop can report success after an earlier package push fails

Author: yohimikCreated Sep 9, 2026Updated Sep 10, 2026

Release Type: GitHub release automation

Version: master at 1714e21ce4f8706e38100896a3f017ac29ba5026

Platform: PowerShell release step; isolated reproduction with PowerShell 7.6.5 on macOS, using a stub publisher and no registry access.

Describe the bug

In release-deploy.yml, Push NuGet packages, each loop invokes dotnet nuget push without checking its exit status. With the default $PSNativeCommandUseErrorActionPreference = $false, an earlier failed upload can be overwritten by a later successful native command. The step then exits zero and the subsequent tag/release steps can proceed.

To reproduce

  1. Extract the existing Push NuGet packages run block into a temporary .ps1 file.
  2. Create empty fixture files under bin/packages: Stride.Core.4.4.0-beta6.nupkg, Stride.Engine.4.4.0-beta6.nupkg, and Stride.GameStudio.4.4.0-beta6.nupkg.
  3. Put a native executable named dotnet first on PATH that returns exit 1 for the Core filename and exit 0 for the others. Do not use a real publisher.
  4. Execute with GitHub's documented PowerShell wrapper: prepend $ErrorActionPreference = 'stop', append if ((Test-Path -LiteralPath variable:\LASTEXITCODE)) { exit $LASTEXITCODE }.

Observed: the simulated Core upload failed; Engine and GameStudio continued; the script exited 0. Adding an immediate $LASTEXITCODE check after each push made the same fixture exit 1.

Expected behavior

An upload failure must make the step fail, even if independent uploads continue. Check every push and either stop immediately or collect failures and exit nonzero at the end. GameStudio should not publish when required providers failed. --skip-duplicate is useful recovery behavior and should remain where intended.

Additional context

This is an isolated reproduction of the checked-in loop, not a claim that an official release currently has missing packages. GitHub's shell documentation explains the last-exit-code wrapper.

Disclosure: I maintain dispat and found this while reviewing release failure propagation. The fix belongs in the existing workflow.