GitOps Promoter: promoting environment branches with commit statuses
GitOps Environment Promotion tool that lets you focus on the "what," not the "how"
At a glance
- What is it?
- GitOps Promoter moves configuration between environment branches by treating promotion as a series of commit statuses rather than as pipeline steps, so a release is gated by the checks attached to a commit. It is built for Kubernetes teams that already keep their environment config in Git, and it is still marked experimental with an alpha custom resource API.
- Who is it for?
- GitOps Promoter suits a team that already stores environment configuration in Git and wants promotion to be decided by commit statuses on a pull request, and it does not suit a team that wants a one command deploy or a policy engine of its own, since the project supplies promotion gates rather than deployment logic.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Promotion as a chain of commit statuses instead of pipeline steps
GitOps Promoter exists to move a configuration change from one environment to the next, and the design choice that defines it is where the decision lives. Instead of a pipeline that knows the order of environments and mutates branches on its own, this project expresses the environment order as a Kubernetes custom resource and expresses the approval of each step as a commit status attached to a commit. The README describes this as focusing on the what rather than the how, and it points to a talk titled "Space Age GitOps: The Rise of the Humble Pull Request" for the reasoning behind the idea.
The audience is therefore narrow and clear: teams running a GitOps setup on Kubernetes, where configuration for each environment already lives on its own branch, and where a pull request is the natural unit of change. The README lists a drift-free promotion process, a promotion gating system, integration with git and SCM tooling, and no fragile automated changes to user facing files among the key features. That last point is the design centre. The tool does not rewrite the files an application consumes; it opens and updates pull requests and reads status back, which keeps the environment branches the single source of truth.
The PromotionStrategy resource encodes branch order and gates
Everything the project needs to run a promotion is expressed in one custom resource, and the example in the README shows the whole shape. The first document defines the strategy, the repository it operates on, the order in which environments are traversed, and the statuses that block or allow each step.
apiVersion: promoter.argoproj.io/v1alpha1
kind: PromotionStrategy
metadata:
name: example-promotion-strategy
spec:
gitRepositoryRef:
name: example-git-repo
orderCommitStatusRef:
group: promoter.argoproj.io
kind: DependentsSuccessfulCommitStatus
name: example-promotion-strategy
activeCommitStatuses:
- key: argocd-app-health
proposedCommitStatuses:
- key: security-scan
environments:
- branch: environment/dev
- branch: environment/test
- branch: environment/prodThree fields carry most of the meaning. The environments list is an ordered list of branches, and the order in that list is the promotion order. The orderCommitStatusRef points at a second custom resource, a DependentsSuccessfulCommitStatus, which is what tracks whether a step can proceed once the dependent environments have caught up. The gitRepositoryRef names the repository where the pull requests are opened.
Active and proposed statuses separate the running version from the candidate
The gating vocabulary is the part worth understanding before writing any configuration. Each environment and the strategy itself carry two lists of status keys. Active statuses describe the checks that must be healthy for the change currently running in that environment. Proposed statuses describe the checks that must pass for the candidate change to be allowed to move forward. The names come from the commit status API: a status has a key, a state and a context, and the project uses the key as the identifier of a check that the CI system already reports.
The example makes the split concrete. At the strategy level the active key is argocd-app-health and the proposed key is security-scan, so the running version is watched for app health while the candidate is watched for a security scan result. The production environment then narrows and extends the rules for itself, since the same document adds performance-test as an active key and deployment-freeze as a proposed key, and it sets autoMerge to false so that promotion into production waits for a human instead of merging on its own.
autoMerge: false
activeCommitStatuses:
- key: performance-test
proposedCommitStatuses:
- key: deployment-freeze
---
apiVersion: promoter.argoproj.io/v1alpha1
kind: DependentsSuccessfulCommitStatus
metadata:
name: example-promotion-strategy
spec:
key: dependents-successful
promotionStrategyRef:
name: example-promotion-strategyThe consequence for a user is that the key names have to line up with what the CI system actually reports. Nothing in the resource declares where those statuses come from or how to run the check.
Building the binary and the dashboard from the repository itself
The README does not contain a copy and paste install section. It states that the project is currently experimental, asks readers to use it with caution, and points at the getting started page on the documentation site at gitops-promoter.readthedocs.io for setup instructions. The repository itself is where the build recipe lives, and the Dockerfile shows that the artifact is not a single Go binary but a binary with a web dashboard embedded in it.
The build runs in stages. The first stage builds the dashboard from the ui directory with Node, and the second stage compiles the Go code and copies the static files into the tree before embedding them.
FROM golang:1.27.2@sha256:820153096fda4de6ac1b7194d12e416b7dd8f4e9a33d17e0345b111b945162d8 AS builder
ARG TARGETOS
ARG TARGETARCH
WORKDIR /workspace
COPY go.mod go.mod
COPY go.sum go.sum
RUN go mod downloadThe Go side of the project declares a language floor and a Kubernetes dependency set, and the module path is what you would use to import the API types.
module github.com/argoproj-labs/gitops-promoter
go 1.27.0For a packaged install, the README carries a badge for a Helm chart published to Artifact Hub, and the Makefile names the container image that the build pushes, quay.io/argoprojlabs/gitops-promoter, with the tag taken from the current git tag when the tree is clean and otherwise falling back to latest.
A Go control plane with a Node dashboard and an embedded web server
The repository layout shows what the running system is made of. The api, applyconfiguration, cmd and internal directories are the standard shape of a Kubernetes controller project, and the dependency list in go.mod pulls in the Kubernetes API and apiextensions packages, a cobra command line interface, the gin web framework, the Prometheus client library, and both ginkgo and gomega for tests. The module also carries client libraries for GitHub, GitLab, Gitea, Forgejo, Bitbucket and Azure DevOps, which is a strong hint that the git side of the tool is written against several hosting providers rather than one.
The web side is separate. The ui directory contains a components library and a dashboard application, and the Dockerfile builds the dashboard with vite and copies the result into the internal web static directory so the Go binary can serve it. A webrequestsimulator directory sits at the top level next to the test directory, and the .mockery.yaml file indicates generated mocks are part of the test setup. A Tiltfile and a Dockerfile.tilt point at a local development loop.
The practical consequence is that deploying this means deploying a controller that watches the cluster, needs credentials for your git host, and needs permission to open pull requests and write commit statuses. The documentation site is built with mkdocs, and the mkdocs Docker image is pinned in the Makefile for local docs work.
Experimental status, an alpha API and no rollback path
The most important limitation is stated in the README rather than hidden: the project is currently experimental and should be used with caution. That is reinforced by the API version. The custom resource uses apiVersion promoter.argoproj.io/v1alpha1, so the shape of the PromotionStrategy and the DependentsSuccessfulCommitStatus is not frozen and can change without a major version bump. A team that bakes those resources into many clusters should expect to revisit them.
The second limitation concerns failure handling. The README does not document a rollback path, and it does not document what happens to a pull request when a status is never reported, when a branch is protected, or when the git provider rejects the merge. The list of key features mentions no fragile automated changes to user facing files, and the presence of autoMerge set to false on the production environment in the example shows that a human can be put in the loop, but the behaviour of a stalled or conflicting promotion is not spelled out.
The third is about scope. The tool does not deploy anything. It moves configuration between branches and reports status, so a stack that expects a single command to build, verify and ship a release will need the rest of its pipeline around it.
Where this differs from a pipeline that merges branches itself
The alternative to this approach is the common one: a CI job that knows the environment order, merges the change into the next environment branch when the previous environment looks healthy, and repeats until production. The difference in approach is where the policy lives and what the tool is allowed to touch.
A pipeline keeps the policy in the job definition, in shell steps, and it usually pushes to the environment branches itself. GitOps Promoter keeps the policy in a custom resource that lives in the cluster, and it opens pull requests and reads commit statuses rather than writing to the branches directly. That inversion has two practical effects. First, the gate conditions are named data, so a reviewer can read the promotion rules in one manifest instead of in a job graph. Second, because the pull request is the promotion mechanism, the existing protections, reviewers and audit trail of the git provider apply to environment changes as well.
The cost is that this approach depends on the surrounding system already reporting meaningful commit statuses. If the CI setup publishes only a single build status, the gating model has little to work with, and a hand written promotion job would be simpler for the same result. The gating is also only as good as the keys declared, and the resource has no notion of health checks of its own.
Release cadence and what an upgrade actually costs
Maintenance signals are healthy in the short term. The last push was on 2026-10-22, and the recent release list shows v0.45.3 published on 2026-10-15, v0.45.2 on 2026-10-14 and v0.45.1 on 2026-10-14, so the project is shipping tagged versions rather than only commits on the main branch. The default branch is main, and the release configuration is in.goreleaser.yaml and.goreleaser-latest.yaml.
An upgrade is where the details matter. The custom resources are v1alpha1, so a version jump can bring changed fields, and a team running several environments will need to apply the new manifests rather than only replace the container image. The repository includes an upgrade path through renovate.json5, and RENOVATE_SETUP.md documents the bot setup, which means dependency updates arrive as pull requests against the same repository the promoter is promoting configuration for, a detail worth thinking about before pointing both at the same branch.
The licence is Apache-2.0, which permits modification and redistribution with the customary notice and licence text. Nothing in the licence terms changes the practical constraint, which is that the project still describes itself as experimental.
Editorial conclusion
GitOps Promoter suits a team that already stores environment configuration in Git and wants promotion to be decided by commit statuses on a pull request, and it does not suit a team that wants a one command deploy or a policy engine of its own, since the project supplies promotion gates rather than deployment logic. Before adopting it, read the getting started page on the documentation site and confirm that the status keys your CI system already publishes, such as argocd-app-health or security-scan, match the keys you would declare in the PromotionStrategy, and pin a release tag rather than tracking the main branch, since the custom resource API is v1alpha1 and the README calls the project experimental.
Frequently asked questions
What problem does GitOps Promoter solve?
It moves configuration between environment branches for a GitOps setup, and it makes the promotion decision through commit statuses rather than through pipeline steps. It creates pull requests and reads status back instead of writing to the environment branches directly.
How do I install GitOps Promoter?
The README points at the getting started page on the documentation site for setup instructions, and carries a badge for a Helm chart on Artifact Hub. The container image built by the Makefile is quay.io/argoprojlabs/gitops-promoter.
Is GitOps Promoter ready for production use?
The README states that the project is currently experimental and asks users to use it with caution. The custom resource API version is promoter.argoproj.io/v1alpha1, so the resource shape is not frozen.
How do promotion gates work in GitOps Promoter?
A PromotionStrategy lists environments in promotion order, and each level carries activeCommitStatuses and proposedCommitStatuses, which are keys of checks reported as commit statuses on the commit being promoted. In the README example the strategy watches argocd-app-health as active and security-scan as proposed, and the production environment adds performance-test and deployment-freeze.
What does autoMerge false mean in a PromotionStrategy environment?
The production entry in the README example sets autoMerge to false, which keeps the promotion from merging on its own at that step and leaves the merge to a person. Other environments in the same example do not set the field.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/argoproj-labs-gitops-promoter)Was this useful?