{"id":17116445,"url":"https://github.com/dakimura/migrent","last_synced_at":"2025-04-13T04:27:54.561Z","repository":{"id":45245141,"uuid":"376754388","full_name":"dakimura/migrent","owner":"dakimura","description":"A data migration tool for ent","archived":false,"fork":false,"pushed_at":"2022-12-21T02:13:59.000Z","size":82,"stargazers_count":17,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-26T21:22:15.449Z","etag":null,"topics":["entity-framework","golang","migration","migration-tool","orm"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dakimura.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-14T08:27:52.000Z","updated_at":"2024-06-21T00:48:23.000Z","dependencies_parsed_at":"2023-01-30T02:30:59.869Z","dependency_job_id":null,"html_url":"https://github.com/dakimura/migrent","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/dakimura%2Fmigrent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dakimura%2Fmigrent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dakimura%2Fmigrent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dakimura%2Fmigrent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dakimura","download_url":"https://codeload.github.com/dakimura/migrent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248662807,"owners_count":21141634,"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":["entity-framework","golang","migration","migration-tool","orm"],"created_at":"2024-10-14T17:48:51.890Z","updated_at":"2025-04-13T04:27:54.530Z","avatar_url":"https://github.com/dakimura.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## migrent - A data migration tool for ent\n\nmigrent is a library to manage data migrations for applications using [ent](https://github.com/ent/ent).\n\nEnt is one of the most popular ORM libraries for Golang, and [automatic schema migration](https://entgo.io/docs/migrate) is already supported.\nHowever, with regard to data migration/incremental migration history management, there is some room for adding more functionality.\nWhen an application using ent needs master data (=data needed to be registered in advance), the users need to have the code to manage the data by themselves because `Upsert` is not yet implemented, \nand it is not possible to \"Up\" and \"Down\" migrations like with\nexisting tools such as [goose](https://github.com/pressly/goose), [sql-migrate](https://github.com/rubenv/sql-migrate),\nand [golang-migrate](https://github.com/golang-migrate/migrate).\n\nmigrent enables the applying and rolling back of data migrations by creating an internal \"migration\" entity in the DB, while\nkeeping the great part of ent, such as type-safety.\n\n## Quick Installation\n\n```console\ngo get github.com/dakimura/migrent\n```\n\n## Usage\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\n\t\"github.com/dakimura/migrent/example\"\n\n\t\"github.com/dakimura/migrent/example/ent\"\n\n\t\"github.com/dakimura/migrent\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n)\n\n// example master data definition \nvar masterData = []ent.User{\n\t{Age: 12, Name: \"Alice\"},\n\t{Age: 24, Name: \"Bob\"},\n\t{Age: 36, Name: \"Carol\"},\n\t{Age: 48, Name: \"David\"},\n\t{Age: 60, Name: \"Eve\"},\n}\n\nfunc main() {\n\tctx := context.Background()\n\n\tdialect := \"mysql\"\n\tdsn := \"user:password@tcp(IPAddress:Port)/dbname?parse=True\"\n\t\n\t// initialize ent client for your DB\n\tuserDBCli, _ := ent.Open(dialect, dsn)\n\t// initialize migrent client (you can use the same dsn).\n\t// because migrent creates an internal entity to manage the migration history\n\t// in the DB, an ent client for it is necessary\n\tcli, _ := migrent.Open(dialect, dsn)\n\n\t// define your migration\n\tmigrations := map[migrent.MigrationName]migrent.Migration{\n\t\t\"20220712_user_data_v1\": example.NewUserMasterDataMigration(masterData, userDBCli.User),\n\t}\n\n\t// ---  execute migration(Up)\n\tcli.Up(ctx, migrations)\n\n\t// --- execute migration(Down)\n\tcli.Down(ctx, migrations)\n}\n\n```\n\nYou need to define what operation you need when `Up` or `Down` is called.\n\n```go\ntype Migration interface {\n\tUp(ctx context.Context) error\n\tDown(ctx context.Context) error\n}\n```\n\n- Each migration doesn't have to be idempotent, but we recommend it to be.\n  If your migration is idempotent, you can update the value of existent records\n  by just changing the values in your data files and change the migration name like \"data_v1\" to \"data_v2\",\n  and run the migration.\n  Because migrent manages whether each migration has already been applied or not by the migration name,\n  the \"data_v2\" migration will be executed and update your existent values.\n\n- Migrations are executed by dictionary order (AtoZ) of migration names, so \"{timestamp}_{name}\" might be a good naming\n  for migrations.\n\nThe following is the simple example of a migration that inserts master data to User entity.\n\n```go\npackage example\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dakimura/migrent/example/ent/user\"\n\n\tent \"github.com/dakimura/migrent/example/ent\"\n)\n\ntype UserMasterDataMigration struct {\n\tData   []ent.User\n\tClient *ent.UserClient\n}\n\nfunc NewUserMasterDataMigration(data []ent.User, client *ent.UserClient,\n) *UserMasterDataMigration {\n\treturn \u0026UserMasterDataMigration{\n\t\tData:   data,\n\t\tClient: client,\n\t}\n}\n\n// Up inserts data to User entity\nfunc (m *UserMasterDataMigration) Up(ctx context.Context) error {\n\tfor _, rec := range m.Data {\n\t\terr := m.Client.Create().SetID(rec.ID).SetAge(rec.Age).SetName(rec.Name).\n\t\t\tOnConflictColumns(user.FieldID).UpdateNewValues().Exec(ctx)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"create User entities: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Down deletes data from User entity\nfunc (m *UserMasterDataMigration) Down(ctx context.Context) error {\n\tusers := make([]uuid.UUID, len(m.Data))\n\tfor i, u := range m.Data {\n\t\tusers[i] = u.ID\n\t}\n\n\t_, err := m.Client.\n\t\tDelete().\n\t\tWhere(user.IDIn(users...)).Exec(ctx)\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"delete User entities: %w\", err)\n\t}\n\n\treturn nil\n}\n```\n\n## License\n\nmigrent is licensed under MIT as found in the [LICENSE file](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdakimura%2Fmigrent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdakimura%2Fmigrent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdakimura%2Fmigrent/lists"}