{"id":13412049,"url":"https://github.com/lopezator/migrator","last_synced_at":"2026-01-29T04:18:19.754Z","repository":{"id":35003004,"uuid":"169056015","full_name":"lopezator/migrator","owner":"lopezator","description":"Dead simple Go database migration library.","archived":false,"fork":false,"pushed_at":"2024-03-14T21:52:43.000Z","size":730,"stargazers_count":168,"open_issues_count":9,"forks_count":18,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-07-31T20:49:43.537Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lopezator.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-04T09:40:01.000Z","updated_at":"2024-07-11T02:39:54.000Z","dependencies_parsed_at":"2022-08-08T03:16:11.597Z","dependency_job_id":"0e60ec50-662b-43cf-8cc0-a7d7aefcfc92","html_url":"https://github.com/lopezator/migrator","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/lopezator/migrator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lopezator%2Fmigrator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lopezator%2Fmigrator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lopezator%2Fmigrator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lopezator%2Fmigrator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lopezator","download_url":"https://codeload.github.com/lopezator/migrator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lopezator%2Fmigrator/sbom","scorecard":{"id":598911,"data":{"date":"2025-08-11","repo":{"name":"github.com/lopezator/migrator","commit":"09f72601e8a29b17e0439d9b3142609bc421fe53"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Code-Review","score":2,"reason":"Found 6/27 approved changesets -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/lopezator/migrator/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/lopezator/migrator/main.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile.build:1: pin your Docker image by updating golang:1.17 to golang:1.17@sha256:87262e4a4c7db56158a80a18fefdc4fee5accc41b59cde821e691d05541bbb18","Warn: downloadThenRun not pinned by hash: Dockerfile.build:8","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   1 downloadThenRun dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2024-2606 / GHSA-7jwh-3vrq-q3m8 / GHSA-mrww-27vc-gghv","Warn: Project is vulnerable to: GO-2024-2605 / GHSA-m7wr-2xf7-cm9p","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T23:51:44.191Z","repository_id":35003004,"created_at":"2025-08-20T23:51:44.191Z","updated_at":"2025-08-20T23:51:44.191Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28862142,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T22:56:21.783Z","status":"online","status_checked_at":"2026-01-29T02:00:06.714Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-07-30T20:01:20.506Z","updated_at":"2026-01-29T04:18:19.738Z","avatar_url":"https://github.com/lopezator.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/lopezator/migrator/blob/master/logo.png\" width=\"360\"\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://cloud.drone.io/lopezator/migrator\"\u003e\u003cimg src=\"https://cloud.drone.io/api/badges/lopezator/migrator/status.svg?branch=master\" alt=\"DroneCI\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/lopezator/migrator\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/lopezator/migrator\" alt=\"Go Report Card\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/lopezator/migrator\"\u003e\u003cimg src=\"https://codecov.io/gh/lopezator/migrator/branch/master/graph/badge.svg\" alt=\"codecov\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/avelino/awesome-go#database\"\u003e\u003cimg src=\"https://awesome.re/mentioned-badge.svg\" alt=\"DroneCI\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://godoc.org/github.com/lopezator/migrator\"\u003e\u003cimg src=\"https://godoc.org/github.com/lopezator/migrator/go?status.svg\" alt=\"GoDoc\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://opensource.org/licenses/Apache-2.0\"\u003e\u003cimg src=\"https://img.shields.io/badge/License-Apache%202.0-blue.svg\" alt=\"License: Apache 2.0\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n# migrator\n\nDead simple Go database migration library.\n\n# Features\n\n* Simple code\n* Usage as a library, embeddable and extensible on your behalf\n* Support of any database supported by `database/sql`\n* Go code migrations, either transactional or transaction-less, using `*sql.Tx` (`migrator.Migration`) or `*sql.DB` (`migrator.MigrationNoTx`)\n* No need to use `//go:embed` or others, since all migrations are just Go code\n\n# Compatibility\n\nAlthough any database supported by [database/sql](https://golang.org/pkg/database/sql/) and one of its recommended drivers [SQLDrivers](https://github.com/golang/go/wiki/SQLDrivers) should work OK, at the moment only `PostgreSQL` and `MySQL` are being explicitly tested.\n\nIf you find any issues with any of the databases included under the umbrella of `database/sql`, feel free to [contribute](#Contribute) by opening an issue or sending a pull request.\n\n# Usage\n\nThe following example assumes:\n\n- A working `postgres` DB conn on localhost, with a user named `postgres`, empty password, and db named `foo`\n\nCustomize this to your needs by changing the driver and/or connection settings.\n\n### QuickStart:\n\n```go\npackage main\n\nimport (\n\t\"database/sql\"\n\t\"log\"\n\n\t_ \"github.com/jackc/pgx/v4/stdlib\" // postgres driver\n\t\"github.com/lopezator/migrator\"\n)\n\nfunc main() {\n    // Configure migrations\n    m, err := migrator.New(\n        migrator.Migrations(\n            \u0026migrator.Migration{\n                Name: \"Create table foo\",\n                Func: func(tx *sql.Tx) error {\n                    if _, err := tx.Exec(\"CREATE TABLE foo (id INT PRIMARY KEY)\"); err != nil {\n                        return err\n                    }\n                    return nil\n                },\n            },\n        ),\n    )\n    if err != nil {\n        log.Fatal(err)\n    }\n   \n    // Open database connection\n    db, err := sql.Open(\"pgx\", \"postgres://postgres@localhost/foo?sslmode=disable\")\n    if err != nil {\n        log.Fatal(err)\n    }\n    \n    // Migrate up\n    if err := m.Migrate(db); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\nNotes on examples above:\n\n- Migrator creates/manages a table named `migrations` to keep track of the applied versions. However, if you want to customize the table name `migrator.TableName(\"my_migrations\")` can be passed to `migrator.New` function as an additional option. \n\n### Logging\n\nBy default, migrator prints applying/applied migration info to stdout. \nIf that's enough for you, you can skip this section.\n\nIf you need some special formatting or want to use a 3rd party logging library, this could be done by using `WithLogger` option as follows:\n\n```go\nlogger := migrator.WithLogger(migrator.LoggerFunc(func(msg string, args ...interface{}) {\n\t// Your code here \n})))\n```\n\nThen you will only need to pass the logger as an option to `migrator.New`. \n\n### Looking for more examples?\n\nJust examine the [migrator_test.go](migrator_test.go) file.\n\n### But I don't want to write complex migrations in strings! 😥\n\nYou still can use your favorite embedding tool to write your migrations inside `.sql` files and load them into migrator!\n\nI provide a simple example using `//go:embed` on the `Using tx, one embedded query` test here: [migrator_test](https://github.com/lopezator/migrator/blob/master/migrator_test.go)\n\n### Erm... Where are the ID's of the migrations to know their order? 🤔\n\nIn order to avoid problems with different identifiers, ID collisions, etc... the order of the migrations is just the order being passed to the migrator.\n\n### Wait... no down migrations? 😱\n\nAdding the functionality to reverse a migration introduces complexity to the API, the code, and the risk of losing the synchrony between the defined list of migrations and current state of the database. In addition to this, depending on the case, not all the migrations are easily reversible, or they cannot be reversed.\n\nWe also think that it's a good idea to follow an \"append-only\" philosophy when coming to database migrations, so correcting a defective migration comes in the form of adding a new migration instead of reversing it.\n\ne.g. After a `CREATE TABLE foo` we'll simply add a new `DROP TABLE foo` instead of reverting the first migration, so both states are reflected both in the code and the database.  \n\n### Caveats\n\n- The name of the migrations must be SQL-safe for your engine of choice. Avoiding conflicting characters like `'` is recommended, otherwise, you will have to escape them by yourself e.g. `''` for PostgreSQL and `\\'` for MySQL.\n\n# Motivation\n\nWhy another migration library?\n\n* Lightweight dummy implementation with just `database/sql` support. Migrator doesn't need any ORM or other heavy libraries as a dependency. It's just made from a [single file](migrator.go) in less than 200 lines of code!\n* Easily embedabble into your application, no need to install/use a separate binary\n* Supports Go migrations, either transactional or transaction-less\n* Flexible usage\n\n# These are not migrator objectives\n\n* Add support to databases outside `database/sql`\n* Complicate the code/logic to add functionality that could be accomplished easily on userland, like view current version, list of applied versions, etc.\n* Add a bunch of dependencies just to provide a CLI/standalone functionality\n\n# Comparison with other tools\n\n* [rubenv/sql-migrate](https://github.com/rubenv/sql-migrate) doesn't support Go migrations. Sometimes you need Go code to accomplish complex tasks that can't be done using just SQL.\n\n* [Boostport/migration](https://github.com/Boostport/migration) is a nice tool with support for many databases. Migrator code is inspired by its codebase. It supports both Go and SQL migrations. Unfortunately, when using Go migrations you have to write your own logic to retrieve and update version info in the database. Additionally I didn't find a nice way to encapsulate both migration and version logic queries inside the same transaction.\n\n* [golang-migrate/migrate](https://github.com/golang-migrate/migrate) doesn't support Go migrations. Sometimes you need Go code to accomplish complex tasks that couldn't be done using just SQL. Additionally it feels a little heavy for the task.\n\n* [pressly/goose](https://github.com/pressly/goose) supports both Go and SQL migrations. Unfortunately it doesn't support transaction-less Go migrations. Sometimes using transactions is either not possible with the combination of queries you need in a single migration, or others could be very slow and you simply don't need them for that specific case. It's also pretty big, with internals that are difficult to follow. It's crowded with a lot of functionality that could be done in userland pretty fast.\n\n# Contribute\n\nPull requests are welcome, this is an early implementation and work is needed in all areas: docs, examples, tests, ci...\n\nThe easiest way to contribute is by installing [docker](https://docs.docker.com/install/) and [docker-compose](https://docs.docker.com/compose/install/), and ensure you comply with code standards and pass all the tests before submitting a PR by running:\n\n```bash\n$\u003e docker-compose up -d --build\n$\u003e docker-compose exec migrator make prepare\n$\u003e docker-compose exec migrator make sanity-check\n$\u003e docker-compose exec migrator make test\n$\u003e docker-compose down\n```\n\nMake sure you also provide relevant information in your PR as detailed in the [pull request template](https://github.com/lopezator/migrator/blob/master/pull_request_template.md).\n\n## Logo\n\nThe logo was taken from @ashleymcnamara's [gophers repo](https://github.com/ashleymcnamara/gophers). I've just applied slight modifications to it.\n","funding_links":[],"categories":["Go","数据库","Database","数据库  `go语言实现的数据库`","Uncategorized","Data Integration Frameworks","Generators"],"sub_categories":["数据库模式迁移","Database Schema Migration","Advanced Console UIs","标准 CLI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flopezator%2Fmigrator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flopezator%2Fmigrator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flopezator%2Fmigrator/lists"}