Most CI/CD tools stop at "the deploy finished". Ring Promoter moves one exact version through ordered rings, checks the running app reports that version, enforces release gates before anything changes, and rolls back on its own. It does this for Kubernetes apps and for VM apps behind an existing GitHub Actions pipeline, from one Go binary.
One ring at a time, never skipped. Source ring must be healthy. Failed target health rolls back automatically.
"Does the cluster match the manifests in Git?"
Sync, drift detection and self-heal per environment. Moving a version from staging to production is left to you: a PR, an image-updater, or another tool such as Kargo.
"Did the deploy job exit 0?"
Great at build and test. There's no record of what runs in each environment, and no automatic rollback. A green job can leave the old version answering 200 OK.
"Is this exact version healthy here, and is it allowed into the next ring right now?"
Promotion is the main concept. It keeps current version, previous version and full history per app and ring, and stops at the first failure.
| Capability | Ring Promoter | Argo CD | Flux | Kargo | Spinnaker | Octopus | Harness | GH Actions envs |
|---|---|---|---|---|---|---|---|---|
| Promotion model | ||||||||
| Ordered environment promotionVersion moves ring by ring with state and history kept per environment | YesNever skip a ring; current, previous and history per (app, ring) | NoOne app per env; promote by PR | No | YesStages + Freight | YesPipeline stages | YesLifecycles | Yes | PartialPer-job envs, no ledger |
| Kubernetes and VM apps in one control planeDeployer chosen per app | Yeskubectl, K8s Jobs, or dispatching an existing GitHub Actions workflow | NoKubernetes only | NoKubernetes only | NoKubernetes only | Yes | Yes | Yes | Yes |
| Opt-in auto-promote per ringAnd a hard stop before prod | YesConfig cannot enable auto-promote into prod | No | No | Yes | Yes | Yes | Yes | Partial |
| Verification and rollback | ||||||||
| Version-verified health checkEndpoint must report the version just deployed, not just answer 200 | YesJSON field or header; also checks the source ring | NoResource health only | No | PartialCustom AnalysisTemplate | PartialCustom stage | PartialScript step | PartialCustom verify | No |
| Automatic rollback on failed healthTo the previous recorded version | YesRuns detached; a dropped client can't abort it | PartialNeeds Argo Rollouts | PartialNeeds Flagger | PartialVia Rollouts | Yes | PartialScripted | Yes | No |
| Rejects a non-existent version before deployingTypo'd branch, tag or SHA | Yes400 before any dispatch | No | No | YesFreight from warehouse | Partial | YesPackages | Yes | No |
| Release governance (checked before any deploy) | ||||||||
| Maintenance windowsRecurring plus ad hoc | YesOpened inline from the promote dialog | YesSync windows | No | PartialVia Argo CD | YesExecution windows | YesDeployment freezes | YesFreeze windows | NoWait timer only |
| Go/No-Go sign-off for an exact versionA GO for v1 doesn't authorise v2 | YesRecorded with QA status and engineer | NoGit PR review | No | YesManual promotion | YesManual judgment | Yes | Yes | YesRequired reviewers |
| Jira change-request validationCR code checked against issue status and project | Yes | No | No | No | PartialPlugin | PartialPaid tier | Yes | Partial3rd-party action |
| Dashboard metrics as a release gateWith stale-data detection | YesGrafana panel queries; max_age turns stale runs into NO DATA |
No | PartialFlagger | YesAnalysis | YesKayenta | Partial | Yes | No |
| Where Ring Promoter is not the better choice | ||||||||
| Git as source of truth, drift detection and self-heal | NoIts database is the source of truth | Yes | Yes | Yes | No | Partial | Yes | No |
| Canary / blue-green traffic shifting | NoWhole-ring deploys | PartialArgo Rollouts | PartialFlagger | Partial | Yes | Partial | Yes | No |
| SSO and fine-grained RBAC | NoAPI bearer token + prod password | Yes | PartialK8s RBAC | Yes | Yes | Yes | Yes | Yes |
| Operational footprintWhat you have to run | SmallOne Go binary with UI + API; Postgres or in-memory | MediumSeveral components | MediumControllers | LargeArgo CD + Rollouts + Kargo | Large~10 services | MediumServer + SQL, or SaaS | LargeSaaS or heavy self-host | SmallHosted |
Set health_version_field or health_version_header on a ring and every health check must return the exact version just deployed. If the old pods are still answering, the check fails and the ring rolls back.
Maintenance windows, version-specific sign-off, Jira CR codes and Grafana go/no-go are checked first. A failed gate leaves every ring untouched, so you never end up halfway through a release.
Only the Grafana gate can be overridden, and only with a written reason that goes to the job log.Promotions run on a context detached from the HTTP request. A CI runner timeout or a dropped connection can't abort a deploy or the rollback after it.
Postgres advisory locks serialize every operation per app, across replicas.Kubernetes apps deploy with kubectl or a Kubernetes Job. VM apps keep their existing GitHub Actions workflow: Ring Promoter dispatches it per ring, waits for the run, then health-checks the result.
Argo CD, Flux and Kargo only deploy to Kubernetes.A separate production password is required to promote or seed into prod, or to enable auto-promote into it. Rollbacks are exempt so an incident is never blocked. Config can't turn on auto-promote into prod.
Auto-promote into a CR-gated ring fails closed.CI builds; Ring Promoter promotes. A pipeline calls seed or promote, and any non-2xx means the promotion failed, so curl --fail is the whole integration. 422 means it ran, failed and was rolled back.
A nightly E2E suite that quietly stopped running would show its last green result forever. With max_age, an old result reads NO DATA. An unreachable Grafana is shown as advisory, so an observability outage doesn't become a release outage.
Web console (installable as a PWA), an iOS app with a home-screen widget and a Live Activity for running promotions, restart-in-place for secret rotation, and optional AI explanations of failed jobs from a self-hosted Ollama model.
Failure logs stay on your own infrastructure.Verdict: Argo CD is a sync engine. Ring Promoter is a release control plane. If your problem is "what's allowed into prod, and is it really running", Argo CD doesn't answer that. An Argo CD deployer is on the V2 roadmap so the two can run together.
Verdict: If you're fully committed to Argo CD on Kubernetes, look at Kargo. If you have a mixed estate or no GitOps stack yet, Ring Promoter gets you there with far less to run.
Verdict: Spinnaker suits large platform teams who can staff it. Ring Promoter gives most teams the release safety they need without that running cost.
Verdict: Octopus lifecycles and Harness pipelines are the closest in concept. Ring Promoter offers the same ring discipline without the platform lock-in or the bill.
Verdict: Not a replacement. CI produces the version; Ring Promoter moves it. Your deploy workflow becomes one of Ring Promoter's deployers.
Saying "better than Argo CD" only holds up if we say where it isn't. These are the gaps a technical buyer will find in the first hour.
Access is an API bearer token plus a production password. Teams that need per-user roles and audit by identity should put it behind an auth proxy for now.
A ring is deployed as a whole. For canary or blue/green inside a ring, pair it with Argo Rollouts or Flagger.
Ring state lives in Postgres, not Git. You get a clear history per ring, but not drift detection or self-heal.
Deployers today: kubectl, Kubernetes Jobs and GitHub Actions. Argo CD and more CI adapters are planned for V2.
Argo CD keeps clusters in sync with Git. Ring Promoter decides what reaches production. It moves one exact version through int, test, acc and prod; checks that each ring is really running that version; enforces change windows, sign-offs, Jira CRs and Grafana gates before anything changes; and rolls back by itself when health fails. It handles Kubernetes and VM apps from one small binary.