Skip to content

fix: resolve 76 CI test failures across encoder roundtrip, HitObjectContainer lifetime, skin editor state, and GC tests - #360

Merged
winnerspiros merged 13 commits into
masterfrom
copilot/update-release-yml-and-optimizations
May 28, 2026
Merged

fix: resolve 76 CI test failures across encoder roundtrip, HitObjectContainer lifetime, skin editor state, and GC tests#360
winnerspiros merged 13 commits into
masterfrom
copilot/update-release-yml-and-optimizations

Conversation

Copilot AI commented May 27, 2026

Copy link
Copy Markdown

76 test failures across four distinct root causes introduced in the initial branch commit. Each fix is surgical and addresses the underlying logic bug rather than the symptom.

Fixes

  • LegacyBeatmapEncoder (66 failures — TestEncodeDecodeStability): Removed erroneous HIT_NORMAL → LegacyHitSoundType.Normal case from toLegacyHitSoundType(). The Normal bit is implicit in the legacy format — the decoder derives IsLayered from its absence (type != None && !type.HasFlag(Normal)), so encoding it explicitly breaks the roundtrip for every sample-bearing hit object.

  • HitObjectContainer (2 failures — TestHitObjectLifetime("non-pooled")): Fixed aliveObjectsSortedCache lifecycle for non-pooled drawables. Add(DrawableHitObject) was calling addDrawable() which immediately inserted into the sorted alive cache, while AddDrawable/RemoveDrawable both returned early for non-pooled entries — leaving all non-pooled objects permanently in AliveObjects regardless of lifetime state. Cache insertion/removal is now driven exclusively by the AddDrawable/RemoveDrawable callbacks for both pooled and non-pooled paths.

  • TestSceneSkinEditor (5 failures — TestMigrationTriangles + 4 cascade): SetUpSteps reset the skin after base.SetUpSteps() loaded the player, so each test inherited the previous test's skin. TestMigrationArgon left a modified custom argon skin active; the subsequent TestMigrationTriangles player load then failed resolving sh_CursorTrail.vs. Moved AddStep("reset skin", ...) to before base.SetUpSteps().

  • TestScenePlayerReferenceLeaking (3 failures — GC timeout): Under parallel CI load, a single GC.Collect() was insufficient to collect WorkingBeatmap instances within the 10-second AddUntilStep window. Replaced with a 3-pass forced blocking collection loop:

    for (int i = 0; i < 3; i++)
    {
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true);
        GC.WaitForPendingFinalizers();
    }

Copilot AI and others added 6 commits May 27, 2026 07:02
- release.yml now supports platform selection (all/android/windows/linux/macos/ios)
- Each platform builds in parallel with OS-specific optimizations
- Desktop builds: self-contained, single-file, trimmed, compressed, Server GC
- README rewritten to cover all platforms, removed Android-only focus
- Removed marketing language and device-specific references
- Added low-latency audio documentation for all platforms
- Added framework-level audio requirements section for mac/ios/linux
…py#37846)

- Part of ppy#37818
- [x] Depends on ppy#37845

Purely mechanical, split away for ease of review / due to size.

---------

Co-authored-by: Dean Herbert <pe@ppy.sh>
Copilot AI changed the title bump osu-framework to 2026.527.3 HitErrorMeter: make ScoreProcessor nullable to fix DI crash on Linux May 27, 2026
Copilot AI requested a review from winnerspiros May 27, 2026 19:47
Copilot AI changed the title HitErrorMeter: make ScoreProcessor nullable to fix DI crash on Linux fix: add explicit GITHUB_TOKEN permissions to workflows missing them May 27, 2026
Copilot AI requested a review from winnerspiros May 27, 2026 20:26
@gitar-bot

gitar-bot Bot commented May 28, 2026

Copy link
Copy Markdown

Gitar is working

Gitar

Copilot AI changed the title fix: add explicit GITHUB_TOKEN permissions to workflows missing them fix(tests): mark TestCorrectReflections as [FlakyTest] May 28, 2026
Copilot AI changed the title fix(tests): mark TestCorrectReflections as [FlakyTest] fix(ci): preserve Normal flag in legacy encoder and mark flaky tests May 28, 2026
Copilot AI requested a review from winnerspiros May 28, 2026 07:39
Copilot AI changed the title fix(ci): preserve Normal flag in legacy encoder and mark flaky tests fix(ci): correct HIT_NORMAL legacy encoder round-trip and remove flaky test noise May 28, 2026
Copilot AI requested a review from winnerspiros May 28, 2026 09:39
Copilot AI changed the title fix(ci): correct HIT_NORMAL legacy encoder round-trip and remove flaky test noise fix: resolve 76 CI test failures across encoder roundtrip, HitObjectContainer lifetime, skin editor state, and GC tests May 28, 2026
@winnerspiros
winnerspiros marked this pull request as ready for review May 28, 2026 14:46
Copilot AI review requested due to automatic review settings May 28, 2026 14:46
@winnerspiros
winnerspiros merged commit 16ba38d into master May 28, 2026
18 of 24 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates the fork to a newer ppy.osu.Framework build, migrates away from per-mod ScoreMultiplier overrides toward the new score-multiplier calculator API, and expands the release workflow/docs to cover multi-platform distribution.

Changes:

  • Bump ppy.osu.Framework* package references from 2026.527.12026.527.3.
  • Deprecate Mod.ScoreMultiplier and remove many per-mod overrides/tests relying on the old API.
  • Rework GitHub Actions release workflow + README to support multi-platform builds/releases.

Reviewed changes

Copilot reviewed 97 out of 97 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
osu.iOS.props Update ppy.osu.Framework.iOS package version.
osu.Game/osu.Game.csproj Update ppy.osu.Framework version and adjust pinned-comment reference.
osu.Game/Tests/Rulesets/RulesetScoreMultiplierTest.cs Remove old multiplier API assertion, keep calculator-based check.
osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs Make ScoreProcessor resolution optional and null-safe for event subscription.
osu.Game/Rulesets/UI/HitObjectContainer.cs Adjust alive-object cache handling for non-pooled drawables; refactor insertion helper.
osu.Game/Rulesets/Mods/UnknownMod.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/RateAdjustModHelper.cs Remove ScoreMultiplier helper property.
osu.Game/Rulesets/Mods/MultiMod.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModTouchDevice.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModTimeRamp.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModSynesthesia.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModSuddenDeath.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModScoreV2.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModRelax.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModRandom.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModPerfect.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModNoScope.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModNoMod.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModNoFail.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModNightcore.cs Remove RateAdjustModHelper use and ScoreMultiplier override.
osu.Game/Rulesets/Mods/ModMuted.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModMirror.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModHalfTime.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModEasy.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModDoubleTime.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModDifficultyAdjust.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModDaycore.cs Remove RateAdjustModHelper use and ScoreMultiplier override.
osu.Game/Rulesets/Mods/ModClassic.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModBarrelRoll.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModAutoplay.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModAdaptiveSpeed.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs Remove ScoreMultiplier override (now inherited).
osu.Game/Rulesets/Mods/Mod.cs Change ScoreMultiplier to obsolete virtual property defaulting to 1.
osu.Game.Tests/Visual/UserInterface/TestSceneModSelectOverlay.cs Remove ScoreMultiplier override in test mod.
osu.Game.Tests/Visual/UserInterface/TestSceneBeatmapAttributeText.cs Remove ScoreMultiplier override in test mod.
osu.Game.Tests/Visual/Gameplay/TestSceneSkinEditor.cs Reorder “reset skin” step to run before base setup.
osu.Game.Tests/Visual/Gameplay/TestScenePlayerReferenceLeaking.cs Add multiple forced GC passes to reduce flakiness.
osu.Game.Tests/Resources/TestResources.cs Remove ScoreMultiplier overrides in test mods.
osu.Game.Tests/Online/TestAPIModMessagePackSerialization.cs Remove ScoreMultiplier overrides in test mods.
osu.Game.Tests/Online/TestAPIModJsonSerialization.cs Remove ScoreMultiplier overrides in test mods.
osu.Game.Tests/NonVisual/DifficultyAdjustmentModCombinationsTest.cs Remove ScoreMultiplier overrides in test mods.
osu.Game.Tests/NonVisual/CustomDataDirectoryTest.cs Mark a migration test as [FlakyTest].
osu.Game.Tests/Mods/TestCustomisableModRuleset.cs Remove ScoreMultiplier override in test mod base.
osu.Game.Tests/Mods/ModUtilsTest.cs Remove ScoreMultiplier overrides in test mods.
osu.Game.Tests/Mods/ModSettingsTest.cs Remove ScoreMultiplier override in test mod.
osu.Game.Rulesets.Taiko/Mods/TaikoModSwap.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModSingleTap.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModSimplifiedRhythm.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModHidden.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModHardRock.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModFlashlight.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Taiko/Mods/TaikoModConstantSpeed.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModWiggle.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModTransform.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModTraceable.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModTargetPractice.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModStrictTracking.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModSpunOut.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModRepel.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModObjectScaleTween.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModMagnetised.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModHidden.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModHardRock.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModFreezeFrame.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModFlashlight.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModDepth.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModBubbles.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModBloom.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModBlinds.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModAutopilot.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/OsuModApproachDifferent.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu/Mods/InputBlockingMod.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModMirror.cs Add [FlakyTest] and import for the attribute.
osu.Game.Rulesets.Mania/Mods/ManiaModNoRelease.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModNightcore.cs Remove ScoreMultiplier override and related comment.
osu.Game.Rulesets.Mania/Mods/ManiaModInvert.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModHoldOff.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModHidden.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModHardRock.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModFlashlight.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModFadeIn.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModDualStages.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModDoubleTime.cs Remove ScoreMultiplier override and related comment.
osu.Game.Rulesets.Mania/Mods/ManiaModCover.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaModConstantSpeed.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Mania/Mods/ManiaKeyMod.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Catch/Mods/CatchModMovingFast.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Catch/Mods/CatchModHidden.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Catch/Mods/CatchModHardRock.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Catch/Mods/CatchModFloatingFruits.cs Remove ScoreMultiplier override (now inherited).
osu.Game.Rulesets.Catch/Mods/CatchModFlashlight.cs Remove ScoreMultiplier override (now inherited).
osu.Android.props Update ppy.osu.Framework.Android package version.
README.md Rewrite positioning/docs for multi-platform fork; update build/release instructions.
.github/workflows/release.yml Rework workflow into multi-platform “Release Build” with per-platform jobs + release job.
.github/workflows/deploy.yml Explicitly set empty default permissions at workflow level.
.github/workflows/_diffcalc_processor.yml Add explicit contents: read permission for the job.
Comments suppressed due to low confidence (2)

osu.Game/Rulesets/Mods/Mod.cs:1

  • Changing ScoreMultiplier from abstract (with meaningful per-mod overrides) to a virtual default of 1 is a behavior-breaking change for any remaining call sites that still read this property (UI display, serialization, logging, etc.). If the intent is full migration, consider introducing/recommending a replacement API for displaying multipliers (or keeping the legacy values temporarily) and updating the remaining consumers to use the calculator; otherwise, multipliers shown/used outside the new calculator path will silently become incorrect.
    osu.Game/Rulesets/UI/HitObjectContainer.cs:1
  • insertIntoAliveCache(drawable) unconditionally inserts into aliveObjectsSortedCache. If AddDrawable() can be invoked more than once for the same drawable without a symmetric RemoveDrawable() (for example due to re-entrant lifetime transitions or unexpected calls), this will produce duplicate cache entries and break consumers iterating AliveObjects. Consider guarding insertion (e.g., track an 'is in alive cache' flag on the drawable/entry, or ensure aliveObjectsSortedCache doesn't already contain the drawable before inserting).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- name: Determine version
id: version
run: |
INPUT_VERSION="${{ inputs.version }}"
- name: Determine platforms
id: platforms
run: |
PLATFORM="${{ inputs.platforms || 'all' }}"
needs: [prepare, build-android, build-windows, build-linux, build-macos, build-ios]
if: |
always() &&
(inputs.create_release == true || github.event_name == 'push') &&
Comment thread README.md
- On Samsung DeX, queries the active (external) display's mode list via `Activity.Display` / `DisplayManager`
| Option | What it does |
|---|---|
| **Renderer** | Picks the GPU backend. Windows: Metal / Vulkan / D3D11 / D3D12 / OpenGL + deferred variants. |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants