Skip to content

ci: PR 검증을 단일 required gate로 묶고 stale run을 자동 취소 #848

Closed

Description

@1hyok

현황

active ruleset required-checks (develop·main)은 현재 guard context 하나만 요구한다. #683에서 PR base 전환 시 검증이 0건이던 trigger 문제는 고쳤지만 lint·unit-test·screenshot은 여전히 merge를 막는 required check가 아니다. 이 job들에는 PR concurrency도 없어 새 commit 뒤 오래된 실행이 계속 돈다.

Hampouch-Server의 final aggregate job 패턴을 적용해 ruleset이 workflow/job 이름 변화에 덜 취약한 canonical gate를 제공한다.

관련

범위

  • PR 검증을 하나의 orchestration workflow 또는 reusable workflow 집합으로 구성한다.
  • static analysis, unit test, screenshot, repository quality 결과를 needs로 모으는 ci-gate job을 둔다.
  • ci-gate는 if: always()에서 각 선행 job conclusion을 명시적으로 검사해 failed·cancelled·의도치 않은 skipped를 실패로 판정한다.
  • workflow+PR 또는 head ref 기반 concurrency group과 cancel-in-progress를 적용한다.
  • stacked PR과 base 변경에서도 check가 생성되도록 pull_request branch filter를 다시 도입하지 않는다.
  • ruleset은 guard와 안정된 ci-gate만 required로 요구한다.
  • CodeQL은 안정화 후 별도 required check로, androidTest는 경로·주기 실측 후 비용 대비 가치가 있을 때 편입한다.
  • Kover 수치는 report-only이며 gate 조건으로 쓰지 않는다.

완료 조건

  • lint·unit·screenshot·quality 중 하나를 의도적으로 실패시키면 ci-gate와 mergeability가 실패한다.
  • 모두 성공하면 ci-gate가 성공하고 ruleset required context와 정확히 일치한다.
  • 새 commit push 시 이전 동일 PR run이 cancelled되고 최신 SHA 결과만 유효하다.
  • skipped job이 성공으로 오인되지 않는다.
  • draft/stacked/base 변경 시 pending forever 상태가 생기지 않는다.
  • ruleset 재조회에서 guard와 ci-gate가 required로 확인된다.

근거

Activity

  1. self-assigned this
    on Aug 21, 2026
  2. 1hyok commented on Aug 24, 2026

    @1hyok
    CollaboratorAuthor

    concurrency 항목만 #1000 에서 이행했다 (lint · unit-test · screenshot). 이 이슈는 닫지 않는다.

    남은 범위

    • ci-gate 집계 job (orchestration workflow, if: always() 로 선행 job conclusion 명시 검사)
    • ruleset 에 ci-gate 를 required 로 추가

    merge-order-guard 는 이번에 제외했다. 같은 파일을 고치는 #999 가 열려 있어 충돌한다. 실측 0분 job 이라 concurrency 이득도 미미하다. #999 머지 뒤 후속으로 건다 — 이 job 은 pull_request 와 issues 두 이벤트를 받으므로 group 에 github.event.issue.number 를 포함하고 cancel-in-progress 를 ${{ github.event_name == 'pull_request' }} 로 둬야 한다. issues 이벤트의 refresh job 은 다른 PR 들의 guard 를 재실행하는 중이라 취소되면 대상이 통째로 누락된다.

  3. 1hyok commented on Aug 25, 2026

    @1hyok
    CollaboratorAuthor

    ruleset 전환 완료 — required 를 ci-gate 로 옮겼다 (0825)

    #1038 머지와 함께 ruleset 20911039 의 required_status_checks 를 교체했다.

    required contexts
    전 guard, Run Unit Tests, Check Code Quality (Ktlint), Check Project Issues (Android Lint), Validate Compose Preview Screenshots, Repository Quality, Analyze (java-kotlin), Analyze (actions)
    후 guard, ci-gate, Analyze (java-kotlin), Analyze (actions)

    이름이 바뀐 5종을 ci-gate 하나로 접었다. CodeQL 2종은 이 PR 범위 밖이지만 원래 required 였고 이름도 안 바뀌어 그대로 뒀다 — 여기서 빼면 전환을 핑계로 게이트가 줄어든다.

    순서를 뒤집어야 했다

    PR 본문은 "머지 직후 ruleset 을 갱신" 하라고 적었지만 그 순서로는 진행할 수 없었다. 검증 워크플로가 workflow_call 로 바뀌면서 체크 이름이 Unit Test / Run Unit Tests 형태가 됐고, ruleset 이 요구하던 옛 이름 5종은 #1038 에 영영 도착하지 않는다. 체크 14개가 전부 SUCCESS 인데 mergeStateStatus: BLOCKED 로 굳은 상태였다.

    ci-gate 는 #1038 이 이미 SUCCESS 로 내고 있었으므로, required 를 먼저 새 구성으로 바꾸자 그 자리에서 CLEAN 이 됐고 그대로 머지했다.

    게이트가 실제로 막는지 실측

    의도적 실패를 만드는 대신, 전환 자체가 그 실험이 됐다.

    • 막는다 — 전환 직후 열린 PR 23건이 전부 BLOCKED. 옛 이름 체크만 green 이고 ci-gate 가 없기 때문이다. required 가 이름만 걸어 두고 새는 상태가 아니라는 뜻이다.
    • 통과시킨다 — fix(core): 수신인 조회 실패를 빈 목록으로 낮춰 flow 예외 전파를 끊는다 (#884) #1099 에 develop 을 받아(update-branch) 새 진입점으로 다시 돌렸더니 ci-gate=SUCCESS 가 도착하고 required 4종이 모두 green 이 됐다. (이 PR 이 아직 BLOCKED 인 건 별개 ruleset 21304258 의 승인 1건이 남아서다.)
    • 새 구조가 base 경유로도 적용된다 — head 브랜치에 pr-validation.yml 이 없어도 merge ref 에 develop 의 워크플로가 들어와 그대로 실행됐다.

    열린 PR 에 필요한 조치

    ci-gate 는 새 이벤트가 있어야 생성된다. 지금 열려 있는 PR 은 develop 을 받거나 새 커밋을 올려야 게이트가 도착한다 — 그 전까지는 체크가 전부 초록이어도 BLOCKED 로 남는다.

    되돌리려면 백업해 둔 옛 required 목록으로 같은 ruleset 을 PUT 하면 된다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions