{"id":20389314,"url":"https://github.com/positiondev/rivet","last_synced_at":"2025-04-12T10:51:51.185Z","repository":{"id":35329004,"uuid":"39591024","full_name":"positiondev/rivet","owner":"positiondev","description":"A database migration library for Haskell","archived":false,"fork":false,"pushed_at":"2017-06-13T15:36:27.000Z","size":12,"stargazers_count":22,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-26T05:41:58.723Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/positiondev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-23T20:34:31.000Z","updated_at":"2022-08-20T02:32:51.000Z","dependencies_parsed_at":"2022-08-04T01:00:12.560Z","dependency_job_id":null,"html_url":"https://github.com/positiondev/rivet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/positiondev%2Frivet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/positiondev%2Frivet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/positiondev%2Frivet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/positiondev%2Frivet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/positiondev","download_url":"https://codeload.github.com/positiondev/rivet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248557844,"owners_count":21124165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T03:17:20.434Z","updated_at":"2025-04-12T10:51:51.158Z","avatar_url":"https://github.com/positiondev.png","language":"Haskell","readme":"# Rivet - a database migration library for Haskell.\n\n## How it works\n\nYou write SQL or haskell DSL database migrations, and they are\ncompiled into a `migrate` binary that knows how to run migrations,\nroll them back, and inspect the state of the database. Since it is a\nbinary, it can be shipped around via whatever deployment mechanism you\nuse, and will be available in your production environment (where it\ncan talk to production databases), if you need that.\n\n## Usage\n\nAll migrations will be Haskell source files in a `migrations`\ndirectory. They will be run in lexicographic order, which means you should\nname them accordingly. The convention I've used in `M2016..._description_of_change`, \nwhere the beginning is a full timestamp. You should create the `migrations` directory,\nand then add a target to your cabal file.\n\n```\nExecutable migrate\n  hs-source-dirs: src migrations\n  main-is: rivet.hs\n  Build-depends: base,\n                 ... -- same as your application\n  default-language: Haskell2010\n```\n\nAn example migration might be:\n\n```haskell\n{-# LANGUAGE OverloadedStrings #-}\nmodule M20141211212630_add_type_to_gift_subscriptions where\n\nimport           Control.Monad\nimport           Database.Rivet.V0\n\nmigrate :: Migration IO ()\nmigrate = do addColumn \"gift_subscriptions\" (ColumnSpec \"type\" \"text\" Nothing (Just \"not null\"))\n             addColumn \"gift_subscriptions\" (ColumnSpec \"country_code\" \"text\" Nothing (Just \"not null\"))\n```\n\nOr\n\n```haskell\n{-# LANGUAGE OverloadedStrings #-}\nmodule M20160521_add_to_addr_index where\n\nimport           Control.Monad\nimport           Database.Rivet.V0\n\nmigrate :: Migration IO ()\nmigrate = sql up down\n\n\nup = \"CREATE INDEX CONCURRENTLY email_archive_to_addr_idx ON email_archive (to_addr);\"\n\ndown = \"DROP INDEX email_archive_to_addr_idx;\"\n```\n\nSee the full (at this point very limited) API in `Database.Rivet.V0`.\n\nThen you should create `migrations/rivet.hs`. Currently, there is\nstill some copying / pasting, in particular, to figure out how to\nconnect to the database. The following will work, first loading\nenvironment variables from a `.env` file if it exists, and then\nlooking for an `env.cfg` file in the `configurator` format where it\nwill find database connection info. You can change this to be however\nyour application manages database connections. The preprocessor line\n(second in file) and the last two lines in the `main` function are\nrequired; everything else could vary.\n\n```haskell\n{-# LANGUAGE OverloadedStrings #-}\n{-# OPTIONS_GHC -F -pgmF rivet-autoimporter #-}\nmodule Main where\n\nimport qualified Configuration.Dotenv\nimport           Control.Monad                     (when)\nimport qualified Data.Configurator                 as C\nimport           Data.Monoid\nimport           Database.Rivet.Adaptor.PostgreSQL\nimport qualified Database.Rivet.Main               as Rivet\nimport           System.Directory                  (doesFileExist)\nimport           System.Environment\n\n\nmain :: IO ()\nmain = do e \u003c- doesFileExist \".env\"\n          when e $ Configuration.Dotenv.loadFile False \".env\"\n          args \u003c- getArgs\n          let (env, mode) =\n               case args of\n                 [env', \"up\"] -\u003e (env', Rivet.MigrateUp)\n                 [env', \"down\"] -\u003e (env', Rivet.MigrateDown)\n                 [env', \"status\"] -\u003e (env', Rivet.MigrateStatus)\n                 _ -\u003e error \"Usage: [executable] [devel|prod|...] [up|down|status]\"\n          conf \u003c- C.load [C.Required (env \u003c\u003e \".cfg\")]\n          host \u003c- C.require conf \"postgresql-simple.host\"\n          port \u003c- C.require conf \"postgresql-simple.port\"\n          user \u003c- C.require conf \"postgresql-simple.user\"\n          pass \u003c- C.require conf \"postgresql-simple.pass\"\n          db \u003c- C.require conf \"postgresql-simple.db\"\n          adaptor \u003c- setup id (ConnectInfo host port user pass db)\n          Rivet.main adaptor mode migrations\n```\n\nOnce you've done that, build your project as normal, and then run the\nproduced `migrate` binary. The main file provided has usage\ninstructions, though if you customize it, obviously these might vary.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpositiondev%2Frivet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpositiondev%2Frivet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpositiondev%2Frivet/lists"}