Skip to content

Commit 9e9c474

Browse files
authored
Merge pull request #3115 from stride3d/feature/ci-gpu
Migrate CI/CD from TeamCity to GitHub Actions: release workflows & WARP GPU testing (D3D11)
2 parents df53363 + 74b1a55 commit 9e9c474

957 files changed

Lines changed: 2398 additions & 1195 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Release workflows require approval from release managers
2+
.github/workflows/release*.yml @stride3d/stride-release-managers

.github/workflows/main.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,23 @@ on:
1414
- '!**/.gitignore'
1515
- '!**/*.md'
1616
- '!crowdin.yml'
17+
pull_request:
18+
paths:
19+
- '.github/workflows/**'
20+
- 'build/**'
21+
- 'deps/**'
22+
- 'sources/**'
23+
- '!**/.all-contributorsrc'
24+
- '!**/.editorconfig'
25+
- '!**/.gitignore'
26+
- '!**/*.md'
27+
- '!crowdin.yml'
28+
types: [opened, synchronize, reopened, ready_for_review]
1729
workflow_dispatch:
1830

1931
concurrency:
20-
group: ${{ github.workflow }}-${{ github.ref }}
21-
cancel-in-progress: true
32+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
33+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
2234

2335
jobs:
2436
### Misc. ###
@@ -87,7 +99,7 @@ jobs:
8799
strategy:
88100
matrix:
89101
build-type: [Release]
90-
test-category: [Simple]
102+
test-category: [Simple, Game]
91103
uses: ./.github/workflows/test-windows.yml
92104
secrets: inherit
93105
with:
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
name: Release Launcher
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
sign:
7+
description: Code sign packages
8+
default: true
9+
type: boolean
10+
deploy:
11+
description: Deploy to NuGet.org
12+
default: false
13+
type: boolean
14+
15+
concurrency:
16+
group: release-launcher-${{ github.ref }}
17+
cancel-in-progress: false
18+
19+
jobs:
20+
#
21+
# Validate inputs and permissions
22+
#
23+
Validate:
24+
name: Validate
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Check deploy requires signing
28+
if: ${{ inputs.deploy && !inputs.sign }}
29+
run: |
30+
echo "::error::Cannot deploy unsigned packages. Enable 'sign' to deploy."
31+
exit 1
32+
33+
- name: Check release permissions
34+
if: ${{ inputs.sign || inputs.deploy }}
35+
env:
36+
GH_TOKEN: ${{ secrets.GH_PAT }}
37+
run: |
38+
ORG=$(echo "${{ github.repository }}" | cut -d/ -f1)
39+
TEAM="stride-release-managers"
40+
USER="${{ github.actor }}"
41+
STATUS=$(gh api "orgs/$ORG/teams/$TEAM/memberships/$USER" --silent 2>&1 && echo "ok" || echo "fail")
42+
if [ "$STATUS" = "fail" ]; then
43+
echo "::error::User $USER is not a member of $ORG/$TEAM. Sign/deploy requires stride-release-managers team membership."
44+
exit 1
45+
fi
46+
47+
#
48+
# Build, package and optionally deploy the launcher
49+
#
50+
Package:
51+
name: Package Launcher
52+
needs: Validate
53+
runs-on: windows-latest
54+
environment: production
55+
outputs:
56+
version: ${{ steps.version.outputs.version }}
57+
steps:
58+
- uses: actions/checkout@v4
59+
with:
60+
lfs: true
61+
fetch-depth: 0
62+
63+
- uses: actions/setup-dotnet@v4
64+
with:
65+
dotnet-version: |
66+
6.0.x
67+
10.0.x
68+
69+
- uses: microsoft/setup-msbuild@v2
70+
71+
- name: Install Advanced Installer
72+
shell: pwsh
73+
run: |
74+
Invoke-WebRequest -Uri "https://www.advancedinstaller.com/downloads/22.0/advinst.msi" -OutFile advinst.msi
75+
msiexec /i advinst.msi /qn ADDLOCAL=ALL | Out-Null
76+
if ("${{ secrets.ADVINST_LICENSE_KEY }}" -ne "") {
77+
& "${env:ProgramFiles(x86)}\Caphyon\Advanced Installer 22.0\bin\x86\AdvancedInstaller.com" /register "${{ secrets.ADVINST_LICENSE_KEY }}"
78+
}
79+
80+
- name: Build and package launcher
81+
shell: pwsh
82+
run: |
83+
msbuild build\Stride.build `
84+
/t:FullBuildLauncher `
85+
/bl /m /nr:false `
86+
/p:StrideSign=${{ inputs.sign }}
87+
env:
88+
StrideSignTenantId: ${{ secrets.STRIDE_SIGN_TENANT_ID }}
89+
StrideSignClientId: ${{ secrets.STRIDE_SIGN_CLIENT_ID }}
90+
StrideSignClientSecret: ${{ secrets.STRIDE_SIGN_CLIENT_SECRET }}
91+
StrideSignKeyVaultCertificate: ${{ secrets.STRIDE_SIGN_KEYVAULT_CERTIFICATE }}
92+
StrideSignKeyVaultName: ${{ secrets.STRIDE_SIGN_KEYVAULT_NAME }}
93+
94+
- name: Get version
95+
id: version
96+
shell: pwsh
97+
run: |
98+
$nupkg = Get-ChildItem -Path bin/launcher -Filter "*.nupkg" | Select-Object -First 1
99+
if ($nupkg -and $nupkg.BaseName -match '\.(\d+\.\d+\.\d+.*)$') {
100+
echo "version=$($Matches[1])" >> $env:GITHUB_OUTPUT
101+
}
102+
103+
- name: Upload launcher artifacts
104+
uses: actions/upload-artifact@v4
105+
with:
106+
name: launcher
107+
path: |
108+
bin/launcher/*.nupkg
109+
bin/launcher/*.exe
110+
retention-days: 30
111+
112+
Deploy:
113+
name: Deploy Launcher
114+
if: ${{ inputs.deploy && inputs.sign }}
115+
needs: Package
116+
runs-on: ubuntu-latest
117+
steps:
118+
- uses: actions/setup-dotnet@v4
119+
with:
120+
dotnet-version: 10.0.x
121+
122+
- name: Download launcher artifacts
123+
uses: actions/download-artifact@v4
124+
with:
125+
name: launcher
126+
path: bin/launcher
127+
128+
- name: Push to NuGet
129+
shell: pwsh
130+
run: |
131+
Get-ChildItem -Path bin/launcher -Filter "*.nupkg" | ForEach-Object {
132+
echo "Pushing $($_.Name)..."
133+
dotnet nuget push $_.FullName --api-key $env:STRIDE_NUGET_API_KEY --source "https://api.nuget.org/v3/index.json" --skip-duplicate
134+
}
135+
env:
136+
STRIDE_NUGET_API_KEY: ${{ secrets.STRIDE_NUGET_API_KEY }}
137+
138+
- name: Create GitHub Release
139+
if: ${{ needs.Package.outputs.version != '' }}
140+
uses: softprops/action-gh-release@v2
141+
with:
142+
tag_name: launcher/${{ needs.Package.outputs.version }}
143+
name: Stride Launcher ${{ needs.Package.outputs.version }}
144+
files: bin/launcher/*.exe
145+
prerelease: ${{ contains(needs.Package.outputs.version, '-') }}
146+
generate_release_notes: true
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: Unlist Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: Version to unlist (e.g. 4.3.0.2286-beta01)
8+
required: true
9+
type: string
10+
dry-run:
11+
description: Dry run (list packages without unlisting)
12+
default: true
13+
type: boolean
14+
15+
jobs:
16+
Validate:
17+
name: Validate
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Check release permissions
21+
env:
22+
GH_TOKEN: ${{ secrets.GH_PAT }}
23+
run: |
24+
ORG=$(echo "${{ github.repository }}" | cut -d/ -f1)
25+
TEAM="stride-release-managers"
26+
USER="${{ github.actor }}"
27+
STATUS=$(gh api "orgs/$ORG/teams/$TEAM/memberships/$USER" --silent 2>&1 && echo "ok" || echo "fail")
28+
if [ "$STATUS" = "fail" ]; then
29+
echo "::error::User $USER is not a member of $ORG/$TEAM. Unlisting requires stride-release-managers team membership."
30+
exit 1
31+
fi
32+
33+
Unlist:
34+
name: Unlist ${{ inputs.version }}
35+
needs: Validate
36+
runs-on: ubuntu-latest
37+
environment: production
38+
steps:
39+
- name: Find and unlist Stride packages
40+
shell: pwsh
41+
run: |
42+
$version = "${{ inputs.version }}"
43+
$dryRun = $${{ inputs.dry-run }}
44+
45+
# Query NuGet for all packages owned by Stride
46+
$searchUrl = "https://api-v2v3search-0.nuget.org/query?q=owner:stride&take=500&prerelease=true"
47+
$results = Invoke-RestMethod -Uri $searchUrl
48+
$stridePackages = $results.data | Where-Object { $_.id -like "Stride*" } | Select-Object -ExpandProperty id
49+
50+
echo "Found $($stridePackages.Count) Stride packages on NuGet.org"
51+
52+
$found = @()
53+
$notFound = @()
54+
55+
foreach ($id in $stridePackages) {
56+
# Check if this specific version exists
57+
$versionUrl = "https://api.nuget.org/v3-flatcontainer/$($id.ToLower())/index.json"
58+
try {
59+
$versions = Invoke-RestMethod -Uri $versionUrl -ErrorAction Stop
60+
if ($versions.versions -contains $version.ToLower()) {
61+
$found += $id
62+
}
63+
} catch {
64+
# Package version listing failed, skip
65+
}
66+
}
67+
68+
echo ""
69+
echo "## Packages with version $version : $($found.Count)"
70+
foreach ($id in $found) {
71+
echo " - $id"
72+
}
73+
74+
if ($dryRun) {
75+
echo ""
76+
echo "** DRY RUN - no packages were unlisted **"
77+
echo "Uncheck 'Dry run' to actually unlist these packages."
78+
} else {
79+
echo ""
80+
$failed = @()
81+
foreach ($id in $found) {
82+
echo "Unlisting $id $version..."
83+
dotnet nuget delete $id $version --api-key $env:STRIDE_NUGET_API_KEY --source "https://api.nuget.org/v3/index.json" --non-interactive
84+
if ($LASTEXITCODE -ne 0) { $failed += $id }
85+
}
86+
87+
if ($failed.Count -gt 0) {
88+
echo ""
89+
echo "::error::Failed to unlist $($failed.Count) packages: $($failed -join ', ')"
90+
exit 1
91+
}
92+
93+
echo ""
94+
echo "Successfully unlisted $($found.Count) packages for version $version"
95+
}
96+
97+
# Step summary
98+
echo "## Unlist Release" >> $env:GITHUB_STEP_SUMMARY
99+
echo "**Version:** $version" >> $env:GITHUB_STEP_SUMMARY
100+
echo "**Mode:** $(if ($dryRun) { 'Dry run' } else { 'Live' })" >> $env:GITHUB_STEP_SUMMARY
101+
echo "**Packages:** $($found.Count)" >> $env:GITHUB_STEP_SUMMARY
102+
echo '```' >> $env:GITHUB_STEP_SUMMARY
103+
$found | ForEach-Object { echo $_ >> $env:GITHUB_STEP_SUMMARY }
104+
echo '```' >> $env:GITHUB_STEP_SUMMARY
105+
env:
106+
STRIDE_NUGET_API_KEY: ${{ secrets.STRIDE_NUGET_API_KEY }}

0 commit comments

Comments
 (0)