{"id":13852621,"url":"https://github.com/layervault/divergence","last_synced_at":"2026-01-11T14:04:07.311Z","repository":{"id":4877953,"uuid":"6033194","full_name":"layervault/divergence","owner":"layervault","description":"A HTTP proxy that lets you map subdomains to git branches for site testing","archived":false,"fork":false,"pushed_at":"2013-03-13T16:26:40.000Z","size":461,"stargazers_count":406,"open_issues_count":12,"forks_count":13,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-07-13T06:40:52.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://cosmos.layervault.com/divergence.html","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"aws/aws-sdk-java","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/layervault.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":"2012-10-01T17:10:30.000Z","updated_at":"2025-03-15T03:21:55.000Z","dependencies_parsed_at":"2022-09-01T08:51:21.699Z","dependency_job_id":null,"html_url":"https://github.com/layervault/divergence","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/layervault/divergence","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/layervault%2Fdivergence","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/layervault%2Fdivergence/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/layervault%2Fdivergence/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/layervault%2Fdivergence/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/layervault","download_url":"https://codeload.github.com/layervault/divergence/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/layervault%2Fdivergence/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28306985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T11:18:18.743Z","status":"ssl_error","status_checked_at":"2026-01-11T11:07:56.842Z","response_time":60,"last_error":"SSL_read: 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":[],"created_at":"2024-08-04T22:01:29.019Z","updated_at":"2026-01-11T14:04:07.288Z","avatar_url":"https://github.com/layervault.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Divergence\n\nMap subdomains to git branches for switching live codebases on the fly. It's a Rack application that acts as a HTTP proxy between you and your web application for rapid testing.\n\n## Installation\n\nFirst, you will need to install the gem:\n\n```\ngem install divergence\n```\n\nThen, since divergence is a rackup application, you will need to initialize it somewhere by running:\n\n```\ndivergence init\n```\n\nThis copies all of the necessary files into the current folder for you.\n\n### DNS\n\nYou have to do this manually for now. Hopefully in the future, Divergence will be able to automatically handle the DNS setup. All you need to do is create an A record with a wildcard subdomain that points to your testing server IP.\n\n## Config\n\nAll configuration happens in `config/config.rb`. You must set the git repository root and the application root before using divergence.\n\nYou will probably want divergence to take over port 80 on your testing server, so you may have to update the forwarding host/port. Note, this is the address where your actual web application can be reached.\n\nA sample config could look like this:\n\n``` ruby\nDivergence::Application.configure do |config|\n  config.git_path = \"/path/to/git_root\"\n  config.app_path = \"/path/to/app_root\"\n  config.cache_path = \"/path/to/cache_root\"\n\n  config.forward_host = 'localhost'\n  config.forward_port = 80\n\n  config.callbacks :after_swap do\n    restart_passenger\n  end\n\n  config.callbacks :after_cache, :after_webhook do\n    bundle_install :path =\u003e \"vendor/bundle\"\n  end\n\n  config.callbacks :on_branch_discover do |subdomain|\n    case subdomain\n    when \"release-1\"\n      \"test_branch\"\n    when \"release-2\"\n      \"other_branch\"\n    end\n  end\nend\n```\n\n### Callbacks\n\nDivergence lets you hook into various callbacks throughout the entire process. These are defined in `config/callbacks.rb`. Most callbacks automatically change the current working directory for you in order to make modifications as simple as possible.\n\nThe available callbacks are:\n\n* before_cache\n  * Active dir: git repository\n* after_cache\n  * Active dir: cached folder path\n* before_swap\n  * Active dir: cached folder path\n* after_swap\n  * Active dir: application\n* before_pull\n  * Active dir: git repository\n  * Only executes if a git pull is required\n* after_pull\n  * Active dir: git repository\n  * Only executes if the git pull succeeds\n* on_pull_error\n  * Active dir: git repository\n  * Executes if there is a problem checking out and pulling a branch\n* on_branch_discover\n  * Active dir: git repository\n  * Executes if the subdomain has a dash in the name. The subdomain name is passed to the callback in the options hash.\n  * If the callback returns nil, Divergence will try to auto-detect the branch name, otherwise it will use whatever you return.\n* before_webook\n  * Active dir: git repository\n  * Runs before a branch is updated via webhooks.\n* after_webhook\n  * Active dir: cached folder path\n  * Runs after a webhook update completes\n\nThere are also some built-in helper methods that are available inside callbacks. They are:\n\n* bundle_install\n  * Recommended - after_cache, after_webhook\n  * Options:\n    * :deployment =\u003e boolean\n    * :path =\u003e string\n* restart_passenger\n  * Recommended - after_swap\n\n### Github Service Hook\n\nYou can automatically keep the currently active branch up to date by using a Github service hook. In your repository on Github, go to Admin -\u003e Service Hooks -\u003e WebHook URLs. Add the url:\n\n```\nhttp://divergence.[your domain].com/update\n```\n\nNow, whenever you push code to your repository, divergence will automatically know and will update accordingly.\n\n## Running\n\nTo start divergence, simply run in the divergence directory you initialized:\n\n```\ndivergence start\n```\n\nThis will start up divergence on port 9292 by default. If you'd like divergence to run on a different port, you can specify that as well:\n\n```\ndivergence start --port=88\n```\n\nThere is also a `--dev` flag that will run divergence in the foreground instead of daemonizing it.\n\n### Port 80\n\nOn many systems, running on port 80 requires special permissions. If you try starting divergence, but get the error `TCPServer Error: Permission denied - bind(2)`, then you will need to run divergence with sudo (or as root). If you use RVM to manage multiple Ruby versions, then you can use `rvmsudo` instead.\n\nMake sure, if you're using Git over SSH, that you have your repository's host added to your known hosts file for the root user.\n\n### HTTPS\n\nDivergence currently does not support HTTPS on its own; however, you can still use HTTPS in combination with a load balancer if you enable SSL termination.\n\n### Invalid URL Characters\n\nGit supports a much wider range of characters for branch names than URLs support. To get around this limitation, simply replace any invalid URL character with a `-` and Divergence will find the branch you're looking for automatically.\n\n## TODO\n\n* Handle simultaneous users better\n* Built-in HTTPS support\n* Helpers for more frameworks\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n## Authors\n\n* [Ryan LeFevre](http://meltingice.net) - Project Creator\n\n## License\n\nLicensed under the Apache 2.0 License. See LICENSE for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayervault%2Fdivergence","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flayervault%2Fdivergence","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flayervault%2Fdivergence/lists"}