diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6847ed7..b5b851d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -104,7 +104,14 @@ jobs: android: runs-on: ubuntu-latest - timeout-minutes: 45 + # 70 rather than 45: a ghc-options change invalidates every + # Haskell derivation, and this job only READS nix-cache.jappie.me + # (extra-substituters; nothing here pushes to it), so each run of + # such a change builds cold until the cache is populated + # externally, and the budget must fit a full cold build; run + # 29340371964 timed out at exactly 45 minutes mid emulator test + # on such a build. Warm runs take ~25 minutes. + timeout-minutes: 70 steps: - name: Free disk space run: | @@ -157,7 +164,14 @@ jobs: ios: runs-on: macos-latest - timeout-minutes: 45 + # 70 rather than 45: like the android job, this only READS + # nix-cache.jappie.me, so a ghc-options change builds cold until + # the cache is fed externally, and the leftover budget must still + # fit the simulator test (which is also the #235 flake). The + # cutoff has eaten the simulator test after a successful build + # twice (run 29281533228 on #239, run 29344658446 on #244) and + # once mid-compile before that (9dcf105). + timeout-minutes: 70 steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v31 diff --git a/Changelog.md b/Changelog.md index 7d4671a..e97aeaf 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,13 @@ ### Changed +- Missing fields in record construction are compile errors now + (`-Werror=missing-fields`): the default-on warning was overlooked + during the #243 migration and surfaced as a runtime crash in the + test suite, and the same flag immediately caught three long-standing + incomplete `UserState` constructions in the tests. A missing field + is always a latent runtime crash, so the build refuses it outright. + - BREAKING: text color moved from `WidgetStyle` into the text-bearing configs (`tcTextColor` / `bcTextColor` / `tiTextColor`, next to the font override), following the `tcFontConfig` precedent. A text diff --git a/hatter.cabal b/hatter.cabal index a781c20..09fe483 100644 --- a/hatter.cabal +++ b/hatter.cabal @@ -76,6 +76,7 @@ common common-options -O2 -Wall -split-sections -Wincomplete-uni-patterns -Wincomplete-record-updates -Widentities -Wredundant-constraints -Wcpp-undef -fwarn-tabs -Wpartial-fields + -Werror=missing-fields -fdefer-diagnostics -Wunused-packages -fenable-th-splice-warnings -fno-omit-yields diff --git a/test/Test/AppContextTests.hs b/test/Test/AppContextTests.hs index 45edf6d..3e78073 100644 --- a/test/Test/AppContextTests.hs +++ b/test/Test/AppContextTests.hs @@ -32,6 +32,7 @@ import Hatter.Lifecycle ) import Hatter.Widget (ButtonConfig(..), TextConfig(..), Widget(..)) import Hatter.Permission (newPermissionState) +import Hatter.PlatformSignIn (newPlatformSignInState) import Hatter.SecureStorage (newSecureStorageState) import Hatter.Ble (newBleState) import Hatter.Dialog (newDialogState) @@ -76,6 +77,7 @@ registrationTests = testGroup "Registration" dummyHttpState <- newHttpState dummyNetworkStatusState <- newNetworkStatusState dummyAnimationState <- newAnimationState + dummyPlatformSignInState <- newPlatformSignInState let dummyUserState = UserState { userPermissionState = dummyPermState , userSecureStorageState = dummySecureStorageState @@ -88,6 +90,8 @@ registrationTests = testGroup "Registration" , userHttpState = dummyHttpState , userNetworkStatusState = dummyNetworkStatusState , userAnimationState = dummyAnimationState + , userPlatformSignInState = dummyPlatformSignInState + , userRequestRedraw = pure () } viewFn <- readIORef (acViewFunction appCtx) widget <- viewFn dummyUserState @@ -124,6 +128,7 @@ registrationTests = testGroup "Registration" dummyHttpState <- newHttpState dummyNetworkStatusState <- newNetworkStatusState dummyAnimationState <- newAnimationState + dummyPlatformSignInState <- newPlatformSignInState let dummyUserState = UserState { userPermissionState = dummyPermState , userSecureStorageState = dummySecureStorageState @@ -136,6 +141,8 @@ registrationTests = testGroup "Registration" , userHttpState = dummyHttpState , userNetworkStatusState = dummyNetworkStatusState , userAnimationState = dummyAnimationState + , userPlatformSignInState = dummyPlatformSignInState + , userRequestRedraw = pure () } viewFnA <- readIORef (acViewFunction appCtxA) viewFnB <- readIORef (acViewFunction appCtxB) diff --git a/test/Test/WidgetTests.hs b/test/Test/WidgetTests.hs index b5cf06b..a00a6f8 100644 --- a/test/Test/WidgetTests.hs +++ b/test/Test/WidgetTests.hs @@ -56,6 +56,7 @@ import Hatter.Widget ) import Hatter.Render (RenderState(..), RenderedNode(..), renderWidget, dispatchEvent, dispatchTextEvent) import Hatter.Permission (newPermissionState) +import Hatter.PlatformSignIn (newPlatformSignInState) import Hatter.SecureStorage (newSecureStorageState) import Hatter.Ble (newBleState) import Hatter.Dialog (newDialogState) @@ -160,6 +161,7 @@ uiTests = testGroup "UI" dummyHttpState <- newHttpState dummyNetworkStatusState <- newNetworkStatusState dummyAnimationState <- newAnimationState + dummyPlatformSignInState <- newPlatformSignInState let dummyUserState = UserState { userPermissionState = dummyPermState , userSecureStorageState = dummySecureStorageState @@ -172,6 +174,8 @@ uiTests = testGroup "UI" , userHttpState = dummyHttpState , userNetworkStatusState = dummyNetworkStatusState , userAnimationState = dummyAnimationState + , userPlatformSignInState = dummyPlatformSignInState + , userRequestRedraw = pure () } app <- testApp widget <- maView app dummyUserState