keiro-migrations 0.17.0.0 → 0.18.0.0
raw patch · 4 files changed
+64/−18 lines, 4 filesdep +unixdep ~ephemeral-pgPVP ok
version bump matches the API change (PVP)
Dependencies added: unix
Dependency ranges changed: ephemeral-pg
API changes (from Hackage documentation)
Files
- CHANGELOG.md +11/−0
- keiro-migrations.cabal +5/−3
- test-legacy/Main.hs +20/−10
- test/Main.hs +28/−5
CHANGELOG.md view
@@ -6,6 +6,17 @@ ## [Unreleased] +## 0.18.0.0 — 2026-09-20+++### Other Changes++- Both test suites require `ephemeral-pg >=0.3.1 && <0.4` and start their+ clusters under a stable per-user temporary root. The legacy suite uses+ `withCachedConfig` in place of its hand-rolled `startCached`/`finally`+ bracket. No migration payload changed, so no recorded checksum moves and no+ ledger fixup is required.+ ## 0.17.0.0 — 2026-09-17 ### Other Changes
keiro-migrations.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: keiro-migrations-version: 0.17.0.0+version: 0.18.0.0 synopsis: Schema migrations for keiro description: Embedded PostgreSQL schema migrations and a migration runner for the Keiro@@ -410,7 +410,7 @@ bytestring >=0.11 && <0.13, containers >=0.6 && <0.8, directory >=1.3 && <1.4,- ephemeral-pg >=0.2 && <0.3,+ ephemeral-pg >=0.3.1 && <0.4, filepath >=1.4 && <1.6, hasql >=1.10 && <1.11, hspec >=2.10 && <2.12,@@ -420,6 +420,7 @@ pg-migrate-import-codd ^>=1.1.0.0, pg-migrate-test-support ^>=1.1.0.0, text >=2.0 && <2.2,+ unix >=2.8 && <2.9, test-suite keiro-migrations-legacy-test import: common@@ -443,7 +444,7 @@ containers, contravariant-extras, directory,- ephemeral-pg >=0.2,+ ephemeral-pg >=0.3.1 && <0.4, filepath, generic-lens >=2.2 && <2.4, hasql >=1.10 && <1.11,@@ -456,4 +457,5 @@ temporary, text >=2.0 && <2.2, time >=1.12 && <1.15,+ unix >=2.8 && <2.9, vector >=0.13 && <0.14,
test-legacy/Main.hs view
@@ -9,16 +9,17 @@ import Codd.Types (ConnectionString, SchemaAlgo (..), SchemaSelection (..), SqlSchema (..), TxnIsolationLvl (..), singleTryPolicy) import Contravariant.Extras (contrazip3) import Control.Concurrent.Async (concurrently)-import Control.Exception (finally) import Control.Monad (filterM) import Data.Attoparsec.Text (endOfInput, parseOnly) import Data.Int (Int32) import Data.List (isSuffixOf, sort)+import Data.Monoid (Last (..)) import Data.Text (Text) import Data.Text qualified as T import Data.Text.IO qualified as TIO import Data.Time (UTCTime (..), fromGregorian, secondsToDiffTime) import EphemeralPg qualified as Pg+import EphemeralPg.Config qualified as Pg.Config import Hasql.Connection.Settings qualified as Conn import Hasql.Decoders qualified as D import Hasql.Encoders qualified as E@@ -40,27 +41,36 @@ verifySchema, ) import Keiro.Migrations.New (migrationFileName, migrationSlug, newMigrationFile)-import System.Directory (doesDirectoryExist, doesFileExist, listDirectory)+import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, listDirectory) import System.FilePath (takeFileName) import System.IO.Temp (withSystemTempDirectory)+import System.Posix.User (getEffectiveUserID) import Test.Hspec -- | Pin the ephemeral PostgreSQL superuser to the fixed name @keiro@ so the -- captured snapshot identity (roles, database owner, per-object owners) is -- deterministic across machines and CI rather than the local OS username. This is -- the portability fix for the strict drift gate.-keiroPgConfig :: Pg.Config-keiroPgConfig = Pg.defaultConfig {Pg.user = "keiro"}+keiroPgConfig :: IO Pg.Config+keiroPgConfig = withStableRoot Pg.defaultConfig {Pg.Config.user = "keiro"} +-- | Give @config@ a stable, per-user temporary root, so ephemeral-pg's startup+-- sweep reclaims clusters abandoned by earlier killed runs instead of searching a+-- per-session @$TMPDIR@. Must match the root in @Keiro.Test.Postgres@+-- (keiro-test-support) so every Keiro suite shares it.+withStableRoot :: Pg.Config -> IO Pg.Config+withStableRoot config = do+ uid <- getEffectiveUserID+ let root = "/tmp/ephpg-keiro-" <> show uid+ createDirectoryIfMissing True root+ pure config {Pg.temporaryRoot = Last (Just root)}+ -- | Start a cached ephemeral server whose PostgreSQL superuser is the fixed--- name @keiro@. Mirrors 'Pg.withCached' but pins the user; 'Pg.withCachedConfig'--- is not exported, so we use 'Pg.startCached' + 'finally'.+-- name @keiro@. Mirrors 'Pg.withCached' but pins the user. withKeiroPg :: (Pg.Database -> IO a) -> IO (Either Pg.StartError a) withKeiroPg action = do- started <- Pg.startCached keiroPgConfig Pg.defaultCacheConfig- case started of- Left err -> pure (Left err)- Right db -> Right <$> (action db `finally` Pg.stop db)+ config <- keiroPgConfig+ Pg.withCachedConfig config Pg.defaultCacheConfig action main :: IO () main =
test/Main.hs view
@@ -14,6 +14,7 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.List.NonEmpty qualified as NonEmpty import Data.Map.Strict qualified as Map+import Data.Monoid (Last (..)) import Data.Set qualified as Set import Data.Text (Text) import Data.Text qualified as Text@@ -29,8 +30,9 @@ planDescription, ) import Database.PostgreSQL.Migrate.Internal qualified as Migrate.Internal-import Database.PostgreSQL.Migrate.Test (withMigratedDatabase)+import Database.PostgreSQL.Migrate.Test (MigratedDatabaseError, withMigratedDatabaseConfig) import EphemeralPg qualified as Pg+import EphemeralPg.Config qualified as Pg.Config import Hasql.Connection qualified as Connection import Hasql.Connection.Settings qualified as Settings import Hasql.Decoders qualified as Decoders@@ -46,9 +48,10 @@ import Kiroku.Store.Migrations.History.Codd qualified as Kiroku.Codd import Lint import Numeric qualified-import System.Directory (doesDirectoryExist, doesFileExist, listDirectory)+import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, listDirectory) import System.Environment (lookupEnv) import System.FilePath (takeExtension, (</>))+import System.Posix.User (getEffectiveUserID) import Test.Hspec main :: IO ()@@ -1347,12 +1350,32 @@ importOutcomes :: HistoryImportReport -> [HistoryImportOutcome] importOutcomes HistoryImportReport {importResults} = importOutcome <$> toList importResults -keiroPgConfig :: Pg.Config-keiroPgConfig = Pg.defaultConfig {Pg.user = "keiro"}+-- | Give @config@ a stable, per-user temporary root, so ephemeral-pg's startup+-- sweep reclaims clusters abandoned by earlier killed runs instead of searching a+-- per-session @$TMPDIR@. Must match the root in @Keiro.Test.Postgres@+-- (keiro-test-support) so every Keiro suite shares it.+withStableRoot :: Pg.Config -> IO Pg.Config+withStableRoot config = do+ uid <- getEffectiveUserID+ let root = "/tmp/ephpg-keiro-" <> show uid+ createDirectoryIfMissing True root+ pure config {Pg.temporaryRoot = Last (Just root)} +keiroPgConfig :: IO Pg.Config+keiroPgConfig = withStableRoot Pg.defaultConfig {Pg.Config.user = "keiro"}++withMigratedDatabase ::+ MigrationPlan ->+ (Connection.Connection -> IO value) ->+ IO (Either MigratedDatabaseError value)+withMigratedDatabase plan callback = do+ config <- withStableRoot Pg.defaultConfig+ withMigratedDatabaseConfig config defaultRunOptions plan callback+ withKeiroPg :: (Pg.Database -> IO ()) -> IO () withKeiroPg action = do- started <- Pg.startCached keiroPgConfig Pg.defaultCacheConfig+ config <- keiroPgConfig+ started <- Pg.startCached config Pg.defaultCacheConfig case started of Left startError -> expectationFailure (show startError) Right database -> action database `finally` Pg.stop database