Skip to content

Latest commit

 

History

48 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mergify CI Buildkite Plugin

A Buildkite plugin for integrating with Mergify CI Insights — upload JUnit test reports, detect pull request scopes, and upload scopes to Mergify Merge Queue.

Authentication

Put the Mergify token in MERGIFY_TOKEN in the agent environment. None of the examples below pass it through the plugin's token config, on purpose.

buildkite-agent pipeline upload interpolates variables at upload time, so token: "${MERGIFY_TOKEN}" writes the plaintext secret into the stored pipeline, where the Buildkite UI renders it and build history keeps it. The agent warns about it on upload, and Buildkite Agent v4 rejects such uploads by default: v3's opt-in --reject-secrets becomes an opt-out --allow-secrets.

Escaping does not help. $$MERGIFY_TOKEN survives upload as the literal string $MERGIFY_TOKEN, and the plugin prefers its token config over the environment, so that non-empty string shadows the MERGIFY_TOKEN that would have worked and is sent as the token.

Supply MERGIFY_TOKEN the way you supply any other Buildkite secret, so it only ever exists in the job's environment:

  • an agent environment hook that exports MERGIFY_TOKEN
  • a secrets plugin that exports MERGIFY_TOKEN into the job from its own environment hook, which runs before this plugin resolves the token

A pipeline-level env: block is not one of these: it is stored with the pipeline just like token is.

Unsetting MERGIFY_TOKEN does not necessarily stop a build from authenticating, because mergify-cli falls back to GITHUB_TOKEN and then to gh auth token. With none of those available, scopes still detects scopes and writes the meta-data and skips only the API upload with a warning, scopes-upload warns and skips, and junit-process fails the step.

Plugin version

The examples pin mergifyio/mergify-ci#v7. Newer tags are on the releases page; the pins here are bumped once a tag exists, so they can trail the newest release by a day.

Coming from #v2 or older, drop python_version from the plugin config before you move. v5 removed that property and the schema sets additionalProperties: false, so a step still passing it fails validation. Pin the CLI with mergify_cli_version instead. v5 also replaced the uv install with a prebuilt binary, so the agent needs tar and sha256sum/shasum rather than Python, see Requirements.

Actions

junit-process

Process JUnit XML test reports and upload them to Mergify CI Insights. Detects silent test failures automatically using the step's exit code.

steps:
  - label: "Run tests"
    command: pytest --junitxml=reports/junit.xml
    plugins:
      - mergifyio/mergify-ci#v7:
          action: junit-process
          report_path: "reports/*.xml"

scopes

Detect which code scopes are affected by a pull request and upload them to the Mergify API. A Buildkite annotation is created to display the detected scopes directly on the build page.

steps:
  - label: "Detect scopes"
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes

scopes-git-refs

Return the merge-queue-aware base and head SHAs. Results are stored as Buildkite meta-data (mergify-ci.base, mergify-ci.head) for use by subsequent steps.

steps:
  - label: "Get git refs"
    key: git-refs
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes-git-refs

scopes-upload

Upload scopes to the Mergify API. Requires a prior scopes-git-refs step for base/head refs. Scopes can be provided as a comma-separated list in plugin config, or read automatically from the mergify-ci.scopes meta-data set by a prior scopes step (both JSON and CSV formats are supported).

# Option 1: explicit scopes via plugin config
steps:
  - label: "Get git refs"
    key: git-refs
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes-git-refs

  - label: "Upload scopes"
    depends_on: git-refs
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes-upload
          scopes: "backend,frontend"
# Option 2: scopes from meta-data (set by a prior step)
steps:
  - label: "Generate scopes"
    key: generate-scopes
    command: |
      buildkite-agent meta-data set "mergify-ci.scopes" "backend,frontend"

  - label: "Upload scopes"
    depends_on: generate-scopes
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes-upload

Using scopes to conditionally run steps

Detect scopes first, then use the meta-data to skip steps unaffected by the change:

steps:
  - label: "Detect scopes"
    key: scopes
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes

  - label: "Backend tests"
    depends_on: scopes
    command: pytest tests/backend/
    if: build.env("BUILDKITE_TRIGGERED_FROM_BUILD_PIPELINE_SLUG") != null || build.pull_request.id != null
    plugins:
      - mergifyio/mergify-ci#v7:
          action: junit-process
          report_path: "reports/*.xml"
    # Use a dynamic pipeline or script to check scopes:
    # SCOPES=$(buildkite-agent meta-data get "mergify-ci.scopes")
    # echo "$SCOPES" | jq -e '.backend == "true"'

  - label: "Frontend tests"
    depends_on: scopes
    command: npm test
    plugins:
      - mergifyio/mergify-ci#v7:
          action: junit-process
          report_path: "reports/*.xml"
    # SCOPES=$(buildkite-agent meta-data get "mergify-ci.scopes")
    # echo "$SCOPES" | jq -e '.frontend == "true"'

For full conditional control, use a dynamic pipeline that reads the scopes meta-data and only uploads the relevant steps:

#!/bin/bash
# .buildkite/dynamic-pipeline.sh
SCOPES=$(buildkite-agent meta-data get "mergify-ci.scopes")

if echo "$SCOPES" | jq -e '.backend == "true"' > /dev/null 2>&1; then
  cat <<'YAML'
  - label: "Backend tests"
    command: pytest tests/backend/
    plugins:
      - mergifyio/mergify-ci#v7:
          action: junit-process
          report_path: "reports/*.xml"
YAML
fi

if echo "$SCOPES" | jq -e '.frontend == "true"' > /dev/null 2>&1; then
  cat <<'YAML'
  - label: "Frontend tests"
    command: npm test
    plugins:
      - mergifyio/mergify-ci#v7:
          action: junit-process
          report_path: "reports/*.xml"
YAML
fi
# pipeline.yml
steps:
  - label: "Detect scopes"
    key: scopes
    plugins:
      - mergifyio/mergify-ci#v7:
          action: scopes

  - label: "Upload pipeline"
    depends_on: scopes
    command: .buildkite/dynamic-pipeline.sh | buildkite-agent pipeline upload

Configuration

Authentication is not one of these properties: the token comes from MERGIFY_TOKEN in the agent environment, see Authentication.

Property Required Default Description
action yes junit-process, scopes, scopes-git-refs, or scopes-upload
token no Mergify token taken from plugin config. Plugin config is stored with the pipeline, so only set this to a value that is not a secret, such as a mock token. See Authentication
report_path for junit-process Glob path to JUnit XML files
scopes no Comma-separated list of scopes. If not set, scopes-upload reads from mergify-ci.scopes meta-data
mergify_api_url no https://api.mergify.com Mergify API endpoint
job_name no Step label Override job name (useful for matrix builds)
mergify_config_path no Path to .mergify.yml configuration file
mergify_cli_version no pinned default Version of mergify-cli to install. Leave unset to use the plugin's pinned default (kept current by Renovate, see hooks/environment), pin an exact release (e.g. 2026.6.16.1, must be >= 2026.6.15.1), or use latest to always install the newest released version.

Meta-data

The plugin stores the following values via buildkite-agent meta-data:

Key Set by Description
mergify-ci.base scopes, scopes-git-refs Merge-queue-aware base SHA
mergify-ci.head scopes, scopes-git-refs Merge-queue-aware head SHA
mergify-ci.source scopes, scopes-git-refs Reference source (e.g. buildkite_pull_request, merge_queue)
mergify-ci.scopes scopes JSON mapping of scope names to "true"/"false"

Annotations

The mergify-cli writes Buildkite annotations (context: mergify-ci-scopes) showing the detected scopes as a table. Annotations are written at both build scope (visible on the build page) and job scope (visible on the job card).

Requirements

mergify-cli is installed as a prebuilt binary (no Python required), downloaded and checksum-verified by the upstream install.sh. Supported platforms: Linux (x86_64, aarch64) and macOS (x86_64, aarch64).

  • curl (to download the installer and the binary)
  • tar (to extract the binary)
  • sha256sum or shasum (to verify the binary checksum)
  • jq (for JSON processing in scopes-upload)

Development

Running tests

The suite drives the plugin for real, so it needs the same jq listed under Requirements. Without it the scopes-upload tests fail with exit 127.

bats tests/

CI runs them in GitHub Actions (.github/workflows/ci.yaml), which reports the ci-gate check that merges are gated on.

License

Apache 2.0 — see LICENSE.

About

Mergify integration for Buildkite — JUnit processing, scope detection, and scope upload

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages