diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54e25738557e..d900e0029446 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,6 +17,21 @@ on: required: false default: true type: boolean + keystore_base64: + description: "Base64-encoded keystore (from SAVE-THESE-SECRETS.txt). Overrides ANDROID_KEYSTORE_BASE64 secret." + required: false + default: "" + type: string + key_alias: + description: "Signing key alias (from SAVE-THESE-SECRETS.txt). Overrides ANDROID_SIGNING_KEY_ALIAS secret." + required: false + default: "" + type: string + key_password: + description: "Signing key password (from SAVE-THESE-SECRETS.txt). Overrides ANDROID_SIGNING_KEY_PASSWORD secret." + required: false + default: "" + type: string jobs: build-android: @@ -82,17 +97,37 @@ jobs: run: | KS_PATH="${{ github.workspace }}/osu.Android/osu.keystore" - if [ -n "$KEYSTORE_BASE64" ]; then - # ── User provided a persistent keystore secret ────────────── - echo "$KEYSTORE_BASE64" | base64 --decode > "$KS_PATH" + # Priority: workflow_dispatch inputs > repository secrets > auto-generate. + # This lets users paste values from SAVE-THESE-SECRETS.txt directly into + # the "Run workflow" form so they don't need to set up repo secrets. + # Note: the auto-generated keystore uses the same password for both key and + # store, so a single key_password input covers both. Users with separate + # passwords should use repository secrets instead of workflow inputs. + EFFECTIVE_KS="${INPUT_KEYSTORE_BASE64:-$KEYSTORE_BASE64}" + EFFECTIVE_ALIAS="${INPUT_KEY_ALIAS:-$KEY_ALIAS_SECRET}" + EFFECTIVE_PASS="${INPUT_KEY_PASSWORD:-$KEY_PASS_SECRET}" + EFFECTIVE_STORE_PASS="${INPUT_KEY_PASSWORD:-${STORE_PASS_SECRET:-$EFFECTIVE_PASS}}" + + # Mask passwords so they never appear in logs. + if [ -n "$EFFECTIVE_PASS" ]; then echo "::add-mask::$EFFECTIVE_PASS"; fi + if [ -n "$EFFECTIVE_STORE_PASS" ]; then echo "::add-mask::$EFFECTIVE_STORE_PASS"; fi + + if [ -n "$EFFECTIVE_KS" ]; then + # ── User provided a keystore (via input or secret) ────────────── + echo "$EFFECTIVE_KS" | base64 --decode > "$KS_PATH" echo "has_keystore=true" >> "$GITHUB_OUTPUT" echo "generated=false" >> "$GITHUB_OUTPUT" - echo "key_alias=$KEY_ALIAS_SECRET" >> "$GITHUB_OUTPUT" - echo "key_pass=$KEY_PASS_SECRET" >> "$GITHUB_OUTPUT" - echo "store_pass=$STORE_PASS_SECRET" >> "$GITHUB_OUTPUT" - echo "✅ Using saved keystore from repository secrets." + echo "key_alias=${EFFECTIVE_ALIAS:-osu-release}" >> "$GITHUB_OUTPUT" + echo "key_pass=${EFFECTIVE_PASS}" >> "$GITHUB_OUTPUT" + echo "store_pass=${EFFECTIVE_STORE_PASS}" >> "$GITHUB_OUTPUT" + + if [ -n "$INPUT_KEYSTORE_BASE64" ]; then + echo "✅ Using keystore from workflow dispatch inputs." + else + echo "✅ Using saved keystore from repository secrets." + fi else - # ── No secret → auto-generate a keystore for this build ───── + # ── No keystore → auto-generate one for this build ────────────── # The APK will install fine on any device, but UPDATING from a # previous build signed with a DIFFERENT key will fail. # To avoid that, save the generated keystore as a secret @@ -141,6 +176,9 @@ jobs: KEY_ALIAS_SECRET: ${{ secrets.ANDROID_SIGNING_KEY_ALIAS }} KEY_PASS_SECRET: ${{ secrets.ANDROID_SIGNING_KEY_PASSWORD }} STORE_PASS_SECRET: ${{ secrets.ANDROID_SIGNING_STORE_PASSWORD }} + INPUT_KEYSTORE_BASE64: ${{ inputs.keystore_base64 }} + INPUT_KEY_ALIAS: ${{ inputs.key_alias }} + INPUT_KEY_PASSWORD: ${{ inputs.key_password }} - name: Determine version id: version @@ -308,6 +346,11 @@ jobs: echo "" echo " ⚡ After saving the secrets, all future builds will use the" echo " same keystore automatically — no more setup needed." + echo "" + echo " 💡 QUICK OPTION: You can also paste the values from" + echo " SAVE-THESE-SECRETS.txt directly into the workflow" + echo " dispatch inputs (keystore_base64, key_alias, key_password)" + echo " when running the 'Build Android APK' workflow manually." echo "==================================================================" # Create a GitHub Release with the APK attached. diff --git a/osu.Game.Tests/Visual/RankedPlay/TestSceneStarRatingSequence.cs b/osu.Game.Tests/Visual/RankedPlay/TestSceneStarRatingSequence.cs new file mode 100644 index 000000000000..4644a00f029a --- /dev/null +++ b/osu.Game.Tests/Visual/RankedPlay/TestSceneStarRatingSequence.cs @@ -0,0 +1,33 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro; + +namespace osu.Game.Tests.Visual.RankedPlay +{ + [TestFixture] + public partial class TestSceneStarRatingSequence : RankedPlayTestScene + { + [Test] + public void TestBasicAppearance() + { + float starRating = 5; + + AddSliderStep("set star rating", 0f, 10, 5, sr => starRating = sr); + AddStep("play sequence", () => + { + StarRatingSequence sequence; + + Child = sequence = new StarRatingSequence + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre + }; + double delay = 0; + sequence.Play(ref delay, starRating); + }); + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Intro/StarRatingSequence.cs b/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Intro/StarRatingSequence.cs index 73fdce23578d..f084b008189f 100644 --- a/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Intro/StarRatingSequence.cs +++ b/osu.Game/Screens/OnlinePlay/Matchmaking/RankedPlay/Intro/StarRatingSequence.cs @@ -14,8 +14,8 @@ using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Overlays; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay.Intro { @@ -35,7 +35,7 @@ public partial class StarRatingSequence : CompositeDrawable private float lastTickStdDev; [BackgroundDependencyLoader] - private void load(OsuColour colour, AudioManager audio) + private void load(OsuColour colour, OverlayColourProvider overlayColourProvider, AudioManager audio) { Width = 600; AutoSizeAxes = Axes.Y; @@ -43,19 +43,18 @@ private void load(OsuColour colour, AudioManager audio) Origin = Anchor.Centre; Alpha = 0; - Masking = true; - CornerRadius = 10; - InternalChild = new Container { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, + Masking = true, + CornerRadius = 10, Children = new Drawable[] { new Box { - Colour = Color4.Black, - Alpha = 0.2f, + Colour = overlayColourProvider.Background5, + Alpha = 0.8f, RelativeSizeAxes = Axes.Both, }, new FillFlowContainer @@ -88,7 +87,7 @@ private void load(OsuColour colour, AudioManager audio) new Box { Alpha = 0.4f, - Colour = Color4.Black, + Colour = overlayColourProvider.Background4, RelativeSizeAxes = Axes.Both, }, bars = new Container @@ -204,7 +203,7 @@ public void Play(ref double delay, float starRating) RelativePositionAxes = Axes.X, X = starRating * 0.1f, Y = 34, - Colour = colours.ForStarDifficulty(starRating), + Colour = starRating < OsuColour.STAR_DIFFICULTY_DEFINED_COLOUR_CUTOFF ? colours.ForStarDifficulty(starRating) : colours.ForStarDifficultyText(starRating), Spacing = new Vector2(4, 0), Children = [ @@ -226,6 +225,8 @@ public void Play(ref double delay, float starRating) }; centerContainer.Add(container); + // Avoid text getting masked out by inner containers + AddInternal(container.CreateProxy()); container.FadeInFromZero(200) .ScaleTo(0) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index be2f5903b703..f1b72ab2d324 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -40,7 +40,7 @@ - + diff --git a/submodules/osu-framework b/submodules/osu-framework index 8097681bfbb9..c85f1debf40c 160000 --- a/submodules/osu-framework +++ b/submodules/osu-framework @@ -1 +1 @@ -Subproject commit 8097681bfbb9331f6766a4c4e862924df640df15 +Subproject commit c85f1debf40cfc7188701431419e066df3568f8e