{"id":27061168,"url":"https://github.com/c2pc/config-migrate","last_synced_at":"2026-03-05T06:00:33.687Z","repository":{"id":283904325,"uuid":"953179540","full_name":"c2pc/config-migrate","owner":"c2pc","description":"config-migrate is a plugin for golang-migrate that enables versioned migrations for configuration files like YAML and JSON.","archived":false,"fork":false,"pushed_at":"2025-04-07T23:01:01.000Z","size":97,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-03T04:46:23.299Z","etag":null,"topics":["config","go","golang","json","migration","yaml"],"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/c2pc.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-22T18:47:34.000Z","updated_at":"2025-04-07T23:01:05.000Z","dependencies_parsed_at":"2025-06-02T17:22:34.541Z","dependency_job_id":null,"html_url":"https://github.com/c2pc/config-migrate","commit_stats":null,"previous_names":["c2pc/golang-file-migrate","c2pc/config-migrate"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/c2pc/config-migrate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c2pc%2Fconfig-migrate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c2pc%2Fconfig-migrate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c2pc%2Fconfig-migrate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c2pc%2Fconfig-migrate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/c2pc","download_url":"https://codeload.github.com/c2pc/config-migrate/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c2pc%2Fconfig-migrate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30111779,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T03:40:26.266Z","status":"ssl_error","status_checked_at":"2026-03-05T03:39:15.902Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["config","go","golang","json","migration","yaml"],"created_at":"2025-04-05T14:19:43.247Z","updated_at":"2026-03-05T06:00:33.662Z","avatar_url":"https://github.com/c2pc.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Config-Migrate\n\n`config-migrate` is a plugin for [golang-migrate](https://github.com/golang-migrate/migrate) that enables versioned migrations for configuration files like YAML and JSON.\n\n## Configs\n\nConfig drivers apply migrations to configuration files instead of traditional databases.  \n[Want to add a new config driver?](driver/driver.go)\n\nCurrently supported config drivers:\n\n* [JSON](driver/json)\n* [YAML](driver/yaml)\n\n## Why use `config-migrate`?\n\nThis is useful when:\n\n- You want to apply versioned updates to your application configs.\n- You need a reproducible and auditable history of config changes.\n- You want to manage infrastructure or system configs as part of CI/CD.\n\n## Features\n\n* Seamless integration with [`golang-migrate`](https://github.com/golang-migrate/migrate)\n* **Migration scenarios**: rename keys, move paths, `_deprecated` (path→key), `_replace` (force new value), `_deprecated_expand` (array of scalars→array of objects), `_deprecated_collapse` (array of objects→array of scalars). See [docs/MIGRATION_SCENARIOS.md](docs/MIGRATION_SCENARIOS.md) for all scenarios and production tips.\n* File-based locking to prevent concurrent writes\n* Config merging with support for version tracking\n* Supports `version`, `force`, and `drop` commands\n* Graceful file handling using `io.Reader` / `io.Writer`\n* Thread-safe with `sync.Mutex`\n* Built-in support for YAML and JSON config formats\n\n## Getting Started\n\n### Install\n\nMake sure you have Go 1.18+ and Go modules enabled.\n\n```bash\ngo get github.com/c2pc/config-migrate\n```\n\n📚 __[Go Documentation](https://pkg.go.dev/github.com/golang-migrate/migrate/v4)__\n\n### Basic usage with config file:\n\n```go\nimport (\n    \"github.com/golang-migrate/migrate/v4\"\n    _ \"github.com/c2pc/config-migrate/driver/json\"\n    _ \"github.com/golang-migrate/migrate/v4/source/github\"\n)\n\nfunc main() {\n    m, err := migrate.New(\n        \"github://username:token@your-repo/json-migrations\",\n        \"json://./config.json\")\n    if err != nil {\n        panic(err)\n    }\n\n    // Apply the next 2 migration steps\n    m.Steps(2)\n}\n```\n\n### Advanced usage with an existing config client:\n\n```go\nimport (\n    \"github.com/golang-migrate/migrate/v4\"\n    \"github.com/c2pc/config-migrate/driver/yaml\"\n    \"github.com/c2pc/config-migrate/config\"\n    _ \"github.com/golang-migrate/migrate/v4/source/file\"\n)\n\nfunc main() {\n    driver := yaml.New(driver.Settings{\n        Path: \"config.yml\",\n        Perm: 0777,\n    })\n\n    m, err := migrate.NewWithDatabaseInstance(\n        \"file://driver/migrations\",\n        \"yaml\", driver)\n    if err != nil {\n        panic(err)\n    }\n\n    m.Up()\n}\n```\n\n## Dynamic Replacers\n\nYou can use dynamic placeholders in your config files and define how they should be replaced at runtime using `replacer`.\n\n### Built-in Example: Random\n\nThe following example registers a replacer that replaces `___random___` with random string:\n\n```go\npackage random\n\nimport (\n\t\"crypto/rand\"\n\n\t\"github.com/c2pc/config-migrate/replacer\"\n)\n\nconst letters = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"\n\nfunc init() {\n\treplacer.Register(\"___random___\", randomReplacer(16))\n}\n\nfunc randomReplacer(n int) func() string {\n\treturn func() string {\n\t\tbytes := make([]byte, n)\n\t\t_, err := rand.Read(bytes)\n\t\tif err != nil {\n\t\t\treturn \"\"\n\t\t}\n\n\t\tfor i, b := range bytes {\n\t\t\tbytes[i] = letters[b%byte(len(letters))]\n\t\t}\n\n\t\treturn string(bytes)\n\t}\n}\n\n```\n\n### Writing Your Own Replacers\n\nYou can create and register your own replacers by calling `replacer.Register`:\n\n```go\npackage main\n\nimport (\n    \"github.com/c2pc/config-migrate/replacer\"\n)\n\nfunc init() {\n    replacer.Register(\"___my_placeholder___\", func() string {\n        return \"dynamic-value\"\n    })\n}\n```\n\nThese placeholders will be replaced automatically when configs are processed during migrations.\n\n### When to Use Replacers\n\nUse replacers when you want to inject dynamic values (like IPs, ports, timestamps, environment info) into your config files at the time of applying a migration.\n\n\n## Comments\n\nyou can enable comment replacer in settings `UnableToReplaceComments: true`\n```go\npackage main\n\nimport (\n\t\"embed\"\n\t\"errors\"\n\n\t\"github.com/c2pc/config-migrate/driver\"\n\t\"github.com/c2pc/config-migrate/driver/yaml\"\n\t\"github.com/golang-migrate/migrate/v4\"\n\t\"github.com/golang-migrate/migrate/v4/source/iofs\"\n)\n\n//go:embed migrations/*.yml\nvar fs embed.FS\n\nfunc runMigration(path string) error {\n\t//You can set a comment suffix\n\tdriver.CommentSuffix = \"___comment___\"\n\t\n\t//Enable to replace comments\n\tyamlMigr := yaml.New(driver.Settings{\n\t\tPath:                    path,\n\t\tPerm:                    0777,\n\t\tUnableToReplaceComments: true,\n\t})\n\n\t//Using iofs as a source\n\td, err := iofs.New(fs, \"migrations\")\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//Create yaml migration\n\tm, err := migrate.NewWithInstance(\"iofs\", d, \"yaml\", yamlMigr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t//Run migrations\n\tif err := m.Up(); errors.Is(err, migrate.ErrNoChange) {\n\t\treturn nil\n\t} else if err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n```\n\n\n### YAML\nYou can add comments to your parameters. Add suffix `______` to parameter name\nSet empty comment `host______:` to add `\\n` to file\n```yaml\nhttp______:\nhttp_______: HTTP server configuration1\nhttp________: HTTP server configuration2\nhttp:\n  host______:\n  host_______: The IP address the server will bind to\n  host: ___ip_address___\n  port______:\n  port_______: The port the server will listen on\n  port: 8052\n```\n\nAs a result we get\n```yaml\n\n# HTTP server configuration1\n# HTTP server configuration2\nhttp:\n\n  # The IP address the server will bind to\n  host: ___ip_address___\n\n  # The port the server will listen on\n  port: 8052\n```\n\n### JSON\nYou can add comments to your parameters. Add suffix `______` to parameter name.\nSet empty comment `\"http______\": \"\"` to add `\\n` to file\n```json\n{\n  \"http______\": \"\",\n  \"http_______\": \"HTTP server configuration\",\n  \"http________\": \"HTTP server configuration1\",\n  \"http_________\": \"HTTP server configuration2\",\n  \"http\": {\n    \"host______\": \"\",\n    \"host_______\": \"The IP address the server will bind to\",\n    \"host\": \"___ip_address___\",\n\n    \"port______\": \"\",\n    \"port_______\": \"The port the server will listen on\",\n    \"port\": 8052\n  }\n}\n```\n\nAs a result we get\n```json\n{\n  \n  \"____http\": \"HTTP server configuration\",\n  \"____http_\": \"HTTP server configuration1\",\n  \"____http__\": \"HTTP server configuration2\",\n  \"http\": {\n    \n    \"____host\": \"The IP address the server will bind to\",\n    \"host\": \"___ip_address___\",\n\n    \"____port\": \"The port the server will listen on\",\n    \"port\": 8052\n  }\n}\n```\n\n\n### Examples\n\n* [JSON](driver/json/examples/migrations) - JSON migrations with replacers and comments\n* [YAML](driver/yaml/examples/migrations) - YAML migrations with replacers and comments\n* [EXAMPLE](example) - Example application with YAML migrations\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc2pc%2Fconfig-migrate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fc2pc%2Fconfig-migrate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc2pc%2Fconfig-migrate/lists"}