Release #28
This file contains hidden or 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: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| platform-linux: | |
| description: Include Linux | |
| default: true | |
| type: boolean | |
| platform-android: | |
| description: Include Android | |
| default: true | |
| type: boolean | |
| platform-ios: | |
| description: Include iOS | |
| default: true | |
| type: boolean | |
| platform-macos: | |
| description: Include macOS | |
| default: true | |
| type: boolean | |
| sign: | |
| description: Code sign packages | |
| default: true | |
| type: boolean | |
| build-prerequisites-installer: | |
| description: Build prerequisites installer | |
| default: true | |
| type: boolean | |
| version-suffix: | |
| description: Prerelease suffix, no leading dash (e.g. "beta" -> 4.4.123-beta). Empty = stable. | |
| default: '' | |
| type: string | |
| deploy: | |
| description: Deploy to NuGet.org and create GitHub Release | |
| default: false | |
| type: boolean | |
| bump-version: | |
| description: After a stable deploy, commit the next Patch to the branch (open next dev version) | |
| default: true | |
| type: boolean | |
| upload-binlog: | |
| description: Capture and upload an MSBuild binlog (parallel/race diagnostics). Ignored on signed builds — a binlog records env vars/task params and would leak signing secrets. | |
| default: false | |
| type: boolean | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| # | |
| # Validate inputs and permissions | |
| # | |
| Validate: | |
| name: Validate | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check deploy requires signing | |
| if: ${{ inputs.deploy && !inputs.sign }} | |
| run: | | |
| echo "::error::Cannot deploy unsigned packages. Enable 'sign' to deploy." | |
| exit 1 | |
| - name: Check release permissions | |
| if: ${{ inputs.sign || inputs.deploy }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_PAT }} | |
| run: | | |
| ORG=$(echo "${{ github.repository }}" | cut -d/ -f1) | |
| TEAM="stride-release-managers" | |
| USER="${{ github.actor }}" | |
| STATUS=$(gh api "orgs/$ORG/teams/$TEAM/memberships/$USER" --silent 2>&1 && echo "ok" || echo "fail") | |
| if [ "$STATUS" = "fail" ]; then | |
| echo "::error::User $USER is not a member of $ORG/$TEAM. Sign/deploy requires stride-release-managers team membership." | |
| exit 1 | |
| fi | |
| # | |
| # Build and package | |
| # | |
| Package: | |
| name: Package | |
| needs: Validate | |
| runs-on: windows-2025-vs2026 | |
| environment: production | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| lfs: true | |
| fetch-depth: 0 # Full history + tags needed for tag-based versioning | |
| fetch-tags: true | |
| - uses: actions/setup-dotnet@v4 | |
| with: | |
| # 6.0.x required by deps/Gettext.Net/GNU.Gettext.Msgfmt.exe (see #3113) | |
| dotnet-version: | | |
| 6.0.x | |
| 10.0.x | |
| - name: Install Apple Workloads | |
| # VS provisions the android workload but not ios/macos. | |
| if: ${{ inputs.platform-ios || inputs.platform-macos }} | |
| uses: ./.github/actions/stride-workload | |
| with: | |
| workloads: ${{ inputs.platform-ios && inputs.platform-macos && 'ios macos' || inputs.platform-ios && 'ios' || 'macos' }} | |
| - name: Install Advanced Installer | |
| if: ${{ inputs.build-prerequisites-installer }} | |
| shell: pwsh | |
| run: | | |
| Invoke-WebRequest -Uri "https://www.advancedinstaller.com/downloads/22.0/advinst.msi" -OutFile advinst.msi | |
| msiexec /i advinst.msi /qn ADDLOCAL=ALL | Out-Null | |
| # Register license if provided | |
| if ("${{ secrets.ADVINST_LICENSE_KEY }}" -ne "") { | |
| & "${env:ProgramFiles(x86)}\Caphyon\Advanced Installer 22.0\bin\x86\AdvancedInstaller.com" /register "${{ secrets.ADVINST_LICENSE_KEY }}" | |
| } | |
| - name: Build Package | |
| run: | | |
| $platforms = "Windows" | |
| if ("${{ inputs.platform-linux }}" -eq "true") { $platforms += ";Linux" } | |
| if ("${{ inputs.platform-android }}" -eq "true") { $platforms += ";Android" } | |
| if ("${{ inputs.platform-ios }}" -eq "true") { $platforms += ";iOS" } | |
| if ("${{ inputs.platform-macos }}" -eq "true") { $platforms += ";macOS" } | |
| echo "Building for platforms: $platforms" | |
| # --no-restore: Stride.build's targets restore their own solutions (same as the | |
| # previous desktop msbuild invocation, which never passed /restore). | |
| dotnet build build\Stride.build ` | |
| -t:Package ` | |
| --no-restore ` | |
| ${{ inputs.upload-binlog && !inputs.sign && '-bl' || '' }} -m -nr:false ` | |
| -p:StridePlatforms=$($platforms.Replace(';','%3B')) ` | |
| -p:StrideGraphicsApiDependentBuildAll=true ` | |
| -p:StrideSign=${{ inputs.sign }} ` | |
| -p:StrideVersionSuffix=${{ inputs.version-suffix }} ` | |
| -p:StrideBuildPrerequisitesInstaller=${{ inputs.build-prerequisites-installer }} ` | |
| -p:StrideNativeBuildMode=Clang | |
| env: | |
| StrideDisableAssetCompilerExecServerProxy: true | |
| StrideSignTenantId: ${{ inputs.sign && secrets.STRIDE_SIGN_TENANT_ID || '' }} | |
| StrideSignClientId: ${{ inputs.sign && secrets.STRIDE_SIGN_CLIENT_ID || '' }} | |
| StrideSignClientSecret: ${{ inputs.sign && secrets.STRIDE_SIGN_CLIENT_SECRET || '' }} | |
| StrideSignKeyVaultCertificate: ${{ inputs.sign && secrets.STRIDE_SIGN_KEYVAULT_CERTIFICATE || '' }} | |
| StrideSignKeyVaultName: ${{ inputs.sign && secrets.STRIDE_SIGN_KEYVAULT_NAME || '' }} | |
| - name: Detect version | |
| id: version | |
| shell: pwsh | |
| run: | | |
| $pkg = Get-ChildItem -Path bin/packages -Filter "Stride.Core.*.nupkg" | Select-Object -First 1 | |
| if (-not $pkg) { | |
| echo "::error::No Stride.Core package found" | |
| exit 1 | |
| } | |
| $version = $pkg.Name -replace 'Stride\.Core\.(.*?)\.nupkg','$1' | |
| # Guard against a malformed SharedAssemblyInfo.cs slipping a weird version into the package name. | |
| if ($version -notmatch '^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$') { | |
| echo "::error::Detected package version '$version' is not a valid version - check SharedAssemblyInfo.cs" | |
| exit 1 | |
| } | |
| echo "version=$version" >> $env:GITHUB_OUTPUT | |
| echo "::notice::Package version: $version" | |
| # Forget-to-bump guard: the version is the committed value in SharedAssemblyInfo.cs, bumped per release. If it | |
| # wasn't bumped, its releases/<version> tag already exists on the previously-released commit, so fail the | |
| # deploy. Re-running the release on the exact tagged commit (idempotent) is allowed (tag points at HEAD). | |
| - name: Guard against re-publishing an existing version | |
| if: ${{ inputs.deploy }} | |
| run: | | |
| TAG="releases/${{ steps.version.outputs.version }}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1 && [ -z "$(git tag --points-at HEAD --list "$TAG")" ]; then | |
| echo "::error::Version ${{ steps.version.outputs.version }} is already released (tag $TAG on another commit). Bump Patch/NuGetVersionSuffix in SharedAssemblyInfo.cs." | |
| exit 1 | |
| fi | |
| - name: Upload NuGet packages | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: packages | |
| path: bin/packages/*.nupkg | |
| if-no-files-found: error | |
| - name: Upload build log | |
| uses: actions/upload-artifact@v4 | |
| if: ${{ always() && inputs.upload-binlog && !inputs.sign }} | |
| with: | |
| name: build-log | |
| path: msbuild.binlog | |
| if-no-files-found: ignore | |
| # | |
| # Surface the package version in the run UI. A job can't reference its own outputs in its | |
| # name, so this lightweight job shows Package's version even when Deploy is skipped. | |
| # | |
| Version: | |
| name: Packaged ${{ needs.Package.outputs.version }} | |
| needs: Package | |
| if: ${{ always() && needs.Package.result == 'success' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - run: echo "::notice title=Packaged::${{ needs.Package.outputs.version }}" | |
| # | |
| # Deploy to NuGet.org and create GitHub Release | |
| # | |
| Deploy: | |
| name: Deploy ${{ needs.Package.outputs.version }} | |
| if: ${{ inputs.deploy && inputs.sign }} | |
| needs: Package | |
| permissions: | |
| contents: write | |
| uses: ./.github/workflows/release-deploy.yml | |
| with: | |
| run-id: ${{ github.run_id }} | |
| bump-version: ${{ inputs.bump-version }} | |
| secrets: inherit |