Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ concurrency:

permissions:
contents: read # to fetch code (actions/checkout)
packages: read # to restore NuGet packages from GitHub Packages
security-events: write # for reporting InspectCode issues

jobs:
Expand All @@ -16,7 +17,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- name: Install .NET 10.0.x
Expand All @@ -31,6 +31,9 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props') }}
restore-keys: ${{ runner.os }}-nuget-

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

Comment on lines +34 to +36

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow authenticates to GitHub Packages using dotnet nuget update source ... --store-password-in-clear-text, which writes the token into a NuGet.Config file in plain text. To reduce the risk of accidental token exposure (e.g., if the workspace/config is ever uploaded), consider writing credentials to a temporary config under $RUNNER_TEMP and passing --configfile to restore/build, then deleting it after.

Copilot uses AI. Check for mistakes.
- name: Restore Tools
run: dotnet tool restore

Expand All @@ -53,10 +56,6 @@ jobs:
exit_code=0
while read -r line; do
if [[ ! -z "$line" ]]; then
# Skip submodule files — third-party code doesn't use our license header
if [[ "$line" == *"./submodules/"* ]]; then
continue
fi
echo "::error::$line"
exit_code=1
fi
Expand Down Expand Up @@ -93,7 +92,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- name: Install .NET 10.0.x
Expand All @@ -108,6 +106,9 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props') }}
restore-keys: ${{ runner.os }}-nuget-

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

- name: Compile
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf

Expand Down Expand Up @@ -171,7 +172,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- name: Setup JDK 11
Expand All @@ -192,6 +192,9 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props') }}
restore-keys: ${{ runner.os }}-nuget-

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

- name: Install .NET workloads
run: dotnet workload install android

Expand All @@ -206,7 +209,6 @@ jobs:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- name: Install .NET 10.0.x
Expand All @@ -221,6 +223,9 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props') }}
restore-keys: ${{ runner.os }}-nuget-

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

- name: Set Xcode version
run: sudo xcode-select -s /Applications/Xcode_26.3.app

Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ jobs:
name: Pack
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
packages: read
steps:
- name: Checkout
uses: actions/checkout@v6
Expand All @@ -55,6 +58,9 @@ jobs:
with:
dotnet-version: "10.0.x"

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

Comment on lines +61 to +63

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job authenticates to GitHub Packages by writing the token into NuGet.Config in clear text (--store-password-in-clear-text). Consider using a temporary config file (via --configfile) scoped to the job and removing it after restore/pack to avoid any possibility of credentials being captured in uploaded artifacts or reused unexpectedly.

Copilot uses AI. Check for mistakes.
- name: Pack
run: |
# Replace project references in templates with package reference, because they're included as source files.
Expand Down
27 changes: 5 additions & 22 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ jobs:
timeout-minutes: 60
permissions:
contents: write
packages: read
steps:
- name: Checkout
uses: actions/checkout@v6
with:
submodules: recursive
fetch-depth: 0

- name: Setup JDK 17
Expand All @@ -61,6 +61,9 @@ jobs:
- name: Install .NET Android workload
run: dotnet workload install android

- name: Authenticate to GitHub Packages
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step stores the GitHub Packages token in clear text via dotnet nuget update source ... --store-password-in-clear-text. Consider instead generating a temporary NuGet.Config (or updating a temp config via --configfile) for the duration of the job and deleting it afterwards to minimize the chance of credentials being persisted or leaked via artifacts/logging.

Suggested change
run: dotnet nuget update source winnerspiros-github --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
run: |
NUGET_CONFIG_FILE="$RUNNER_TEMP/NuGet.Config"
cat > "$NUGET_CONFIG_FILE" <<'EOF'
<?xml version="1.0" encoding="utf-8"?>
<configuration>
</configuration>
EOF
dotnet nuget add source "https://nuget.pkg.github.com/winnerspiros/index.json" \
--name winnerspiros-github \
--username "${{ github.actor }}" \
--password "${{ secrets.GITHUB_TOKEN }}" \
--store-password-in-clear-text \
--configfile "$NUGET_CONFIG_FILE"
echo "NUGET_CONFIG_FILE=$NUGET_CONFIG_FILE" >> "$GITHUB_ENV"

Copilot uses AI. Check for mistakes.

- name: Ensure Android NDK and CMake are available
run: |
# The ubuntu-latest runner has $ANDROID_HOME pre-installed.
Expand Down Expand Up @@ -215,7 +218,6 @@ jobs:
-p:AndroidSigningKeyAlias="${{ steps.keystore.outputs.key_alias }}"
-p:AndroidSigningKeyPass="${{ steps.keystore.outputs.key_pass }}"
-p:AndroidSigningStorePass="${{ steps.keystore.outputs.store_pass }}"
-p:CustomBeforeMicrosoftCommonTargets="${{ github.workspace }}/build/SuppressSubmoduleWarnings.targets"

- name: Find and rename APK
id: find_apk
Expand Down Expand Up @@ -256,7 +258,6 @@ jobs:
- name: Verify native libraries in APK
run: |
APK="${{ steps.find_apk.outputs.apk_path }}"
SUBMOD="submodules/osu-framework/osu.Framework.Android/arm64-v8a"
echo "Checking APK for required native libraries..."

Comment on lines 258 to 262

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The native library verification here only checks that the required .so files are present. Previously there was also an ABI/compatibility validation to ensure libbass.so was the Android build (not a desktop/Linux variant), which helps catch hard-to-debug startup crashes. Consider reintroducing an equivalent compatibility check (e.g., extracting and inspecting libbass.so with readelf).

Copilot uses AI. Check for mistakes.
NATIVE_LIBS=$(unzip -l "$APK" | grep "lib/arm64-v8a/.*\.so" || true)
Expand All @@ -275,31 +276,13 @@ jobs:

if [ "$MISSING" -ne 0 ]; then
echo ""
echo "::error::One or more required native libraries are missing. Check that the osu-framework submodule is initialised and the AndroidNativeLibrary glob in osu.Android.props resolves correctly."
echo "::error::One or more required native libraries are missing from the APK. Ensure ppy.osu.Framework.Android was properly restored from the winnerspiros GitHub Packages feed."
exit 1
fi

echo ""
echo "All required native libraries present ✓"

# Verify the BASS libraries are the Android-built versions, not the Linux desktop
# ones from the NativeLibs NuGet package. The Android libbass.so links against
# libOpenSLES.so (Android audio API); the Linux one links against libc.so.6.
echo ""
echo "Verifying native library ABI compatibility..."
TMPDIR=$(mktemp -d)
unzip -q -o "$APK" "lib/arm64-v8a/libbass.so" -d "$TMPDIR"
if readelf -d "$TMPDIR/lib/arm64-v8a/libbass.so" | grep -q "libOpenSLES.so"; then
echo "✅ libbass.so is the correct Android build (links libOpenSLES.so)"
else
echo "::error::libbass.so in APK is NOT the Android build — it appears to be the Linux desktop version from ppy.osu.Framework.NativeLibs NuGet. The app will crash with DllNotFoundException."
echo "::error::Ensure ppy.osu.Framework.NativeLibs has ExcludeAssets=native in osu.Android.props."
readelf -d "$TMPDIR/lib/arm64-v8a/libbass.so" | grep NEEDED || true
rm -rf "$TMPDIR"
exit 1
fi
rm -rf "$TMPDIR"

- name: Upload APK artifact
uses: actions/upload-artifact@v7
with:
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

15 changes: 0 additions & 15 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
<GenerateAssemblyInfo Condition="'$(Configuration)'=='Debug'">false</GenerateAssemblyInfo>
<!-- Required due to the above -->
<NoWarn Condition="'$(Configuration)'=='Debug'">$(NoWarn);CA1416</NoWarn>
<!-- NU1605: Suppress package downgrade error for ppy.Veldrid.SPIRV.
We intentionally override the framework's 1.0.15-gfbb03d21c2 with the fork's
1.0.15-gb268bf39ea. NuGet considers this a "downgrade" because 'b' < 'f' in
prerelease suffix comparison, but it's actually a newer fork build. -->
<NoWarn>$(NoWarn);NU1605</NoWarn>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>$(MSBuildThisFileDirectory)app.manifest</ApplicationManifest>
Expand All @@ -24,16 +19,6 @@
<ItemGroup Label="Resources">
<EmbeddedResource Include="Resources\**\*.*" />
</ItemGroup>
<!-- Override ppy.Veldrid.SPIRV with winnerspiros/veldrid-spirv fork for ALL projects.
The fork (1.0.15-gb268bf39ea) is API-compatible and includes:
- 16KB ELF-aligned Android .so (no PatchElfPageSize workaround needed)
- Modern runtimes/android-arm64/native/ NuGet layout (no MonoAndroid10 workarounds)
- CompileCompute interop bug fix, debug flag passthrough, error diagnostics
The .nupkg is in local-packages/ (see NuGet.Config).
This overrides the framework's transitive reference to 1.0.15-gfbb03d21c2. -->
<ItemGroup Label="Veldrid.SPIRV Override">
<PackageReference Include="ppy.Veldrid.SPIRV" Version="1.0.15-gb268bf39ea" />
</ItemGroup>
<ItemGroup Label="Code Analysis">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
Expand Down
5 changes: 2 additions & 3 deletions NuGet.Config
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
<configuration>
<packageSources>
<clear />
<!-- winnerspiros/veldrid-spirv fork NuGet package (included in local-packages/).
Source: https://github.com/winnerspiros/veldrid-spirv/releases -->
<add key="local-packages" value="local-packages" />
<!-- winnerspiros/osu-framework fork NuGet packages (published to GitHub Packages) -->

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NuGet.Config adds the winnerspiros GitHub Packages feed but doesn’t document how contributors should authenticate locally (restore will fail without credentials for this source). Consider adding a short note here (or in README/CONTRIBUTING) with the recommended dotnet nuget add/update source command and required token scopes so local builds are reproducible.

Suggested change
<!-- winnerspiros/osu-framework fork NuGet packages (published to GitHub Packages) -->
<!--
winnerspiros/osu-framework fork NuGet packages (published to GitHub Packages).
Local restore requires authenticating this source first, for example:
dotnet nuget update source winnerspiros-github --username YOUR_GITHUB_USERNAME --password YOUR_GITHUB_TOKEN --store-password-in-clear-text
If the source has not been added yet, use:
dotnet nuget add source https://nuget.pkg.github.com/winnerspiros/index.json --name winnerspiros-github --username YOUR_GITHUB_USERNAME --password YOUR_GITHUB_TOKEN --store-password-in-clear-text
The GitHub token should include at least the `read:packages` scope; add `repo` as well if the package/repository is private.
-->

Copilot uses AI. Check for mistakes.
<add key="winnerspiros-github" value="https://nuget.pkg.github.com/winnerspiros/index.json" />
Comment on lines +5 to +6

Copilot AI Apr 20, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the framework submodule is removed and replaced with a GitHub Packages feed, README.md still contains submodule-based setup instructions (e.g., cloning with --recurse-submodules / “Framework as submodule”). Please update the docs to match the new NuGet-based setup to avoid confusing contributors.

Copilot uses AI. Check for mistakes.
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
8 changes: 0 additions & 8 deletions build/SuppressSubmoduleWarnings.targets

This file was deleted.

3 changes: 0 additions & 3 deletions local-packages/.gitignore

This file was deleted.

Binary file not shown.
34 changes: 1 addition & 33 deletions osu.Android.props
Original file line number Diff line number Diff line change
Expand Up @@ -69,41 +69,9 @@
</ItemGroup>

<ItemGroup>
<!-- Use winnerspiros/osu-framework fork (net10.0-android, optimized) via submodule instead of ppy NuGet package -->
<ProjectReference Include="$(MSBuildThisFileDirectory)submodules/osu-framework/osu.Framework.Android/osu.Framework.Android.csproj" />

<!-- Suppress native assets from the desktop NativeLibs NuGet package.
ppy.osu.Framework.NativeLibs (transitive via osu.Framework.csproj) ships
runtimes/linux-arm64/native/libbass.so and friends built for GNU/Linux (they link
libc.so.6, libpthread.so.0, etc.). The .NET RID fallback chain for android-arm64
(android-arm64 → android → unix → any) causes the Linux ARM64 .so files to leak
into the APK even though the NuGet has an android/native/_._ placeholder.
The result: the APK ends up with a Linux libbass.so that cannot load on Android
(DllNotFoundException at startup).
ExcludeAssets="native" prevents NuGet from contributing any .so files;
the correct Android-built libraries are supplied by AndroidNativeLibrary below. -->
<PackageReference Include="ppy.osu.Framework.NativeLibs" Version="2025.806.0-nativelibs" ExcludeAssets="native" PrivateAssets="all" />
</ItemGroup>

<!-- Include framework native libraries (BASS audio, FFmpeg, etc.) from the submodule.
When using a NuGet package these are bundled automatically; with a ProjectReference
they must be declared explicitly or the app crashes at startup with
System.DllNotFoundException: bass (or similar).
Use forward slashes — backslash globs silently match zero files on Linux CI runners,
which produces an APK without libbass.so (and the other native libs). -->
<ItemGroup>
<AndroidNativeLibrary Include="$(MSBuildThisFileDirectory)submodules/osu-framework/osu.Framework.Android/arm64-v8a/*.so" Abi="arm64-v8a" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.420.3" />
</ItemGroup>

<!-- Fail the build early if critical native libraries are missing.
A missing .so means the app will crash on startup with DllNotFoundException.
This catches silent glob failures (e.g. uninitialised submodule, wrong path)
and NuGet restore failures for Veldrid.SPIRV. -->
<Target Name="ValidateFrameworkNativeLibraries" BeforeTargets="Build">
<Error Condition="!Exists('$(MSBuildThisFileDirectory)submodules/osu-framework/osu.Framework.Android/arm64-v8a/libbass.so')"
Text="libbass.so not found in submodules/osu-framework/osu.Framework.Android/arm64-v8a/. Ensure the osu-framework submodule is initialised: git submodule update --init --recursive" />
</Target>

<PropertyGroup>
<!-- Fody does not handle Android build well, and warns when unchanged.
Since Realm objects are not declared directly in Android projects, simply disable Fody. -->
Expand Down
7 changes: 1 addition & 6 deletions osu.Android.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@
"osu.Game.Rulesets.Taiko\\osu.Game.Rulesets.Taiko.csproj",
"osu.Game.Tests.Android\\osu.Game.Tests.Android.csproj",
"osu.Game.Tests\\osu.Game.Tests.csproj",
"osu.Game\\osu.Game.csproj",
"submodules\\osu-framework\\osu.Framework\\osu.Framework.csproj",
"submodules\\osu-framework\\osu.Framework.Android\\osu.Framework.Android.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid\\Veldrid.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.MetalBindings\\Veldrid.MetalBindings.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.OpenGLBindings\\Veldrid.OpenGLBindings.csproj"
"osu.Game\\osu.Game.csproj"
]
}
}
6 changes: 1 addition & 5 deletions osu.Desktop.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling.Tests\\osu.Game.Rulesets.EmptyScrolling.Tests.csproj",
"Templates\\Rulesets\\ruleset-scrolling-empty\\osu.Game.Rulesets.EmptyScrolling\\osu.Game.Rulesets.EmptyScrolling.csproj",
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon.Tests\\osu.Game.Rulesets.Pippidon.Tests.csproj",
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj",
"submodules\\osu-framework\\osu.Framework\\osu.Framework.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid\\Veldrid.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.MetalBindings\\Veldrid.MetalBindings.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.OpenGLBindings\\Veldrid.OpenGLBindings.csproj"
"Templates\\Rulesets\\ruleset-scrolling-example\\osu.Game.Rulesets.Pippidon\\osu.Game.Rulesets.Pippidon.csproj"
]
}
}
3 changes: 1 addition & 2 deletions osu.Game/osu.Game.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Realm" Version="20.1.0" />
<!-- Use winnerspiros/osu-framework fork (net10.0, optimized) via submodule instead of ppy NuGet package -->
<ProjectReference Include="..\submodules\osu-framework\osu.Framework\osu.Framework.csproj" />
<PackageReference Include="ppy.osu.Framework" Version="2026.420.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2026.420.0" />
<PackageReference Include="Sentry" Version="6.2.0" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
Expand Down
7 changes: 1 addition & 6 deletions osu.iOS.props
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,6 @@
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
</PropertyGroup>
<ItemGroup>
<!-- Use winnerspiros/osu-framework fork (net10.0-ios, optimized) via submodule instead of ppy NuGet package -->
<ProjectReference Include="$(MSBuildThisFileDirectory)submodules\osu-framework\osu.Framework.iOS\osu.Framework.iOS.csproj" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2026.420.3" />
</ItemGroup>
<!-- When using ProjectReference instead of NuGet, the framework's .props and .targets are not
auto-imported. Import explicitly for NativeReference items (bass/ffmpeg xcframeworks)
and workaround targets (remove macOS-only frameworks like ApplicationServices/Quartz). -->
<Import Project="$(MSBuildThisFileDirectory)submodules\osu-framework\osu.Framework.iOS.props" />
</Project>
9 changes: 2 additions & 7 deletions osu.iOS.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@
"osu.Game.Tests.iOS\\osu.Game.Tests.iOS.csproj",
"osu.Game.Tests\\osu.Game.Tests.csproj",
"osu.Game\\osu.Game.csproj",
"osu.iOS\\osu.iOS.csproj",
"submodules\\osu-framework\\osu.Framework\\osu.Framework.csproj",
"submodules\\osu-framework\\osu.Framework.iOS\\osu.Framework.iOS.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid\\Veldrid.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.MetalBindings\\Veldrid.MetalBindings.csproj",
"submodules\\osu-framework\\submodules\\veldrid\\src\\Veldrid.OpenGLBindings\\Veldrid.OpenGLBindings.csproj"
"osu.iOS\\osu.iOS.csproj"
]
}
}
}
Loading
Loading