Docs

Gate

Release Gate ​

How the Bumpkit release gate decides pass, needs approval or fail, and how to run it on GitHub, GitLab, Bitbucket and Azure DevOps.

Risky changes, often written by agents, reach production because no rule stopped them; the gate applies your policy to every change, for engineering leads and platform teams.

The release gate decides whether a change may ship under your repository's bumpkit.yml policy. It runs a release check, works out whether a coding agent wrote the change, counts human approvals, and returns one of three outcomes:

Outcome Meaning GitHub check conclusion
pass Nothing in the policy stops it success
needs_approval A rule needs a person's approval first action_required
fail A blocking finding or failed requirement failure

Run the gate ​

Terminal
bumpkit gate
bumpkit gate --base v1.4.2 --comment
bumpkit gate --json
Flag Meaning
--base Version or ref the release starts from (default: the pull request's base, else the latest tag). With the GitHub App installed, outside a pull request it must be a branch or tag
--policy Policy file to use instead of bumpkit.yml at the base. With the GitHub App installed, the decision uses the base branch's copy instead
--comment Post or update the decision as a pull request comment
--hotfix Gate as a hotfix (see Hotfixes)
--json Print the decision as JSON

The command exits 0 on pass, 1 on needs_approval or fail, and 2 when Bumpkit can't decide (or 0 when on_error: pass). In GitHub Actions it also writes the decision to the job summary. The API equivalent is POST /v1/gate; see the API Reference.

The policy comes from the base ​

The gate reads bumpkit.yml (or .bumpkit.yml) as it is at the base of the change, so a pull request can't loosen its own rules. A repository without one uses the default policy:

YAML
gate:
  block_on: [secret, data_loss]
  require_approval:
    - breaking
    - area: [authentication, authorization, billing, cryptography]
      when: agent
    - untested: true
      when: agent
  vulnerabilities: high
  on_error: fail

A policy with a mistake is an error, never a silent default: the gate fails closed, even with on_error: pass. The full schema is in the bumpkit.yml Reference.

Where Bumpkit reads the file depends on whether the Bumpkit GitHub App is installed on the repository for your workspace:

Setup Policy the decision uses
The App is installed Bumpkit reads bumpkit.yml from GitHub itself and ignores the policy the CLI or Action sends, including --policy and the agents: section. It reads the default branch. A pull request into the default branch uses its base commit. A pull request into any other branch, including a stacked pull request or a release branch, uses the default branch's copy. --base never picks the policy
No App The CLI reads bumpkit.yml at the base from your checkout and sends it with the request

If GitHub can't return the file, the gate fails closed with 503 POLICY_UNAVAILABLE. See Troubleshooting.

With the App installed, only the decisions Bumpkit makes on a diff it fetched itself count. A decision from bumpkit gate, the API or MCP uses a diff the client sent, so it's a report: it never changes the required check, a deployment, a vote or a release train. Approvals the client sends are dropped, and Bumpkit reads them from the pull request's GitHub reviews instead. The agent timeline marks those decisions Sent by a client, from its own diff.

The decision records where the policy came from. The POST /v1/gate response has "policy_source": "client" or "base_branch:<ref>" (for example base_branch:main), and the reasons say more:

Reason When
policy_source: client (pass) No App: "The policy came from the client and wasn't verified from the base branch, because the Bumpkit GitHub App isn't installed on this repository for this workspace."
policy_source: base_branch:main (policy read from your repository) (pass) The App read the policy from main and applied it. The request carried a different copy, which wasn't used

These reasons show in the pull request comment's table and in the compliance evidence. Without the App, a pull request that edits its own workflow could send a looser policy, so install the App on every repository you gate.

How the gate decides ​

The gate considers only deterministic, unsuppressed findings. It applies these steps in order, and the worst outcome wins:

  1. Blocking findings. A high-severity finding whose kind is in block_on (secret, data_loss, breaking, contract_breaking, version_mismatch or compatibility_break) fails.
  2. Vulnerabilities. With vulnerabilities set to high, medium or low, a vulnerable_dependency at or above it fails. If the vulnerability database couldn't be reached, the gate needs approval.
  3. Approval rules. Each require_approval rule that applies and is triggered needs approvals (see Approvals).
  4. Hotfix scope or back-ports. A hotfix is held to hotfix rules; any other release is checked for fixes missing from recent release tags. See Hotfixes.
  5. Blast radius. Reaching an area in blast_radius.approve_areas needs approval.
  6. Fix tasks. With Close the loop (Beta, flag close_the_loop), each fix task still open on the branch fails the gate under fix_tasks: block (the default) or needs approval under fix_tasks: approve.
  7. Regression evidence. With require_regression_evidence (Beta, flag regression_evidence), the gate fails or needs approval unless every test the change's blast radius expects passed in CI-attested results for this exact commit.
  8. Agent budgets and track records. An agent over a limit in the agents section (Beta, flag agent_budgets) fails or needs approval, and an agent_track_record_below rule (Beta, flag agent_track_records) needs approval.
  9. Incomplete check. If the diff was too large to check in full, the gate needs an approval from someone with write access or a code owner. With the GitHub App or a connection, Bumpkit also reads bumpkit.yml and the CODEOWNERS files directly at the base and the head, so a large diff can't hide an edit to them.
  10. Policy change. A change to bumpkit.yml, .bumpkit.yml or a CODEOWNERS file, including renaming or deleting it, needs one approval when the change targets the default branch, with the rule policy_change. The approver can't be the author and needs write access to the repository or to be a code owner of the file, as read from GitHub or GitLab. On Bitbucket and Azure DevOps, Bumpkit counts the approvals those hosts report. This is built in: a repository's policy can't turn it off, and the gate reads the policy from the default branch, so the same pull request can't remove it either. A change against another branch isn't flagged, because Bumpkit doesn't read that branch's copy; the edit is flagged when it reaches the default branch. Only those exact paths are covered: a file that one of them links to is treated like any other file.
  11. CI evidence. require_checks fail when a named check didn't run or didn't pass on the commit, require_check_apps also pins each check to the GitHub App that must report it, and security_alerts fail when open code scanning alerts are at or above the threshold. These need the GitHub App. Without it, a person must approve to vouch for require_checks and security_alerts, and require_check_apps fails.
  12. Denials. A deny vote from Slack, the dashboard or the CLI fails the gate.
  13. Windows and freezes. A release window or change freeze (Beta, flag change_freezes) fails the gate or needs approval.
  14. Override. A break-glass override lets a failing or waiting commit through.

Approval rules ​

A rule is breaking, contract_breaking, untested, intent, or a mapping:

YAML
gate:
  require_approval:
    - breaking
    - area: [billing]
      when: agent_or_unknown
      approvers: ["@acme/payments", "sam"]
      count: 2
    - untested: true
      when: agent
      codeowners: true
Key Meaning
breaking A high-severity breaking finding, or a major version bump
untested An untested finding
area A risk_area finding for one of these areas
when always (default), agent or agent_or_unknown
approvers Only these GitHub logins or @org/team teams count
count Approvals needed, 1 to 10 (default 1)
codeowners The CODEOWNERS of the triggering files count as approvers

Who wrote the change ​

Bumpkit tells agent-written code from human-written code with no setup. Every release check names a committer (the pull request author, then everyone who pushed commits) and a writer (a person, or the coding agent that wrote the code).

Authorship is verified when agent hooks or Agent Telemetry reported the session that made the commit, or a coding agent's bot opened the pull request. The agent hooks report each session's work as it happens, including work by subagents and in other git worktrees of the same repository, so a change counts as agent-written even when it is committed under your name with no Co-authored-by: trailer. The release check names the evidence, for example hook attestation from Claude Code session 1a2b3c4d. Keep the Bumpkit CLI current (bumpkit update) so the hooks can report. It is declared when the agent signed the change, for example with a Co-authored-by: trailer. Anything weaker is inferred. Confidence is shown only where Bumpkit has measured it on your own verified releases; otherwise you see the evidence and no percentage. Run bumpkit report authorship-coverage to see how many of your releases are verified.

Policy uses the difference:

  • when: agent approval rules apply to every change that isn't confirmed as written by a person: any agent signal, inferred included, and any change with no signal at all. An agent using a developer's git identity on a neutral branch leaves no signal, so no signal isn't proof of a person.
  • A change counts as written by a person only when all of this holds: no agent signal on the commits, pull request, branch or vendor usage; agent hooks or Agent Telemetry are on for the repository; and at least 90% of such changes turned out to be human across at least 20 verified releases (your own, or pooled if you opted in).
  • when: agent hard blocks (a quality rule with action: block) fail the gate only for declared or verified agent changes. Any other change the rule covers needs an approval instead, so an inferred signal never blocks a release on its own.
  • when: agent_or_unknown is the same as when: agent for approval rules, and stays valid.

Every change that triggers a when: agent approval rule needs an approval unless Bumpkit has proof about that commit. No agent signal isn't proof of a person, and hooks on the repository say nothing about one commit, so a change with no signal still asks for the approval. A hard block applies only to a verified or declared agent.

For verified authorship with no setup on developer machines, an admin can turn on Agent Telemetry once for the whole org. For how gate decisions and authorship serve as audit evidence, see Security and Compliance.

When Bumpkit can't decide ​

on_error decides what an error means. fail (the default) fails the gate; pass makes the gate advisory. Repository and teammate counts are unlimited, and an error never uses a credit on its own.

Scanner results ​

Bumpkit doesn't run scanners. It reads the results from the ones you already run and shows each finding next to the areas the change reaches, highest reach first. It keeps only findings on lines the change touches or in files it reaches, and stores those findings, never the file you send.

Tool What to send Flag
CodeQL SARIF 2.1.0, e.g. codeql database analyze --format=sarif-latest --sarif
Semgrep SARIF 2.1.0, e.g. semgrep scan --sarif --sarif
Snyk Snyk Code SARIF 2.1.0, e.g. snyk code test --sarif --sarif
Socket The response of Socket's Stream full scan API, saved as is: one JSON artifact per line --socket
Terminal
bumpkit gate --sarif codeql.sarif --sarif semgrep.sarif --socket socket.json

bumpkit check takes the same flags.

The API takes the same files as scans on POST /v1/checks and POST /v1/gate: a list of {"format": "sarif" | "socket", "content": "<file contents>"}.

Limit Value
Reports per check 5
Size per report 4 MiB
Findings kept per tool 50
Uploads per API key 60 a minute

Severity comes from the result's security-severity score when present (9 and up critical, 7 high, 4 medium, else low), otherwise from its SARIF level (error high, warning medium, note low). From Socket, Bumpkit reads each artifact's namespace, name, version and manifestFiles, and each alert's type, severity, file, start, end, action and props.cveId or props.ghsaId. It reads start and end as line numbers, uses the artifact's first manifest file when an alert has no file, and skips alerts whose action is ignore. Socket's middle reads as medium. When Bumpkit has no blast radius for the change, the finding says "Reachability not measured." Each upload is recorded in the audit log. To require a person's approval, add scanner_finding to require_approval.

GitHub ​

On GitHub, the Bumpkit GitHub App runs the gate, with no workflow or token to set up. To run it in your own pipeline instead, see Run it in CI.

The GitHub App ​

Install the Bumpkit GitHub App on a repository and the gate runs on every pull request as a check named Bumpkit release gate, with no workflow or token to set up. It runs when a pull request is opened, pushed to, reopened or marked ready for review, when a review is submitted or dismissed, for merge queue groups, when a required check or status finishes, and when someone re-runs the check.

The App reads bumpkit.yml and CODEOWNERS from the base commit of a pull request into the default branch, and from the default branch for every other pull request. When two open pull requests have the same head commit, the check takes the stricter result and names the pull request holding it. When the policy has require_checks, the check stays in progress, showing what it is waiting for, until those checks finish on the commit. The App verifies approvals from GitHub reviews, resolves @org/team approvers and CODEOWNERS, and posts findings as line annotations. The decision, with each rule's reason, is the check's summary, and its details link opens the release on the dashboard. On each automatic run, the App also posts the decision as one pull request comment from bumpkit[bot] and edits that comment on later runs instead of adding new ones. Checks you start by hand (bumpkit github check, the MCP check tool or the dashboard's run) update the check but leave the comment alone.

Make Bumpkit release gate a required status check in your branch protection to block merges on it.

The pull request comment ​

bumpkit gate --comment posts the decision as a pull request comment: as bumpkit[bot] when the Bumpkit GitHub App is installed on the repository, otherwise with the job's token. This comment is separate from the one the App posts on its own runs. It says it was sent by a client from its own diff, and the Bumpkit check on the commit decides whether the change can merge. It comments only in a CI job that runs for a pull request, such as a GitHub Actions pull_request workflow. Run from a laptop, it can't find the pull request and posts nothing. The comment starts with a headline for the outcome, then says what to do, the suggested version and who wrote the change, and lists each rule's reason and the findings by severity. The headline is one of:

Outcome Headline
pass ✅ Ready to ship
needs_approval ⏳ Needs a human approval from sam, priya (whose approval it needs, for example "⏳ Needs a human approval from anyone except the author (not an AI agent)")
fail ⛔ Blocked: followed by the first failing reason

Bumpkit release gate is the name of the check and commit status, not part of the comment. Bumpkit edits the same comment on every run instead of adding new ones.

GitLab, Bitbucket and Azure DevOps ​

Connect these hosts from the dashboard's Repository page: pick GitLab, Bitbucket or Azure DevOps under Code host, and the page walks you through it. The same form is on Integrations.

You can run the gate on these hosts in two ways, and you can combine them:

  • A connection. Bumpkit receives a signed webhook, runs the gate on its own and reports a status and a comment. No CI job is needed, and approvals are verified on the host.
  • A CI job. bumpkit gate runs in your pipeline, detects the host from its environment, counts approvals and comments with a token you provide. With a connection for the same repository, Bumpkit verifies those approvals itself. See Run it in CI.

Add a connection ​

Workspace owners and admins add a connection on the dashboard's Repository or Integrations page, or with the CLI:

Terminal
bumpkit gate connections add --provider gitlab --path acme/api
bumpkit gate connections add --provider bitbucket --path acme/api
bumpkit gate connections add --provider azure_devops --host https://dev.azure.com/acme --path "Payments/api"
bumpkit gate connections add --provider ghes --host https://github.acme.example --path acme/api
bumpkit gate connections list
bumpkit gate connections remove CONNECTION_ID

add prompts for the access token (or pass --token - to read it from stdin) and stores it encrypted. It prints the webhook URL, https://bumpkit.dev/hooks/gate/{provider}/{token}, and a webhook secret that is shown only once. The same endpoints are GET, POST /v1/gate/connections and DELETE /v1/gate/connections/{id}.

Provider --path --host Access token
gitlab group/project, or a group to cover all its projects Empty for gitlab.com, or your self-managed GitLab's https address A project or group access token with the api scope
bitbucket workspace/repository Empty for Bitbucket Cloud A repository or workspace access token that can read pull requests and write build statuses
azure_devops project/repository Your organization, like https://dev.azure.com/your-org A personal access token with Code (read and status) and Pull Request Threads scopes
ghes owner/repository, or an owner to cover all its repositories Required: your server's https address, like https://github.acme.example A personal access token with the repo scope, from a user who can write to the repository. Add read:org if your rules name teams

Then add the webhook on the host and paste in the URL and secret:

Provider Where URL goes in Secret goes in Events
GitLab The project or group's Settings → Webhooks → Add new webhook URL Secret token Merge request events and Pipeline events
Bitbucket The repository's Repository settings → Webhooks → Add webhook URL Secret Pull request Created, Updated, Approved and Approval removed, plus Repository Build status created and Build status updated
Azure DevOps Project settings → Service hooks → Web Hooks URL Basic authentication password, with any username Pull request created and Pull request updated, one subscription each
GitHub Enterprise Server The repository's Settings → Hooks → Add webhook, with Content type set to application/json Payload URL Secret Pull requests, Pull request reviews, Check runs and Statuses

Then make the gate block merges:

Provider Require the gate
GitLab Add a status check named Bumpkit release gate under Settings → Merge requests → Status checks, or turn on Pipelines must succeed and run the CI job below
Bitbucket Under Repository settings → Branch restrictions, edit the target branch and add a merge check that requires at least one successful build and no failed builds. The gate posts the Bumpkit release gate build status
Azure DevOps Add Bumpkit release gate as a required status check in the target branch's policy
GitHub Enterprise Server Open a pull request so the status appears once, then require the Bumpkit release gate status check in the branch protection rule under Settings → Branches

Open a pull request or merge request to try it. The connection shows Connected on the Repository and Integrations pages, and the first decision appears on the change within a minute.

Webhook deliveries are rate limited per address, and unsigned or wrongly signed deliveries are rejected.

What each host gets ​

Provider Runs on Status Comment Approvals counted
GitLab Merge request opened, reopened, approved, unapproved, pushed or retargeted; pipelines finishing for required checks An external status check named Bumpkit release gate if the project has one, else a commit status with that name A merge request note Merge request approvals after the latest push
Bitbucket Pull request created, updated, approved or unapproved, changes requested or removed; build statuses for required checks A build status with key bumpkit-release-gate A pull request comment Participant approvals after the latest push
Azure DevOps Pull request created or updated while active A pull request status bumpkit/release-gate A pull request thread Reviewer votes of approved or approved with suggestions, after the latest push
GitHub Enterprise Server Pull request opened, reopened, pushed, retargeted or marked ready for review; reviews submitted or dismissed; check runs and statuses finishing for required checks A commit status named Bumpkit release gate A pull request comment Reviews that approve the latest commit

On GitLab, Bitbucket, Azure DevOps and GitHub Enterprise Server, needs_approval is reported as a failed status so the merge stays blocked.

A vote in Bumpkit or Slack counts for the pull request it was cast on, not for another pull request that shares the commit. On GitHub and GitHub Enterprise Server, changing a pull request's base starts approval over: reviews and Bumpkit approvals from before the change don't count toward the new base, so someone has to approve again. A denial stays until that person changes it.

A decision made from a diff your CI sent is shown on its check page as reported by CI. It stays in the record, but it can't be voted on or overridden there, and it doesn't appear in the approvals inbox or count toward agent track records. The approvals inbox lists decisions Bumpkit made itself from a connected repository.

Your org policy and its locks apply on these hosts too. The policy and CODEOWNERS come from the default branch, at the target commit when the change targets the default branch, so a change against another branch can't choose looser rules. If the default branch or the file can't be read, the gate fails closed. When open changes share a commit, the strictest decision on that commit applies to each of them; Bumpkit lists them through the provider's API, and if the list can't be read in full, the gate fails closed. CODEOWNERS is read from CODEOWNERS, docs/CODEOWNERS or .gitlab/CODEOWNERS on GitLab, CODEOWNERS or .bitbucket/CODEOWNERS on Bitbucket, and CODEOWNERS, .azuredevops/CODEOWNERS or docs/CODEOWNERS on Azure DevOps. Approvals given before the latest push don't count, nor do the author's, bots' or coding agents'.

CODEOWNERS on GitHub Enterprise Server is read from .github/CODEOWNERS, CODEOWNERS or docs/CODEOWNERS.

GitHub Enterprise Server ​

Beta, early access. Flags: github_enterprise_server and release_gate.

A connection gives pull requests on your own server the same gate as github.com, with a commit status in place of the GitHub App's check run.

  • Your server must be reachable. Bumpkit calls your server over https on port 443, at /api/v3. The address must be a public host name that resolves to a public address. IP addresses, other ports and private addresses are refused, both when you connect and on every call.
  • Repositories are matched by server. https://github.acme.example/acme/api and github.com/acme/api are two different repositories. Overrides, approvals, freezes and history for one never apply to the other.
  • The policy comes from the server. Every gate reads bumpkit.yml and CODEOWNERS from the repository's default branch, at the target commit when the pull request targets it, so a pull request can't loosen its own rules. If a client sends a different policy, Bumpkit uses the one on your server, and the decision says so. If Bumpkit can't read the policy, the gate fails closed.
  • Approvals come from the server. A bumpkit gate run in CI counts the reviews on your server, not the approvals it was sent. If the run names no pull request, the commit isn't the head of the pull request, or the reviews can't be read, no approvals count. An address on your server that Bumpkit can't read as owner/repository fails closed.
  • Retargeting starts approval over. Changing a pull request's base runs the gate again. Reviews and Bumpkit approvals from before the change don't count toward the new base, so someone has to approve again. A denial stays until that person changes it.
  • Required checks and code scanning count. require_checks, require_check_apps and security_alerts read check runs, commit statuses and open code scanning alerts on your server.

To connect, add the connection, then add the webhook and require the status as shown above. The first pull request shows Bumpkit release gate as a commit status and one Bumpkit comment, and the decision appears on the Checks page.

Run it in CI ​

Add bumpkit gate to your pipeline, and a blocked release fails the job. The setup is the same in every CI:

  1. Create an API key on the dashboard's API keys page, and store it as a secret named BUMPKIT_API_KEY.
  2. Add your CI's configuration from this section. It downloads the CLI, verifies its checksum and runs the gate.
  3. Add your code host's token if the table below calls for one. The gate uses it to count approvals and post its comment.
  4. Make the job a required check on your target branch, so a failed gate blocks the merge.
CI Code hosts Token to add
GitHub Actions GitHub None. The workflow passes the job's token
GitLab CI GitLab GITLAB_TOKEN
Bitbucket Pipelines Bitbucket Cloud BITBUCKET_ACCESS_TOKEN
Azure Pipelines Azure Repos None. The step passes System.AccessToken
Buildkite GitHub, GitLab, Bitbucket Cloud By code host
CircleCI GitHub, Bitbucket Cloud By code host
Jenkins GitHub, GitLab, Bitbucket Cloud By code host

Open a pull request to try it. The job passes on pass, and fails on needs_approval, fail, or when Bumpkit can't decide, unless your policy sets on_error: pass. The job counts approvals when it runs, so re-run it after someone approves.

Run it in GitHub Actions ​

The GitHub App needs no workflow, so use this only if you want the gate in your own workflow. Save this file as .github/workflows/bumpkit-gate.yml:

YAML
name: Bumpkit release gate
on: pull_request

permissions:
  contents: read
  pull-requests: write

jobs:
  bumpkit-release-gate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Bumpkit release gate
        env:
          BUMPKIT_API_KEY: ${{ secrets.BUMPKIT_API_KEY }}
          GITHUB_TOKEN: ${{ github.token }}
        run: |
          set -eu
          arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
          name="bumpkit_linux_${arch}.tar.gz"
          url="https://bumpkit.dev/download/latest"
          dir=$(mktemp -d) && repo=$PWD && cd "$dir"
          curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
          grep " $name\$" checksums.txt | sha256sum -c -
          tar -xzf "$name"
          cd "$repo"
          "$dir/bumpkit" gate --comment          

Add BUMPKIT_API_KEY under the repository's Settings → Secrets and variables → Actions, then require the bumpkit-release-gate job in branch protection.

GitHub doesn't give repository secrets to pull requests from forks, so the job can't get a decision for them.

Run it in GitLab CI ​

YAML
bumpkit-release-gate:
  stage: test
  image: alpine:3.20
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  variables:
    GIT_DEPTH: "0"
    BUMPKIT_VERSION: latest
  script:
    - apk add --no-cache git curl tar >/dev/null
    - |
      arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
      name="bumpkit_linux_${arch}.tar.gz"
      url="https://bumpkit.dev/download/$BUMPKIT_VERSION"
      mkdir -p /tmp/bumpkit && cd /tmp/bumpkit
      curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
      grep " $name\$" checksums.txt | sha256sum -c -
      tar -xzf "$name"
      cd "$CI_PROJECT_DIR"
      git config --global --add safe.directory "$CI_PROJECT_DIR"
      /tmp/bumpkit/bumpkit gate --comment      

Set these CI/CD variables (masked):

Variable Meaning
BUMPKIT_API_KEY Your Bumpkit API key
GITLAB_TOKEN or BUMPKIT_GITLAB_TOKEN A token with the api scope, to count approvals and post the note
BUMPKIT_API_URL Optional; defaults to https://bumpkit.dev/v1

Without a token, the job falls back to CI_JOB_TOKEN, which can't read merge request approvals, so none are counted.

Run it in Bitbucket Pipelines ​

YAML
image: alpine:3.20

definitions:
  steps:
    - step: &bumpkit-release-gate
        name: Bumpkit release gate
        clone:
          depth: full
        script:
          - apk add --no-cache git curl tar >/dev/null
          - export BUMPKIT_VERSION="${BUMPKIT_VERSION:-latest}" BUMPKIT_DOWNLOAD_URL="${BUMPKIT_DOWNLOAD_URL:-https://bumpkit.dev/download}"
          - arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') && name="bumpkit_linux_${arch}.tar.gz"
          - url="$BUMPKIT_DOWNLOAD_URL/$BUMPKIT_VERSION"
          - mkdir -p /tmp/bumpkit && cd /tmp/bumpkit && curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
          - grep " $name\$" checksums.txt | sha256sum -c - && tar -xzf "$name" && cd "$BITBUCKET_CLONE_DIR"
          - /tmp/bumpkit/bumpkit gate --comment

pipelines:
  pull-requests:
    '**':
      - step: *bumpkit-release-gate

Set BUMPKIT_API_KEY and BITBUCKET_ACCESS_TOKEN (or BUMPKIT_BITBUCKET_TOKEN) as secured repository variables. The token is sent as a bearer token, or as basic authentication when it has the form user:password.

Run it in Azure Pipelines ​

YAML
steps:
  - checkout: self
    fetchDepth: 0
    persistCredentials: true
  - bash: |
      set -euo pipefail
      os=$(uname -s | tr A-Z a-z)
      arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
      name="bumpkit_${os}_${arch}.tar.gz"
      url="https://bumpkit.dev/download/latest"
      dir="$AGENT_TEMPDIRECTORY/bumpkit" && mkdir -p "$dir" && cd "$dir"
      curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
      grep " $name\$" checksums.txt | sha256sum -c -
      tar -xzf "$name"
      cd "$BUILD_SOURCESDIRECTORY"
      "$dir/bumpkit" gate --comment      
    displayName: Bumpkit release gate
    condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
    env:
      BUMPKIT_API_KEY: $(BUMPKIT_API_KEY)
      SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Run the pipeline for pull requests (for example as a build validation policy on the target branch), since the step only runs when Build.Reason is PullRequest. Store BUMPKIT_API_KEY as a secret pipeline variable. SYSTEM_ACCESSTOKEN lets the job read reviewer votes and post the thread.

Run it in Buildkite ​

Buildkite, CircleCI and Jenkins build code that lives somewhere else, so gate picks the API from the repository URL. See Tokens for your code host.

YAML
steps:
  - label: "Bumpkit release gate"
    if: build.pull_request.id != null
    env:
      BUILDKITE_GIT_FETCH_FLAGS: "-v --prune --tags"
    command: |
      set -eu
      os=$$(uname -s | tr A-Z a-z)
      arch=$$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
      name="bumpkit_$${os}_$${arch}.tar.gz"
      url="https://bumpkit.dev/download/latest"
      dir=$$(mktemp -d) && repo=$$PWD && cd "$$dir"
      curl -fsSLO "$$url/$$name" && curl -fsSLO "$$url/checksums.txt"
      grep " $$name$$" checksums.txt | sha256sum -c -
      tar -xzf "$$name"
      cd "$$repo"
      "$$dir/bumpkit" gate --comment      

Turn on pull request builds in the pipeline's settings. Give the step BUMPKIT_API_KEY and your code host's token with Buildkite secrets or an agent environment hook, not in this file. Don't set checkout.depth on this step.

Run it in CircleCI ​

YAML
version: 2.1

jobs:
  bumpkit-release-gate:
    docker:
      - image: cimg/base:current
    steps:
      - checkout:
          method: full
      - run:
          name: Bumpkit release gate
          command: |
            set -eu
            arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
            name="bumpkit_linux_${arch}.tar.gz"
            url="https://bumpkit.dev/download/latest"
            dir=$(mktemp -d) && repo=$PWD && cd "$dir"
            curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
            grep " $name\$" checksums.txt | sha256sum -c -
            tar -xzf "$name"
            cd "$repo"
            "$dir/bumpkit" gate --comment            

workflows:
  release-gate:
    jobs:
      - bumpkit-release-gate

Set BUMPKIT_API_KEY and your code host's token as project environment variables or in a context. Turn on Only build pull requests in the project's advanced settings, so the job has a pull request to read.

CircleCI has no variable for the target branch, so gate reads it from the code host with your token. Without a token, pass --base. CircleCI sets CIRCLE_PULL_REQUEST for GitHub and Bitbucket Cloud, and picks one at random when a commit belongs to several pull requests. It doesn't set it for GitLab, so on a GitLab pipeline pass --base and --pr. That pipeline counts no approvals and posts no comment.

Run it in Jenkins ​

Use a Multibranch Pipeline with a branch source plugin that discovers pull requests. Only those set CHANGE_ID, CHANGE_TARGET and CHANGE_URL.

GROOVY
pipeline {
    agent any
    stages {
        stage('Bumpkit release gate') {
            when { changeRequest() }
            environment {
                BUMPKIT_API_KEY = credentials('bumpkit-api-key')
                GITHUB_TOKEN = credentials('github-token')
            }
            steps {
                withCredentials([gitUsernamePassword(credentialsId: 'git-checkout', gitToolName: 'Default')]) {
                    sh '''
                        set -eu
                        os=$(uname -s | tr A-Z a-z)
                        arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
                        name="bumpkit_${os}_${arch}.tar.gz"
                        url="https://bumpkit.dev/download/latest"
                        dir=$(mktemp -d) && cd "$dir"
                        curl -fsSLO "$url/$name" && curl -fsSLO "$url/checksums.txt"
                        grep " $name\\$" checksums.txt | sha256sum -c -
                        tar -xzf "$name"
                        cd "$WORKSPACE"
                        "$dir/bumpkit" gate --comment
                    '''
                }
            }
        }
    }
}

Add these credentials in Jenkins:

Credential Kind Meaning
bumpkit-api-key Secret text Your Bumpkit API key
github-token Secret text Your code host's token. On GitLab, name the variable GITLAB_TOKEN. On Bitbucket Cloud, name it BITBUCKET_ACCESS_TOKEN
git-checkout Username with password Lets gate fetch the target branch and tags over HTTPS

gitUsernamePassword needs the Git plugin and an HTTPS remote. For an SSH remote, load the key in the agent instead. Leave Shallow clone off, and keep Fetch tags on if you add Advanced clone behaviours.

Tokens for your code host ​

In Buildkite, CircleCI and Jenkins, gate picks the API from the repository's URL:

Repository API Token
github.com GitHub BUMPKIT_GITHUB_TOKEN or GITHUB_TOKEN, with read access to pull requests. To post --comment, it also needs write access to pull requests
gitlab.com GitLab BUMPKIT_GITLAB_TOKEN or GITLAB_TOKEN, with the api scope
bitbucket.org Bitbucket Cloud BUMPKIT_BITBUCKET_TOKEN or BITBUCKET_ACCESS_TOKEN
Any other host GitLab if a GitLab token is set, otherwise GitHub Enterprise if a GitHub token is set The same variables. GitHub Enterprise's API is read from /api/v3 on that host; set GITHUB_API_URL if yours differs

Without a token, the gate still runs, but it counts no approvals and posts no comment, so a policy that requires approvals reports needs_approval. Bitbucket Data Center and Azure Repos aren't read from these three CIs.

Hosts detected in CI ​

Host Detected by Pull request Token
GitHub Actions default the event payload GITHUB_TOKEN
GitLab CI GITLAB_CI=true CI_MERGE_REQUEST_IID BUMPKIT_GITLAB_TOKEN, GITLAB_TOKEN, else CI_JOB_TOKEN
Bitbucket Pipelines BITBUCKET_BUILD_NUMBER BITBUCKET_PR_ID BUMPKIT_BITBUCKET_TOKEN or BITBUCKET_ACCESS_TOKEN
Azure Pipelines TF_BUILD=true SYSTEM_PULLREQUEST_PULLREQUESTID SYSTEM_ACCESSTOKEN
Buildkite BUILDKITE=true BUILDKITE_PULL_REQUEST By code host
CircleCI CIRCLECI=true CIRCLE_PULL_REQUEST By code host
Jenkins BUILD_TAG starting with jenkins- CHANGE_ID By code host

Overrides ​

When a commit has to ship anyway, a workspace owner, admin or policy admin can break glass. The override applies to that exact commit only; a new push needs a fresh decision.

An override needs a person signed in to the dashboard. Open the commit's check, enter a reason of 10 to 500 characters under Override this commit and choose Override gate. The pull request's GitHub check re-runs right away. An API key can't override: bumpkit override, the override MCP tool and POST /v1/gate/override answer 403 HUMAN_APPROVAL_REQUIRED with the link, whatever role the key's owner has, so an agent holding an owner's key can't turn the check green.

  • Only owners, admins and policy admins can override (see Roles), and each commit can be overridden once. A second override of the same commit gets 409.
  • An override turns fail or needs_approval into pass and adds a break_glass reason naming who overrode it and why.
  • With break_glass: false, the override is recorded but the gate's outcome doesn't change.
  • Every override is in the gate decision, the audit log and the compliance evidence, and can require a post-hoc review. See Hotfixes & Break Glass.

↑↓ to move, Enter to open