# GitHub Actions

> Send deployment markers to Last9 from GitHub Actions workflows to correlate deployments with service performance and error rates.

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

The [Last9 Deployment Marker action](https://github.com/marketplace/actions/last9-deployment-marker) sends deployment markers to Last9's [Change Events API](/docs/change-events/) directly from your GitHub Actions workflows. 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).
- The `env` value must match the `deployment_environment` label on your APM services for automatic dashboard correlation.

Store your refresh token as a [GitHub Actions secret](https://docs.github.com/en/actions/security-guides/encrypted-secrets) named `LAST9_REFRESH_TOKEN`.

## Setup

Add the action to any job in your workflow:

```yaml
- name: Mark deployment in Last9
  uses: last9/deployment-marker-action@v1
  with:
    refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
    org_slug: your-org-slug
    env: production
```

By default, this sends a `stop` event with `event_name: deployment`. The `service_name` defaults to your repository name.

## Configuration Reference

| Input                       | 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 exactly for dashboard correlation |
| `service_name`              | No       | Repository name        | Service identifier. Must match your APM `service_name` label for dashboard correlation                       |
| `event_state`               | No       | `stop`                 | `start`, `stop`, or `both`. Use `both` to fire start and stop atomically from a single step                  |
| `event_name`                | No       | `deployment`           | Custom label for the event. Appears as a label on the resulting `last9_change_events` metric                 |
| `custom_attributes`         | No       | —                      | Additional metadata as a JSON string (e.g. `{"team":"platform","ticket":"ENG-123"}`)                         |
| `include_github_attributes` | No       | `true`                 | Automatically attach workflow context: commit SHA, actor, branch, run ID, and repository                     |
| `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                                                 |

### Outputs

| Output            | Description                                                                    |
| ----------------- | ------------------------------------------------------------------------------ |
| `success`         | `true` if the event was delivered successfully                                 |
| `start_timestamp` | ISO8601 timestamp of the start event (when `event_state` is `start` or `both`) |
| `stop_timestamp`  | ISO8601 timestamp of the stop event (when `event_state` is `stop` or `both`)   |

## CI/CD Workflows

### Mark deployment complete

The simplest pattern — a single step that fires both start and stop atomically after the deployment finishes:

```yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        run: ./deploy.sh

      - name: Mark deployment in Last9
        if: always()
        uses: last9/deployment-marker-action@v1
        with:
          refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
          org_slug: your-org-slug
          env: production
          event_state: both
```

:::tip
Using `if: always()` ensures the marker fires even when the deploy step fails, giving you accurate failure correlation in Last9.
:::

### Track deployment duration

Use `start` and `stop` events to bracket the actual deploy step and capture deployment duration on your dashboards:

```yaml
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Mark deployment start
        uses: last9/deployment-marker-action@v1
        with:
          refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
          org_slug: your-org-slug
          env: production
          event_state: start

      - name: Deploy
        run: ./deploy.sh

      - name: Mark deployment complete
        if: always()
        uses: last9/deployment-marker-action@v1
        with:
          refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
          org_slug: your-org-slug
          env: production
          event_state: stop
```

### Track rollbacks

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

```yaml
- name: Mark rollback in Last9
  if: always()
  uses: last9/deployment-marker-action@v1
  with:
    refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
    org_slug: your-org-slug
    env: production
    event_state: both
    event_name: rollback
    custom_attributes: '{"rolled_back_to": "${{ env.PREVIOUS_VERSION }}"}'
```

### Multi-environment deployments

Use `github.event.inputs` or a matrix to pass the environment dynamically:

```yaml
on:
  workflow_dispatch:
    inputs:
      environment:
        description: "Target environment"
        required: true
        default: staging

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        run: ./deploy.sh ${{ github.event.inputs.environment }}

      - name: Mark deployment in Last9
        if: always()
        uses: last9/deployment-marker-action@v1
        with:
          refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
          org_slug: your-org-slug
          env: ${{ github.event.inputs.environment }}
          event_state: both
```

### Custom attributes

Attach additional context — version, team, ticket ID — as queryable labels on the `last9_change_events` metric:

```yaml
- name: Mark deployment in Last9
  if: always()
  uses: last9/deployment-marker-action@v1
  with:
    refresh_token: ${{ secrets.LAST9_REFRESH_TOKEN }}
    org_slug: your-org-slug
    env: production
    service_name: payments-api
    event_state: both
    custom_attributes: >
      {
        "version": "${{ github.sha }}",
        "team": "platform",
        "ticket_id": "${{ github.event.head_commit.message }}"
      }
```

## Auto-captured GitHub Context

When `include_github_attributes` is `true` (the default), the action automatically attaches the following to every event:

| Attribute           | Source                                               |
| ------------------- | ---------------------------------------------------- |
| `github_sha`        | `github.sha` — the commit being deployed             |
| `github_actor`      | `github.actor` — the user who triggered the workflow |
| `github_ref`        | `github.ref` — the branch or tag ref                 |
| `github_run_id`     | `github.run_id` — links back to the workflow run     |
| `github_repository` | `github.repository` — the repo name                  |

These labels are queryable in PromQL alongside your custom attributes:

```promql
last9_change_events{event_name="deployment", github_actor="alice"}
```

## 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_name` must equal the `service_name` label on your APM services (defaults to the repository name 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.
