# Release health: lỗi nào tệ hơn sau mỗi lần deploy, bản sửa đã hết lỗi chưa

> Ghi release và deploy marker từ CI bằng sentry-cli hoặc REST, xem lỗi mới, quay lại và tăng trong 24 giờ đầu của mỗi release, đánh dấu xong ở một release và kiểm bản sửa theo từng môi trường.

Mỗi lần deploy đều có hai câu hỏi: **lỗi nào tệ hơn sau release này?** và **bản sửa đã thật sự hết lỗi chưa?** Release health trả lời cả hai từ dữ liệu trên node của bạn — trong app (Project → Release, và trang issue), qua REST API và qua MCP `release_health`.

## Cần chuẩn bị

1. **Tên release trên mọi event.** Đặt `release` trong `init` của SDK, ví dụ commit SHA hoặc `web@1.4.2`. Cùng tên đó dùng cho lần tải source map và deploy marker.
2. **Một deploy marker cho mỗi lần deploy.** Marker cho Belvador biết release bắt đầu chạy ở một môi trường từ lúc nào. Không có marker thì cửa sổ của release bắt đầu từ event đầu tiên và bản sửa không bao giờ được xác minh.
3. Node chạy agent 0.1.38 trở lên. Node tự cập nhật; tab Release sẽ báo khi node của bạn còn cũ.

## Ghi release và deploy từ CI

Dùng cùng token upload với source map (Cài đặt project → Token upload). Token tạo từ khi có release health vừa tải được source map **vừa** ghi được release và deploy; token cũ hơn trả `403` kèm tên scope còn thiếu `releases:write` — hãy tạo token mới.

```bash
export SENTRY_URL=https://edge.belvador.dev
export SENTRY_AUTH_TOKEN="$BELVADOR_UPLOAD_TOKEN"
export SENTRY_ORG=belvador SENTRY_PROJECT=<project-slug>
npx @sentry/cli releases new "$RELEASE"
npx @sentry/cli releases set-commits "$RELEASE" --local
npx @sentry/cli releases finalize "$RELEASE"
npx @sentry/cli deploys new --release "$RELEASE" -e production
```

- `set-commits --local` chỉ gửi SHA và tên repository của mỗi commit. Tên tác giả, e-mail, nội dung commit và danh sách file bị bỏ ngay ở edge, không bao giờ tới node.
- `--auto` cần tích hợp repository mà Belvador không cung cấp; lệnh sẽ tự chuyển sang `--local`.
- Chạy `deploys new` một lần cho mỗi môi trường, sau khi deploy thành công.

### Không dùng sentry-cli

CI nào cũng gửi được deploy marker tới REST API bằng token có scope `releases:write` (Cài đặt → API token):

```bash
curl -fsS -X POST "https://api.belvador.dev/v1/projects/<project-id>/deployments" \
  -H "Authorization: Bearer $BELVADOR_TOKEN" -H "Content-Type: application/json" \
  -d "{\"version\":\"$RELEASE\",\"environment\":\"production\",\"deploy_id\":\"$CI_PIPELINE_ID\"}"
```

`deploy_id` không bắt buộc: gửi lại cùng một marker (job chạy lại) không thay đổi gì.

## Release health

Project → Release liệt kê các release của một môi trường, lần deploy mới nhất lên đầu; release chưa có marker được xếp theo semver. Mỗi dòng có số event mỗi giờ so với release trước và ba con số trong **24 giờ đầu** của release (tính từ lần deploy đầu, hoặc từ event đầu nếu chưa có marker):

| Danh sách | Issue nằm trong đó khi |
|---|---|
| Mới | event đầu tiên của issue ở môi trường này mang release này |
| Quay lại | issue đã được đánh dấu xong rồi quay lại cùng release này |
| Tăng | số event mỗi giờ ít nhất gấp 2 lần release trước, và có ít nhất 10 event (issue mới không lặp lại ở đây) |

Mở một release để xem ba danh sách (tối đa 50 issue mỗi danh sách, kèm biểu đồ theo giờ), deploy marker và commit của nó. **So với** chọn một release khác thay cho release trước.

## Đánh dấu xong ở một release

Trên một issue, **Đánh dấu xong → Xong ở release…** coi issue đã được sửa từ release R trở đi:

- event từ R hoặc release mới hơn sẽ mở lại issue với trạng thái quay lại;
- event từ release cũ hơn vẫn đang chạy thì không — bản cũ được coi là còn lỗi cho tới khi bị thay thế.

"Mới hơn" theo thứ tự deploy ở môi trường đó, rồi tới semver. Khi không xếp được hai release theo cách nào, issue chỉ mở lại với event tới sau lúc đánh dấu, như trước đây. **Đánh dấu xong** và **Xong ở release tiếp theo** vẫn hoạt động như cũ.

## Trạng thái sửa lỗi

Issue đã đánh dấu xong có mục **Trạng thái sửa lỗi** cho từng môi trường mà issue xảy ra trong 30 ngày qua:

| Trạng thái | Ý nghĩa |
|---|---|
| Đã hết lỗi | release có bản sửa có deploy marker, đã chạy 24 giờ traffic, và lỗi không xảy ra ở release đó hay release nào sau nó |
| Chưa xác minh | release chưa deploy, chưa có marker, chưa có traffic, hoặc chạy chưa đủ 24 giờ |
| Chưa hết lỗi | lỗi lặp lại ở một release đã có bản sửa, hoặc issue đã quay lại |
| Không rõ | không xếp được thứ tự các release (không có deploy marker, không theo semver) |

Trạng thái chung của issue là môi trường tệ nhất. "Traffic" là mọi event, span hay log mang release đó (`service.version` với OpenTelemetry), nên app gửi trace vẫn được tính kể cả khi không có lỗi. Với **Xong ở release tiếp theo** và **Đánh dấu xong**, bản sửa được kiểm theo lần deploy đầu tiên sau lúc đánh dấu.

## API và MCP

| Request | Scope |
|---|---|
| `GET /v1/projects/{project}/releases?environment=` | `releases:read` |
| `GET /v1/projects/{project}/releases/{version}/health?environment=&compare=` | `releases:read` |
| `GET /v1/issues/{issue_id}/fix-status` | `releases:read` |
| `POST /v1/projects/{project}/deployments` | `releases:write` |
| `PATCH /v1/issues/{issue_id}` với `{"action":"resolve","in_release":"web@1.4.2"}` | `issues:write` |

MCP `release_health(project, version?, environment?, compare?)` trả cùng ba danh sách; `get_issue` thêm `fix_status` cho issue đã đánh dấu xong. Xem [tài liệu API](https://belvador.dev/vi/docs/reference/api) và [MCP](https://belvador.dev/vi/docs/mcp).

## Giới hạn

| Giới hạn | Giá trị |
|---|---|
| Tên release | 200 ký tự, không khoảng trắng, dấu gạch chéo hay ký tự điều khiển |
| Commit lưu mỗi release | 1,000 (chỉ SHA + repository) |
| Request release và deploy của sentry-cli mỗi token | 600 mỗi giờ |
| Issue mỗi danh sách health | 50 |
| Release liệt kê mỗi môi trường | 50 |

Release và deploy marker chỉ lưu trên node của bạn và bị xoá cùng project.

## Khi có gì đó sai

- **Mọi issue đều "Mới"** — môi trường đó chưa có release nào trước.
- **Trạng thái sửa lỗi mãi "Chưa xác minh"** — kiểm tra CI có chạy `deploys new` (hoặc lệnh REST) cho môi trường đó và event có mang tên release.
- **`403` kèm `releases:write`** — token upload có từ trước release health; hãy tạo token mới.
- **Tab yêu cầu cập nhật node** — node đang cũ hơn agent 0.1.38; node sẽ tự cập nhật theo kênh.
