From d8d042349a7719fc7d48805186a1e115a40aa2c2 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Thu, 20 Aug 2026 17:10:01 +0300 Subject: [PATCH] Close gaps in off-queue DX 49/54/55. Pass -c through to dotnet run so Release stamp and process match, assert changelog order for more than one commit, and restore the last school tab from sessionStorage when opening from the menu. Co-authored-by: Cursor --- docs/design/off-queue/skip-stale-build.md | 12 +++++------ run-aspire.ps1 | 1 + run-aspire.sh | 2 +- src/HSchool.Client/src/ui/gameScreen.test.ts | 20 +++++++++++++++++++ .../BuildChangelogTests.cs | 17 ++++++++++------ 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/docs/design/off-queue/skip-stale-build.md b/docs/design/off-queue/skip-stale-build.md index 4c84bad..003ce45 100644 --- a/docs/design/off-queue/skip-stale-build.md +++ b/docs/design/off-queue/skip-stale-build.md @@ -14,18 +14,18 @@ **Стало.** Если `HSchool.AppHost.dll` и `HSchool.Server.dll` новее входов (C#, csproj, props, `global.json`), скрипт делает `dotnet run --no-build`. Иначе — `dotnet build`, потом `--no-build`. -`--rebuild` собирает всегда. Конфигурация (`-c` / `--configuration`) выбирает, какие dll сравнивать; -по умолчанию Debug, как у `dotnet run`. +`--rebuild` собирает всегда. Конфигурация (`-c` / `--configuration`) выбирает, какие dll сравнивать +и с какой конфигурацией звать `dotnet run`; по умолчанию Debug. **Почему.** Инкрементальный MSBuild всё равно оценивает Aspire SDK. `--no-build` это пропускает. Клиентский TypeScript и JSONC модов не входы: Vite и каталог читают диск (`ContentRoot`), а не `bin`. Тестовые проекты AppHost не ссылается — их правки запуск не пересобирают. -Правила «устарел ли билд» живут в `tools/apphost-uptodate.ps1` (то, что вызывает `run-aspire.ps1`) и в -`LaunchBuildStamp` (то, что проверяют тесты). Менять надо оба. +Правила «устарел ли билд» живут в трёх местах: `tools/apphost-uptodate.ps1` (Windows), +`needs_build` в `run-aspire.sh` (Ubuntu) и `LaunchBuildStamp` (то, что проверяют тесты). +Менять надо все три. ### Что не входит Голый `dotnet run --project src/HSchool.AppHost` по-прежнему собирает — так удобнее агентам с -грязным деревом. Linux-обёртки нет: точка входа Windows — `.cmd`. Протокол, HTTP и сейв не -трогаем. +грязным деревом. Протокол, HTTP и сейв не трогаем. diff --git a/run-aspire.ps1 b/run-aspire.ps1 index f12dc4b..00ceaf8 100644 --- a/run-aspire.ps1 +++ b/run-aspire.ps1 @@ -121,6 +121,7 @@ $run = @( '--project', (Join-Path $PSScriptRoot 'src\HSchool.AppHost\HSchool.AppHost.csproj') '--no-build' '--no-restore' + '-c', $configuration ) + $dotnetArgs & dotnet run @run $exitCode = $LASTEXITCODE diff --git a/run-aspire.sh b/run-aspire.sh index b79fc01..8da89c1 100644 --- a/run-aspire.sh +++ b/run-aspire.sh @@ -131,7 +131,7 @@ fi echo set +e -dotnet run --project src/HSchool.AppHost/HSchool.AppHost.csproj --no-build --no-restore "${dotnet_args[@]}" +dotnet run --project src/HSchool.AppHost/HSchool.AppHost.csproj --no-build --no-restore -c "$configuration" "${dotnet_args[@]}" exit_code=$? set -e diff --git a/src/HSchool.Client/src/ui/gameScreen.test.ts b/src/HSchool.Client/src/ui/gameScreen.test.ts index 66f2a7a..7e8161c 100644 --- a/src/HSchool.Client/src/ui/gameScreen.test.ts +++ b/src/HSchool.Client/src/ui/gameScreen.test.ts @@ -7,6 +7,7 @@ import { getLocale, setLocale } from '../i18n/locale.ts'; import { t } from '../i18n/strings.ts'; import { GameScreen } from './gameScreen.ts'; import type { School } from '../net/api.ts'; +import { patchChrome } from './viewState.ts'; vi.mock('../net/api.ts', async (importOriginal) => { const actual = await importOriginal(); @@ -272,6 +273,25 @@ describe('GameScreen view restore', () => { expect(screen.element.querySelector('.panel__body--fill')?.hasAttribute('hidden')).toBe(false); }); + it('reopens the last tab from sessionStorage when opening from the menu', () => { + history.replaceState(null, '', '/'); + patchChrome(1, { route: { tab: 'people' } }); + const screen = new GameScreen({ + onLeave: () => {}, + onSetRunning: () => {}, + onSetSpeed: () => {}, + onSkip: () => {}, + }); + document.body.append(screen.element); + screen.show(school()); + + const peopleTab = [...screen.element.querySelectorAll('.panel__tab')].find( + (button) => button.textContent === t('peopleTitle'), + ); + expect(peopleTab?.classList.contains('panel__tab--active')).toBe(true); + expect(location.search).toContain('tab=people'); + }); + it('keeps a guest on overview even when the URL asks for manage', () => { history.replaceState(null, '', '/?school=3&mode=manage'); const screen = new GameScreen({ diff --git a/tests/HSchool.Server.Tests/BuildChangelogTests.cs b/tests/HSchool.Server.Tests/BuildChangelogTests.cs index 6732403..ee83658 100644 --- a/tests/HSchool.Server.Tests/BuildChangelogTests.cs +++ b/tests/HSchool.Server.Tests/BuildChangelogTests.cs @@ -5,13 +5,15 @@ namespace HSchool.Server.Tests; public class BuildChangelogTests { private const string Head = "cccccccccccccccccccccccccccccccccccccccc"; + private const string Mid = "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"; private const string Mark = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; private const string Merge = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; private const string Unknown = "dddddddddddddddddddddddddddddddddddddddd"; private static readonly string Sample = string.Join('\n', Head, - $"{Head}\u001f2026-01-03T12:00:00Z\u001fAdd changelog window", + $"{Head}\u001f2026-01-04T12:00:00Z\u001fAdd changelog window", + $"{Mid}\u001f2026-01-03T12:00:00Z\u001fSkip stale AppHost build", $"{Mark}\u001f2026-01-02T12:00:00Z\u001fMark phase 54 in progress.", $"{Merge}\u001f2026-01-01T12:00:00Z\u001fMerge branch 'phase/53-weather-commute'"); @@ -22,9 +24,11 @@ public class BuildChangelogTests var visible = changelog.VisibleSince(Merge); - var commit = Assert.Single(visible); - Assert.Equal(Head, commit.Sha); - Assert.Equal("Add changelog window", commit.Subject); + Assert.Equal(2, visible.Count); + Assert.Equal(Mid, visible[0].Sha); + Assert.Equal("Skip stale AppHost build", visible[0].Subject); + Assert.Equal(Head, visible[1].Sha); + Assert.Equal("Add changelog window", visible[1].Subject); } [Fact] @@ -34,8 +38,9 @@ public class BuildChangelogTests var visible = changelog.VisibleSince(Mark); - var commit = Assert.Single(visible); - Assert.Equal("Add changelog window", commit.Subject); + Assert.Equal(2, visible.Count); + Assert.Equal("Skip stale AppHost build", visible[0].Subject); + Assert.Equal("Add changelog window", visible[1].Subject); } [Fact]