# Buildkite

> Send deployment markers to Last9 from Buildkite pipelines to correlate deployments with service performance and error rates.

Source: https://last9.io/docs/integrations/ci-cd/buildkite/

The [Last9 Deployment Marker Buildkite Plugin](https://github.com/last9/deployment-marker-buildkite-plugin) sends deployment markers to Last9's [Change Events API](/docs/change-events/) directly from your Buildkite pipelines. Deployment events appear as overlays on your service dashboards, letting you correlate releases with performance changes, error spikes, and APDEX shifts.

## Prerequisites

- A Last9 account with an API refresh token (write scope). See [Getting Started with API](/docs/getting-started-with-api/) to generate one.
- Your Last9 organization slug (the `{org}` segment in your Last9 dashboard URL).
- `curl` and `jq` installed on your Buildkite agent (available by default on most agent environments).
- The `env` value must match the `deployment_environment` label on your APM services for automatic dashboard correlation.

Store your refresh token as a [Buildkite secret](https://buildkite.com/docs/pipelines/security/secrets/managing) or in your agent's environment hooks — never hard-code it in `pipeline.yml`.

## Setup

Add the plugin to your deploy step in `pipeline.yml`:

```yaml
steps:
  - label: ":rocket: Deploy to production"
    command: ./deploy.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "production"
```

The plugin runs `pre-command` and `post-command` hooks around your deploy step. It automatically sets `result` to:

- `success` — when your command exits with code `0`
- `failure` — when your command exits with a non-zero code

Deployment duration (`duration_ms`) is captured automatically between the two hooks and attached to the event.

## Configuration Reference

| Option                 | Required | Default                | Description                                                                                          |
| ---------------------- | -------- | ---------------------- | ---------------------------------------------------------------------------------------------------- |
| `refresh_token`        | **Yes**  | —                      | Last9 API refresh token with write scope                                                             |
| `org_slug`             | **Yes**  | —                      | Your Last9 organization slug                                                                         |
| `env`                  | **Yes**  | —                      | Deployment environment. Must match your APM `deployment_environment` label for dashboard correlation |
| `service`              | No       | Pipeline slug          | Service identifier. Must match your APM `service_name` label for dashboard correlation               |
| `event_name`           | No       | `deployment`           | Custom label for the event                                                                           |
| `data_source_name`     | No       | —                      | Last9 cluster or data source name to associate the event with                                        |
| `api_base_url`         | No       | `https://app.last9.io` | Override the Last9 API base URL                                                                      |
| `max_retry_attempts`   | No       | `3`                    | Number of retry attempts with exponential backoff on failure                                         |
| `retry_backoff_ms`     | No       | `1000`                 | Initial backoff in milliseconds between retries                                                      |
| `max_retry_backoff_ms` | No       | `30000`                | Maximum backoff cap in milliseconds                                                                  |

## Pipeline Patterns

### Mark a single deploy step

The simplest setup — add the plugin to your deploy step and it handles start, end, and result automatically:

```yaml
steps:
  - label: ":rocket: Deploy"
    command: ./deploy.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "production"
          service: "payments-api"
```

### Multiple services in one pipeline

Add the plugin to each relevant step with a distinct `service`:

```yaml
steps:
  - label: "Deploy API"
    command: ./deploy-api.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "production"
          service: "payments-api"

  - label: "Deploy Worker"
    command: ./deploy-worker.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "production"
          service: "payments-worker"
```

### Multi-environment pipelines

Pass the environment dynamically using a Buildkite [meta-data](https://buildkite.com/docs/pipelines/build-meta-data) value or pipeline variable:

```yaml
steps:
  - label: "Deploy to ${DEPLOY_ENV}"
    command: ./deploy.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "${DEPLOY_ENV}"
```

### Track rollbacks

Use a distinct `event_name` to distinguish rollbacks from regular deployments:

```yaml
steps:
  - label: ":rewind: Rollback"
    command: ./rollback.sh
    plugins:
      - last9/deployment-marker#v1.0.0:
          refresh_token: "${LAST9_REFRESH_TOKEN}"
          org_slug: "your-org-slug"
          env: "production"
          event_name: "rollback"
```

## Auto-captured Buildkite Context

The plugin automatically captures and attaches the following Buildkite context to every event:

| Attribute                 | Source                                                                |
| ------------------------- | --------------------------------------------------------------------- |
| `service`                 | `service` plugin config (or pipeline slug)                            |
| `env`                     | Plugin config                                                         |
| `result`                  | `success` / `failure` (stop event only)                               |
| `pipeline_slug`           | `BUILDKITE_PIPELINE_SLUG`                                             |
| `pipeline_name`           | `BUILDKITE_PIPELINE_NAME`                                             |
| `build_id`                | `BUILDKITE_BUILD_ID`                                                  |
| `build_number`            | `BUILDKITE_BUILD_NUMBER`                                              |
| `build_url`               | `BUILDKITE_BUILD_URL`                                                 |
| `commit_sha`              | `BUILDKITE_COMMIT`                                                    |
| `branch`                  | `BUILDKITE_BRANCH`                                                    |
| `tag`                     | `BUILDKITE_TAG`                                                       |
| `commit_message`          | `BUILDKITE_MESSAGE`                                                   |
| `actor`                   | `BUILDKITE_BUILD_CREATOR` (falls back to `BUILDKITE_BUILD_AUTHOR`)    |
| `step_label`              | `BUILDKITE_LABEL`                                                     |
| `step_key`                | `BUILDKITE_STEP_KEY`                                                  |
| `job_id`                  | `BUILDKITE_JOB_ID`                                                    |
| `source`                  | `BUILDKITE_SOURCE`                                                    |
| `retry_count`             | `BUILDKITE_RETRY_COUNT`                                               |
| `triggered_from_build_id` | `BUILDKITE_TRIGGERED_FROM_BUILD_ID`                                   |
| `rebuilt_from_build_id`   | `BUILDKITE_REBUILT_FROM_BUILD_ID`                                     |
| `duration_ms`             | Computed: time from `pre-command` to `post-command` (stop event only) |

## Service Dashboard Correlation

For deployment markers to appear as overlays on your Last9 service dashboards, two values must match your APM data exactly:

- `env` must equal the `deployment_environment` label on your APM services
- `service` must equal the `service_name` label on your APM services (defaults to the Buildkite pipeline slug if not set)

When both match, every deployment event appears as a vertical marker on your APDEX, response time, throughput, and error rate charts. See [Change Events](/docs/change-events/) for details on storage, PromQL queries, and visualisation options.

---

## Troubleshooting

Please get in touch with us on [Discord](https://discord.com/invite/Q3p2EEucx9) or [Email](mailto:support@last9.io) if you have any questions.
