{"id":28624286,"url":"https://github.com/commercetools/telefonistka","last_synced_at":"2026-06-23T13:32:49.465Z","repository":{"id":227649116,"uuid":"772036937","full_name":"commercetools/telefonistka","owner":"commercetools","description":"Safe and Controlled GitOps Promotion Across Environments/Failure-Domains","archived":false,"fork":false,"pushed_at":"2026-05-19T16:01:59.000Z","size":1416,"stargazers_count":61,"open_issues_count":12,"forks_count":12,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T00:03:33.785Z","etag":null,"topics":["audit-special-delivery","commercetools-scp"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"wayfair-incubator/telefonistka","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/commercetools.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-03-14T12:18:18.000Z","updated_at":"2026-06-07T08:02:52.000Z","dependencies_parsed_at":"2025-12-16T21:00:06.732Z","dependency_job_id":null,"html_url":"https://github.com/commercetools/telefonistka","commit_stats":null,"previous_names":["commercetools/telefonistka"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/commercetools/telefonistka","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/commercetools%2Ftelefonistka","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/commercetools%2Ftelefonistka/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/commercetools%2Ftelefonistka/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/commercetools%2Ftelefonistka/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/commercetools","download_url":"https://codeload.github.com/commercetools/telefonistka/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/commercetools%2Ftelefonistka/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34691843,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"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":["audit-special-delivery","commercetools-scp"],"created_at":"2025-06-12T07:11:43.301Z","updated_at":"2026-06-23T13:32:49.448Z","avatar_url":"https://github.com/commercetools.png","language":"Go","funding_links":[],"categories":["Configuration Management"],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD033 --\u003e\n\u003cp align=\"center\"\u003e  \u003cimg src=\"https://user-images.githubusercontent.com/1616153/217223509-9aa60a5c-a263-41a7-814d-a1bf2957acf6.png \" width=\"150\"\u003e \u003c/p\u003e\n\n# \u003cp align=\"center\"\u003e Telefonistka\u003c/p\u003e\n\n\u003c!-- markdownlint-enable MD033 --\u003e\n\nTelefonistka is a Github webhook server/Bot that facilitates change promotion across environments/failure domains in Infrastructure as Code(IaC) GitOps repos.\n\nIt assumes the [repeatable part of your infrastucture is modeled in folders](#modeling-environmentsfailure-domains-in-an-iac-gitops-repo)\n\nBased on configuration in the IaC repo, the bot will open pull requests that sync components from \"sourcePaths\" to \"targetPaths\".\n\nProviding reasonably flexible control over what is promoted to where and in what order.\n\nA 10 minutes ArgoCon EU 2023 session describing the project:\n\n[![ArgoCon EU 2023 session](https://img.youtube.com/vi/oiSsSiROj10/0.jpg)](https://www.youtube.com/watch?v=oiSsSiROj10)\n\n## Modeling environments/failure-domains in an IaC GitOps repo\n\nRY is the new DRY!\n\nIn GitOps IaC implementations, different environments(`dev`/`prod`/...) and failure domains(`us-east-1`/`us-west-1`/...) must be represented in distinct files, folders, Git branches or even repositories to allow gradual and controlled rollout of changes across said environments/failure domains.\n\nAt Wayfair's Kubernetes team we choose the \"folders\" approach, more about other choices [here](docs/modeling_environments_in_gitops_repo.md).\n\nSpecifically, we choose the following scheme to represent all the Infrastructure components running in our Kubernetes clusters:\n`clusters`/`[environment]`/`[cloud region]`/`[cluster identifier]`/`[component name]`\n\nfor  example:\n\n```text\nclusters/staging/us-central1/c2/prometheus/\nclusters/staging/us-central1/c2/nginx-ingress/\nclusters/prod/us-central1/c2/prometheus/\nclusters/prod/us-central1/c2/nginx-ingress/\nclusters/prod/europe-west4/c2/prometheus/\nclusters/prod/europe-west4/c2/nginx-ingress/\n```\n\nWhile this approach provides multiple benefits it does mean the user is expected to make changes in multiple files and folders in order to apply a single change to multiple environments/FDs.\n\nManually syncing those files is time consuming, error prone and generally not fun. And in the long run, undesired drift between those environments/FDs is almost guaranteed to accumulate as humans do that thing where they fail to be perfect at what they do.\n\nThis is where Telefonistka comes in.\n\nTelefonistka will automagically create pull requests that \"sync\" our changes to the right folder or folders, enabling the usage of the familiar PR functionality to control promotions while avoiding the toil related to manually syncing directories and checking for environments/FDs drift.\n\n## Notable Features\n\n### IaC stack agnostic (most promotion related features)\n\nTerraform, Helmfile, ArgoCD whatever, as long as environments and sites are modeled as folders and components are copied between environments \"as is\".\n\n### ArgoCD integration\n\nThe ArgoCD integration displays the result of a planned change in a PR comment, allows syncing from a non-default branch, shows application state warnings and more.\n\n![image](https://github.com/user-attachments/assets/c2eb0ce6-8718-4c4a-b7dd-5339f0a0440a)\n\nSee more in the ArgoCD integration documentation [here](docs/argocd.md).\n\n### Unopinionated directory structure\n\nThe [in-repo configuration file](docs/installation.md#repo-configuration) is flexible and even has some regex support.\n\nThe project goal is support any reasonable setup and we'll try to address unsupported setups.\n\n### Multi stage promotion schemes\n\n```text\nlab -\u003e staging -\u003e production\n```\n\nor  \n\n```text\ndev -\u003e production-us-east-1 -\u003e production-us-east-3 -\u003e production-eu-east-1\n```  \n  \nFan out, like:  \n\n```text\nlab -\u003e staging1 --\u003e\n       staging2 --\u003e  production\n       staging3 --\u003e\n```\n\nTelefonistka annotates the PR with the historic \"flow\" of the promotion:\n\n\u003c!-- markdownlint-disable MD033 --\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/1616153/219384172-27b960a8-afd1-42d1-8d5b-4b802134b851.png\"  width=\"50%\" height=\"50%\"\u003e\n\u003c!-- markdownlint-enable MD033 --\u003e\n\n### Control granularity of promotion PRs\n\nAllows separating promotions into a separate PRs per environment/failure domain or group some/all of them.\n\ne.g. \"Sync all dev clusters in one PR but open a dedicated PR for every production cluster\"\n\nAlso allows automatic merging of PRs based on the promotion policy.\n\ne.g. \"Automatically merge PRs that promote to multiple `lab` environments\"\n\n### Optional per-component allow/block override list\n\nAllows overriding the general(per-repo) promotion policy on a per component level.\n\ne.g. \"This component should not be deployed to production\" or \"Promote this only to the us-east-4 region\"\n\n### Drift detection and warning\n\nWarns user on [drift between environment/failure domains](docs/modeling_environments_in_gitops_repo.md#terminology) on open PRs (\"Staging and Production are not synced, these are the differences\")\nThis is how this warning looks in the PR:\n\n\u003c!-- markdownlint-disable MD033 --\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/1616153/219383563-8b833c17-7701-45b6-9471-d937d03142f4.png\"  width=\"50%\" height=\"50%\"\u003e\n\u003c!-- markdownlint-enable MD033 --\u003e\n\n### Artifact version bumping from CLI\n\nIf your IaC repo deploys software you maintain internally you probably want to automate artifact version bumping.\nTelefonistka can automate opening the IaC repo PR for the version change from the  Code repo pipeline:\n\n```shell\ntelefonistka bump-overwrite \\\n    --target-repo Oded-B/telefonistka-example \\\n    --target-file workspace/nginx/values-version.yaml \\\n    --file \u003c(echo -e \"image:\\n  tag: v3.4.9\") \\\n```\n\nIt currently supports full file overwrite, regex and yaml based replacement.\nSee [here](docs/version_bumping.md) for more details\n\n### GitHub Push events fanout/multiplexing\n\nSome GitOps operators can listen for GitHub webhooks to ensure short delays in the reconciliation loop.\n\nBut in some scenarios the number of needed webhooks endpoint exceed the maximum supported by GitHub(think 10 cluster each with in-cluster ArgoCD server and ArgoCD applicationSet controller).\n\nTelefonistka can forward these HTTP requests to multiple endpoint and can even filter or dynamically choose the endpoint URL based on the file changed in the Commit.\n\nThis example configuration includes regex bases endpoint URL generation:\n\n```yaml\nwebhookEndpointRegexs:\n  - expression: \"^workspace/[^/]*/.*\"\n    replacements:\n      - \"https://kube-argocd-c1.service.lab.example.com/api/webhoook\"\n      - \"https://kube-argocd-applicationset-c1.service.lab.example.com/api/webhoook\"\n      - \"https://example.com\"\n  - expression: \"^clusters/([^/]*)/([^/]*)/([^/]*)/.*\"\n    replacements:\n      - \"https://kube-argocd-${3}.${1}.service.{2}.example.com/api/webhoook\"\n      - \"https://kube-argocd-applicationset-${2}.service.${1}.example.com/api/webhoook\"\n\n```\n\nsee [here](docs/webhook_multiplexing.md) for more details\n\n## Installation and Configuration\n\nSee [here](docs/installation.md)\n\n## Observability\n\nSee [here](docs/observability.md)\n\n## Development\n\n### Local Testing\n\nTelefonistka have 3 major methods to interact with the world:\n\n* Receive event webhooks from GitHub\n* Send API calls to GitHub REST and GraphQL APIs(requires network access and credentials)\n* Send API calls to ArgoCD API(requires network access and credentials)\n\nSupporting all those requirements in a local environment might require lots of setup.\nAssuming you have a working lab environment, the easiest way to locally test Telefonistka might be with tools like [mirrord](https://mirrord.dev/) or [telepresence](https://www.telepresence.io/)\n\nA [mirrord.json](mirrord.json) is supplied as reference.\n\nThis is how I compile and trigger mirrord execution\n\n```sh\ngo build . \u0026\u0026 mirrord exec -f mirrord.json ./telefonistka server\n```\n\nAlternatively, you can use `ngrok` or similar services to route webhook to a local instance, but you still need to provide credentials to all outbound API calls.\n\n* use Ngrok ( `ngrok http 8080` ) to expose the local instance\n* See the URLs in ngrok command output.\n* Add a webhook to repo setting (don't forget the `/webhook` path in the URL).\n* Content type needs to be `application/json`, **currently** only PR events are needed\n\n### Building Container Image From Forks\n\nTo publish container images from a forked repo set the `IMAGE_NAME` and `REGISTRY` GitHub Action Repository variables to use GitHub packages.\n`REGISTRY` should be `ghcr.io` and `IMAGE_NAME` should match the repository slug, like so:\nlike so:\n\u003c!-- markdownlint-disable MD033 --\u003e\n\u003cimg width=\"785\" alt=\"image\" src=\"https://github.com/commercetools/telefonistka/assets/1616153/2f7201d6-fdb2-4cbf-8705-d6da7f4f6e80\"\u003e\n\u003c!-- markdownlint-enable MD033 --\u003e\n\n## Roadmap\n\nSee the [open issues](https://github.com/commercetools/telefonistka/issues) for a list of proposed features (and known issues).\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. For detailed contributing guidelines, please see [CONTRIBUTING.md](CONTRIBUTING.md)\n\n## License\n\nDistributed under the MIT License. See [LICENSE](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommercetools%2Ftelefonistka","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcommercetools%2Ftelefonistka","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcommercetools%2Ftelefonistka/lists"}