Docs

Get started

Worked Examples ​

Four step-by-step walkthroughs with real commands and output, from a gated pull request to a hotfix, a release train and a rollback.

Each example follows one change from start to finish. The commands and the output are what Bumpkit prints. Names, versions, SHAs, line numbers and counts are made up.

The examples use a repository called acme/api that already has a v1.4.2 tag. You need the CLI installed and signed in (see Getting Started), or BUMPKIT_API_KEY set in CI.

A pull request through the gate ​

A coding agent opens a pull request that changes billing code. You want two things: a committed secret must always block, and billing changes written by an agent need a named person to approve.

1. Write the policy ​

Add bumpkit.yml to the default branch. The gate reads the policy from the base of the pull request, so the pull request itself can't loosen it. With the Bumpkit GitHub App installed on the repository, Bumpkit reads the file from GitHub itself and ignores any other policy a job sends (see The policy comes from the base).

YAML
gate:
  block_on: [secret, data_loss]
  require_approval:
    - breaking
    - area: [billing]
      when: agent
      approvers: ["sam", "priya"]
  on_error: fail

The bumpkit.yml Reference explains every key.

2. Run the gate on pull requests ​

Install the Bumpkit GitHub App on the repository. It runs the gate on every pull request with the bumpkit.yml on the base branch, and runs it again when someone approves. On another CI, run bumpkit gate --comment in the pipeline instead; see Release Gate.

Make Bumpkit release gate a required check in branch protection.

This example assumes the Bumpkit GitHub App is also installed on the repository, so Bumpkit reads the policy and verifies approvals itself. With the Action alone, each decision also carries a policy_source: client reason that says the policy wasn't verified from the base branch.

3. The first push fails ​

The agent's first commit hard-codes a private key. The job log shows:

Text
BLOCKED: Adds a private key (services/billing/keys.go:3)
Fix the blocking findings below; approval can't override them.
Version: 1.4.2 → 1.5.0 (minor). Derived from Conventional Commit types without a language model.
Committed by Dana Lee
Written with Claude Code · 95% (co-author trailer in 1 of 1 commit). Agent changes, and changes no person is confirmed to have written, need a person's approval.
  BLOCKED · Secrets block the release: Adds a private key (services/billing/keys.go:3)
      What to do: Fix the finding and push. If it is a false positive, mark it so on the release page. An owner, admin or policy admin can break glass on the check page in the dashboard if the policy allows it. https://bumpkit.dev/docs/explanations#gate-blocked-finding
  NEEDS APPROVAL · Agent or unverified changes to billing need approval: Changes billing code (2 files, 8 lines). Needs 1 approval from sam, priya (has 0)
      What to do: Ask a reviewer other than the author to approve the pull request's latest commit. In an emergency, an owner, admin or policy admin can override this commit on its check page in the dashboard, which is audited. https://bumpkit.dev/docs/explanations#gate-sensitive-area-needs-approval
  HIGH  Adds a private key services/billing/keys.go:3
  MED  Changes billing code (2 files, 8 lines) services/billing/invoice.go
  What to do about secrets: Remove it, rotate it with the provider, and load it from the environment. It stays in git history until you rewrite it. https://bumpkit.dev/docs/explanations#secret-in-the-diff
  What to do about changes to sensitive areas: Have someone who owns that area review the change closely. https://bumpkit.dev/docs/explanations#sensitive-area-changed

The first line is the headline: BLOCKED: with the first failing reason. The job exits 1. The same decision is posted as one pull request comment, which Bumpkit edits on every run. A fail can't be approved away: the finding has to go.

4. Fix it and push again ​

The agent moves the key to an environment variable and pushes. The gate runs again on the new commit:

Text
NEEDS APPROVAL: Needs a human approval from sam, priya
Approve the pull request; the gate re-checks automatically.
Version: 1.4.2 → 1.5.0 (minor). Derived from Conventional Commit types without a language model.
Committed by Dana Lee
Written with Claude Code · 95% (co-author trailer in 1 of 1 commit). Agent changes, and changes no person is confirmed to have written, need a person's approval.
  NEEDS APPROVAL · Agent or unverified changes to billing need approval: Changes billing code (2 files, 10 lines). Needs 1 approval from sam, priya (has 0)
      What to do: Ask a reviewer other than the author to approve the pull request's latest commit. In an emergency, an owner, admin or policy admin can override this commit on its check page in the dashboard, which is audited. https://bumpkit.dev/docs/explanations#gate-sensitive-area-needs-approval
  MED  Changes billing code (2 files, 10 lines) services/billing/invoice.go
  LOW  Reads a new environment variable BILLING_PRIVATE_KEY services/billing/keys.go:5
  What to do about changes to sensitive areas: Have someone who owns that area review the change closely. https://bumpkit.dev/docs/explanations#sensitive-area-changed
  What to do about new environment variables: Set it in every environment before you deploy, and document it. https://bumpkit.dev/docs/explanations#new-configuration

With the GitHub App, the check conclusion is action_required.

5. Approve ​

Sam reviews the pull request on GitHub and chooses Approve. The review event re-runs the gate:

Text
READY
Version: 1.4.2 → 1.5.0 (minor). Derived from Conventional Commit types without a language model.
Committed by Dana Lee
Written with Claude Code · 95% (co-author trailer in 1 of 1 commit).
  PASSED (APPROVED BY SAM) · Agent or unverified changes to billing need approval: Changes billing code (2 files, 10 lines)
  MED  Changes billing code (2 files, 10 lines) services/billing/invoice.go
  LOW  Reads a new environment variable BILLING_PRIVATE_KEY services/billing/keys.go:5
  What to do about changes to sensitive areas: Have someone who owns that area review the change closely. https://bumpkit.dev/docs/explanations#sensitive-area-changed
  What to do about new environment variables: Set it in every environment before you deploy, and document it. https://bumpkit.dev/docs/explanations#new-configuration

The pull request comment shows the rule as "Passed (approved by sam)". The approval counts only for this commit. If the agent pushes again, someone has to approve again. See Approvals for which reviews count.

6. Merge, tag and record the deploy ​

Merge the pull request, tag the release and deploy it. Then, from your deploy pipeline, in a checkout of the deployed commit:

Terminal
git tag v1.5.0 && git push origin v1.5.0
bumpkit deploy --version v1.5.0 --environment production
Text
Recorded 4b7a1d2 (v1.5.0) deployed to production with 6 commits

Bumpkit now knows when v1.5.0 went live and which lines each commit changed, so it can match production errors to commits later. Recording deploys needs the forensics or release_health flag. See Release Health & Forensics.

A hotfix with back-port detection ​

Beta, early access. Incidents need early access: a workspace without it gets 403 FEATURE_EARLY_ACCESS and a link to request it. Flag: forensics. The gate is on for every workspace, and bumpkit hotfix version and bumpkit contains read your local git history and need no flag.

v2.3.0 is in production and checkout requests time out. You ship a fix from the release tag, then make sure the next normal release doesn't bring the bug back.

1. Branch from the release and get the next version ​

Keep a branch for the 2.3 line, and branch the fix from it:

Terminal
git push origin v2.3.0:refs/heads/release/2.3
git switch -c hotfix/checkout-timeout v2.3.0
git commit -am "fix: retry the payment provider on timeout"
bumpkit hotfix version
Text
v2.3.1

bumpkit hotfix version takes the latest version tag reachable from HEAD and returns the next free patch version. If v2.3.1 already exists, locally or on origin, it says so on stderr and moves on:

Text
v2.3.1 already exists; using v2.3.2
v2.3.2

version is the only bumpkit hotfix subcommand.

2. Open the pull request and let the gate run ​

Terminal
git push -u origin hotfix/checkout-timeout

Open a pull request from hotfix/checkout-timeout into release/2.3. Because the branch name starts with hotfix/, bumpkit gate treats it as a hotfix (you can also pass --hotfix). A hotfix runs the faster deterministic check and follows the hotfix rules in your policy:

YAML
gate:
  hotfix:
    block_on: [breaking, data_loss, migration]
    max_files: 20
    review_within: 72h
    backports: approve

If someone sneaks a feature into the hotfix, the gate asks for approval:

Text
  NEEDS APPROVAL · Hotfix: feature commits: A hotfix should only fix. It carries 1 feature commit: feat: add retry metrics

Drop that commit, let the gate pass, merge into release/2.3, and tag v2.3.1 on the merged commit.

3. Catch the missing back-port ​

A week later, someone opens the next normal release pull request from main. The fix was never merged back. bumpkit gate compares main with recent release tags and finds it:

Text
NEEDS APPROVAL: Needs a human approval from anyone except the author (not an AI agent)
Approve the pull request; the gate re-checks automatically.
Version: 2.3.0 → 2.4.0 (minor). Derived from Conventional Commit types without a language model.
Committed by Dana Lee
Human-authored · 93% (measured on 64 verified releases in this workspace). No AI-agent signals in 4 commits or the branch.
  NEEDS APPROVAL · Hotfix back-ports (approve): Shipping this would bring fixed bugs back: v2.3.1's fix "fix: retry the payment provider on timeout" isn't on this branch
      What to do: Cherry-pick the named fixes onto this branch. With backports: approve, a person can approve the release without them. https://bumpkit.dev/docs/explanations#gate-missing-backports
  HIGH  v2.3.1's fix "fix: retry the payment provider on timeout" isn't on this branch  (from 3f2a9c1)
  What to do about missing backports: Cherry-pick the named fix onto this branch, or get the release approved without it. https://bumpkit.dev/docs/explanations#missing-backport

With backports: block the gate fails instead. With off it ignores missing fixes. The comparison needs tags and full history, so check out with fetch-depth: 0.

4. Find where the fix is ​

Terminal
bumpkit contains "retry the payment provider"
Text
3f2a9c1 fix: retry the payment provider on timeout
REF                  HOW
v2.3.1               contains
origin/release/2.3   contains

The fix is in v2.3.1 and on release/2.3, but not on main. Cherry-pick it:

Terminal
git switch -c backport/checkout-timeout origin/main
git cherry-pick -x 3f2a9c1
git push -u origin backport/checkout-timeout

Bumpkit matches cherry-picks by their content, so once this lands on main, the release pull request no longer reports the missing fix. bumpkit contains 3f2a9c1 then lists origin/main with cherry-picked.

With Close the loop (Beta, flag close_the_loop) and the GitHub App, bumpkit backport open 3f2a9c1 --onto main does the cherry-pick on Bumpkit's side and opens the pull request for you. If it conflicts, Bumpkit opens nothing and names the conflicting files. See Hotfixes & Break Glass.

If Bumpkit traced the timeouts to v2.3.0 and opened an incident, record which release fixed it:

Terminal
bumpkit incidents list
bumpkit incidents resolve 3f2c9a1e-8b7d-4c2a-9e1f-6a5b4c3d2e1f --version v2.3.1 --sha 3f2a9c1
Text
✓ Resolved 3f2c9a1e-8b7d-4c2a-9e1f-6a5b4c3d2e1f by v2.3.1

If someone had to break glass to ship the hotfix, the override waits for its post-hoc review in bumpkit override list. See Hotfixes & Break Glass.

Cutting a release train ​

Beta, early access. A workspace without access gets 403 FEATURE_EARLY_ACCESS and a link to request it. Flag: release_trains.

A release train is a named group of pull requests that ship together as one version. Each pull request still merges, and is gated, on its own. When the group is ready, you cut the train: Bumpkit picks one version for everything merged since the last release tag, writes one changelog entry that carries the train's name, and creates the tag and the GitHub Release.

Here the team groups the work for "Checkout v2" into one release. Cutting needs the Bumpkit GitHub App on the repository. The full guide is Release Trains.

1. Start the train ​

Terminal
bumpkit train new "Checkout v2"
Text
✓ Started Checkout v2; label pull requests train:checkout-v2 to join it
Checkout v2  acme/api → main  open  (5b8f1c2e-4a7d-4e2b-9c1a-0d3e6f7a8b9c)
Label train:checkout-v2

The train ships the repository's default branch unless you pass --branch. Its label comes from train.label in bumpkit.yml, train:{slug} by default.

2. Add pull requests ​

A pull request joins in one of three ways:

  • It carries the train's label, here train:checkout-v2.
  • It belongs to the train's milestone, if you started the train with --milestone.
  • You add it by hand:
Terminal
bumpkit train add "Checkout v2" 482
bumpkit train remove "Checkout v2" 479

3. Check readiness ​

bumpkit train show reads every member's latest gate decision and, for merged members, their production health:

Terminal
bumpkit train show "Checkout v2"
Text
Checkout v2  acme/api → main  needs approval
  #482  merged   pass            healthy       Saved payment methods
  #485  merged   pass            not_deployed  Order history page
  #488  open     needs_approval  -             Refund flow
• #488 needs approval: area: billing, when: agent.
• #488 isn't merged yet.
• Needs 1 release manager approval of the current members (has 0).
0 breaking, 1 migrations, 1 new env vars (CHECKOUT_V2_ENABLED); reaches billing, checkout

The train is as ready as its least ready reason: ready, waiting, needs_approval or blocked. A member that fails the gate always blocks it. The train: section of bumpkit.yml adds rules such as max_breaking and block_on_unhealthy_deploys (see train).

4. Get each pull request through the gate ​

Each member is approved and merged on its own, exactly as in the first example. Run bumpkit train show again until only the release manager's approval is left.

5. Approve as release manager ​

Sign in to the dashboard, open the batch under Releases and choose Approve batch.

The approval covers the members as they are now. If someone adds a pull request or pushes to one, earlier approvals stop counting and train show lists them as stale: members changed since. Only a person signed in to the dashboard can approve. bumpkit train approve and the train_approve MCP tool are refused with 403 HUMAN_APPROVAL_REQUIRED and the link.

6. Cut it ​

On the same page, choose Start release. An API key is refused here too.

Bumpkit versions every commit on main since the last release tag, writes one changelog entry with the train's name under the version heading, and creates the tag and a GitHub Release named after the version and the train. Starting it again returns the same cut. If train.release_workflow names a workflow file, Bumpkit dispatches that workflow with the train's name instead of creating the release itself.

A train that isn't ready is refused. A workspace owner or admin can cut it anyway by entering a reason on that page, which is kept in the audit log.

The repository needs a release tag like v1.0.0 to version from. Tag the first release by hand, then cut the train.

A production regression traced and rolled back ​

Beta, early access. A workspace without access gets 403 FEATURE_EARLY_ACCESS and a link to request it. Flags: release_health, forensics, intelligent_rollback.

v2.3.0 ships invoice caching. Twenty minutes later, a new TypeError appears in production. You find the commit and revert it.

Before you start, connect an error source (PostHog, Sentry or a signed webhook). Without one, every verdict is unknown. See Release Health & Forensics.

1. Record the deploy ​

Terminal
bumpkit deploy --version v2.3.0 --environment production
Text
Recorded 4b7a1d2 (v2.3.0) deployed to production with 7 commits

The commits and their changed lines are what let Bumpkit point at one commit later. If there is no earlier tag, pass --base with the previous release.

2. Errors arrive ​

Your error source reports the new error with its stack frames, for example billing/invoice.go:131 in Total. Bumpkit counts errors per fingerprint in five-minute buckets and compares the window after the deploy with the window before.

3. Check the release ​

Terminal
bumpkit release health v2.3.0
Text
v2.3.0 → production: REGRESSED
A new error appeared after v2.3.0: TypeError: Cannot read properties of undefined (42 in 60 minutes, p < 0.001).
WINDOW  MINUTES  ERRORS  PER HOUR
before  60       3       3
after   60       45      45

new TypeError: Cannot read properties of undefined (0 → 42)
  4b7a1d2 Cache invoice totals (high)
    billing/invoice.go:131 (Total) → 4b7a1d2 changed lines 120–148 of billing/invoice.go.

Incident 3f2c9a1e-8b7d-4c2a-9e1f-6a5b4c3d2e1f

The command exits 1 because the release regressed, so it also works as a post-deploy step. The suspect commit is the one whose changed lines match the error's stack frames. Bumpkit has opened an incident, linked it to the release and posted the top suspect to your Slack, Discord and webhook integrations.

4. Plan the rollback ​

Terminal
bumpkit rollback plan --incident 3f2c9a1e-8b7d-4c2a-9e1f-6a5b4c3d2e1f
Text
Rollback plan v2.2.0..v2.3.0
Revert 1 commit to undo the change behind the failure; the revert applies cleanly to 4b7a1d2 and changes 2 files.

Suspect commits
↩ 4b7a1d2 Cache invoice totals  Sam Lee, high likelihood (9.0)
      Last changed billing/invoice.go:131, a line in the stack trace.
      Changed billing/invoice.go, which is in the stack trace.
  a1c4f20 Rename invoice fields  Priya Shah, medium likelihood (3.0)
      Changed billing/invoice.go, which is in the stack trace.

Revert by hand: git revert --no-commit 4b7a1d2
An owner or admin opens it as a pull request with: bumpkit rollback open 7b1e0c42-9a4f-4d1c-8e3b-2f6a5d4c3b2a

↩ marks the commits the plan reverts. Bumpkit dry-ran the revert in a temporary worktree; your checkout is unchanged. Later commits that depend on a reverted one are added and listed with the reason.

5. An owner or admin opens the revert ​

Terminal
bumpkit rollback open 7b1e0c42-9a4f-4d1c-8e3b-2f6a5d4c3b2a --branch main
Text
Open a pull request on acme/api that reverts 1 commit? [y/N] y
✓ Opened https://github.com/acme/api/pull/512

Only a workspace owner or admin can open it; anyone else gets 403. The GitHub App opens the pull request on a bumpkit/rollback-… branch. In CI, pass --yes instead of answering the prompt. Without the App on the repository, you get 409 GITHUB_APP_REQUIRED and run the git revert command yourself. If the App on the repository belongs to another workspace, you get 403.

With Close the loop (Beta, flag close_the_loop), you can skip the plan: pass the incident id or the release (v2.3.0) to bumpkit rollback open, and Bumpkit reverts on its side and opens the pull request on bumpkit/rollback/incident-3f2c9a1e or bumpkit/rollback/v2.3.0. See Rollback & Time Machine.

6. Ship the revert ​

The revert pull request goes through the gate like any other change. Merge it, tag v2.3.1, and record the deploy:

Terminal
bumpkit deploy --version v2.3.1 --environment production
bumpkit release health v2.3.1

When the error's rate drops to half its earlier rate or less after a later deploy, Bumpkit resolves the incident with that version. To record it yourself, run bumpkit incidents resolve as in the hotfix example. See Rollback & Time Machine.

↑↓ to move, Enter to open