Skip to content

feat(deploy): 배포 실패 사유를 분류와 상세로 나눠 응답에 싣는다 - #168

Merged
dldnsgkr merged 1 commit into
developfrom
unhak/deployment-failure-code
Aug 19, 2026
Merged

feat(deploy): 배포 실패 사유를 분류와 상세로 나눠 응답에 싣는다#168
dldnsgkr merged 1 commit into
developfrom
unhak/deployment-failure-code

Conversation

@dldnsgkr

Copy link
Copy Markdown
Collaborator

문제

배포 이력 화면에 FAILED 만 뜨고 사유가 없다. 응답에 아무것도 없어서 FE 가 보여줄 수단이 없다.

v1   LIVE
v1   FAILED        ← 왜 실패했는지 알 방법이 없다

왜 문자열만으로는 부족한가

errorMessage 만 주면 화면이 그 문자열을 파싱해 분기하게 된다. 서버가 문구를 조금만 바꿔도 조용히 깨진다. FE 도 같은 이유로 코드성 필드를 요청했다.

그래서 분류를 값으로 함께 준다.

errorCode:    WORKFLOW_FAILED | RESULT_UNKNOWN | RETRY_EXHAUSTED | null
errorMessage: 사람이 읽을 상세 | null
분류 언제 화면에서
WORKFLOW_FAILED GitHub Actions 가 실패로 끝남 실패로 보여도 된다
RESULT_UNKNOWN 회수 워커가 판정을 못 얻고 포기 실패로 단정하면 안 된다
RETRY_EXHAUSTED 재시도 한도 소진 실패

RESULT_UNKNOWN 이 이 PR 의 핵심이다. 이건 "실패했다"가 아니라 "결과를 확인하지 못했다"이다. 웹훅을 놓친 이력을 회수하려던 워커(#161)가 GitHub 에서 실행을 찾지 못하고 포기한 경우이고, 사이트는 실제로 떠 있을 수 있다. 운영에 그렇게 닫힌 이력이 지금 한 건 있는데(projectId=11, historyId=1) 화면에는 그냥 실패로 보인다. 두 경우를 화면이 다르게 말하려면 분류가 값으로 있어야 한다.

옛 이력

errorCodenull 로 남는다. 분류를 붙이기 전에 실패한 것들이라 되살릴 근거가 없다. FE 와 합의했다 — errorCode 가 있으면 매핑한 문구를, 없고 errorMessage 만 있으면 그 문자열을 그대로, 둘 다 없으면 상태만 보여준다.

변경

  • DeployFailureCode 추가. DeploymentHistoryerrorMessage 와 함께 보관
  • complete() 가 분류도 지운다 — 재시도로 되살아난 이력이 옛 분류를 달고 있으면 화면이 성공한 배포를 실패로 그린다
  • V32 마이그레이션: failure_code VARCHAR(40) NULL
  • 실패를 만드는 지점 셋에서 분류를 정한다(웹훅 · 회수 워커 · 재시도 소진)
  • 목록(GET /projects/{id}/deployments)과 상세(GET /deployments/{id})에 동일하게 노출

기존 27인자 생성자는 그대로 두고 분류를 받는 생성자를 따로 뒀다. 테스트와 옛 호출부가 그대로 컴파일되고, 그 경로로 만들면 분류가 null 이 된다.

검증

  • 마이그레이션 V32(컬럼 추가, NULL 허용). 기존 행 영향 없음
  • 테스트 추가: 재시도가 한도 안이면 분류를 찍지 않는지 / 소진하면 RETRY_EXHAUSTED / 성공하면 옛 분류가 지워지는지 / 분류와 상세가 함께 저장되는지
  • 회수 워커 테스트에 단언 추가: 판정을 얻으면 WORKFLOW_FAILED, 못 얻으면 RESULT_UNKNOWN 으로 갈리는지
  • ./gradlew test 전체 통과(통합 테스트가 V32 를 실제로 적용한다)

FE 영향

FE 가 요청한 형태 그대로다. 문구 매핑은 FE 에서 한다 — 서버가 사용자용 문구를 만들려 하면 같은 사건을 두 곳이 서술하게 된다.

🤖 Generated with Claude Code

배포 이력 화면에 FAILED 만 뜨고 사유가 없었다. 응답에 아무것도 없어서 FE 가 보여줄
수단이 없었다.

errorMessage 만 주면 화면이 그 문자열을 파싱해 분기하게 된다. 서버가 문구를 조금만
바꿔도 조용히 깨지는 구조다. 그래서 분류를 값으로 함께 준다.

  errorCode:    WORKFLOW_FAILED | RESULT_UNKNOWN | RETRY_EXHAUSTED | null
  errorMessage: 사람이 읽을 상세 | null

RESULT_UNKNOWN 이 특히 중요하다. 이건 "실패했다"가 아니라 "결과를 확인하지 못했다"
이다. 웹훅을 놓친 이력을 회수하려던 워커가 GitHub 에서 실행을 찾지 못하고 포기한
경우이고, 사이트는 실제로 떠 있을 수 있다. 운영에 그렇게 닫힌 이력이 한 건 있는데
지금 화면에는 그냥 실패로 보인다. 화면이 두 경우를 다르게 말하려면 분류가 값으로
있어야 한다.

옛 이력은 errorCode 가 null 로 남는다. 분류를 붙이기 전에 실패한 것들이라 되살릴
근거가 없다 — FE 는 errorCode 없이 errorMessage 만 있는 경우를 처리하기로 했다.

- DeployFailureCode 추가, DeploymentHistory 가 errorMessage 와 함께 보관
- complete() 가 분류도 지운다. 재시도로 되살아난 이력이 옛 분류를 달고 있으면
  화면이 성공한 배포를 실패로 그린다
- V32 마이그레이션으로 failure_code 컬럼 추가(NULL 허용)
- 실패를 만드는 지점 셋에서 분류를 정한다: 웹훅(WORKFLOW_FAILED), 회수 워커
  (판정을 얻으면 WORKFLOW_FAILED, 못 얻으면 RESULT_UNKNOWN), 재시도 소진
  (RETRY_EXHAUSTED)
- 목록·상세 두 엔드포인트에 동일하게 노출

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dldnsgkr
dldnsgkr merged commit add427f into develop Aug 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant