Skip to content

refactor(release): squash+재정렬 대신 fast-forward 승격 (#480) - #484

Merged
lidge-jun merged 1 commit into
devfrom
codex/480-ff-promotion
Aug 26, 2026
Merged

refactor(release): squash+재정렬 대신 fast-forward 승격 (#480)#484
lidge-jun merged 1 commit into
devfrom
codex/480-ff-promotion

Conversation

@parkjs101

Copy link
Copy Markdown
Collaborator

#480 의 핵심 구조 변경. 머지 전에 브랜치 보호를 바꿀 필요는 없다 — 확인 결과 mainenforcement_level: non_admins 이고 릴리스는 admin 이 돌리므로 ff push 가 현재 설정 그대로 통과한다. preview/dev 는 애초에 무보호다.

문제

승격이 preview 를 squash 해 main 에 얹으면 main 은 preview 에 없는 커밋을 하나 갖게 되고, 그 순간 조상 관계가 끊긴다. 그런데 promote-to-main.sh:41 은 다음 사이클 시작에서 바로 그 관계를 요구한다. 스크립트가 매 릴리스 자기 전제를 깨뜨렸다.

#468 이 자동 재정렬로 증상을 막았지만 dev 와 preview 에 각각 별개의 커밋을 만들었다:

ad223a05 (dev)      parents=b691e6ff 8db06a5b  tree=fd6b3379
c477f9e1 (preview)  parents=b691e6ff 8db06a5b  tree=fd6b3379
→ NOT ancestors of each other

부모도 트리도 같고 SHA 만 다른 쌍둥이가 8개 누적됐고, previewdev 의 조상이 아니게 됐다.

해결

stable 범프를 승격 브랜치가 아니라 preview 위에 커밋하고, preview 를 거기까지 ff 한 뒤, CI 인증이 끝나면 main 을 같은 커밋으로 ff 한다. main 은 preview 에 없는 커밋을 가질 수 없으므로 재정렬할 것이 없다.

부수 효과:

  • 발행 SHA 가 CI 인증 SHA 와 문자 그대로 같아져 publish.ymlcertified-sha 트리 대조 우회 장치가 불필요해졌다 (-80줄)
  • main push 는 --force 를 쓰지 않는다. non-ff 를 git 이 스스로 거부하는 것이 이 구조의 실제 보증이다
  • 원격 승격 브랜치를 만들지 않으므로 그 정리 실패 경로(과거 5개 브랜치 누수)도 사라졌다

preview push 는 --force-with-lease="refs/heads/preview:$PREVIEW_SHA" 로 인증 SHA 에 묶여 있다. 게이트가 도는 동안 preview 가 움직였다면 밀어버리지 않고 거부된다.

순 -343줄

 .github/workflows/publish.yml                    |  80 +------
 AGENTS.md                                        |  54 +++--
 scripts/promote-to-main.sh                       | 254 +++++++++--------------
 scripts/promotion-checkout.sh                    |  55 +----
 tests/integration/promotion-fast-forward.test.ts | 170 +++++++++++++++
 tests/integration/promotion-realign.test.ts      | 134 ------------
 tests/unit/release-scripts-contract.test.ts      | 106 +++-------
 tests/unit/safe-install.test.ts                  |   5 +-

테스트

promotion-realign.test.tspromotion-fast-forward.test.ts 로 교체했다. 실제 git 저장소를 만들어 검증하는 방식은 유지했다 — 조상 관계와 트리 동일성은 실제 객체 그래프로만 증명된다.

FFP-004음성 대조군이다: squash 승격이 조상 관계를 끊는다는 것을 명시적으로 검증해, 누군가 --squash 를 되돌리면 그 이유가 테스트에 드러나게 했다.

promotion-checkout / promotion-fast-forward / installer-sensitive-path-parity
safe-install / release-scripts-contract     →  78 tests, 78 pass, 0 fail

safe-install.test.tsSAF-004j3 은 사라진 승격 브랜치 push 문자열을 찾고 있어서 깨졌다. 증거 게이트가 첫 ref 이동 명령보다 앞선다는 원래 의도는 유지한 채, 대상을 preview ff push 로 바꿨다.

전체 스위트에서 나온 나머지 실패 6건(acp-logging, clone P3-*, dispatch-cli-contract)은 baseline 에서도 동일하게 실패하며, 이 PR 이 건드린 파일을 참조하지 않는다.

Draft 인 이유

실제 릴리스 경로를 바꾸는 변경이라 다음 릴리스가 첫 실행이 된다. #480 에서 방향이 승인된 뒤 머지하는 게 맞다.

머지 후에도 남는 일:

  • 누적된 쌍둥이 8개 정리 (ref 조작이라 PR 범위 밖, 별도 승인 필요)
  • dev 기본 브랜치 전환 (admin 전용, 릴리스 동작과 무관)

…#480)

승격이 preview 를 squash 해 main 에 얹으면 main 은 preview 에 없는 커밋을 하나
갖게 되고, 그 순간 조상 관계가 끊긴다 — 그런데 promote-to-main.sh 는 다음
사이클 시작에서 바로 그 관계를 요구한다. 스크립트가 매 릴리스 자기 전제를
깨뜨렸다.

#468 이 자동 재정렬로 증상을 막았지만, dev 와 preview 에 각각 별개의 커밋을
만들어 두 브랜치를 영구히 갈라놓았다. 부모도 트리도 같고 SHA 만 다른 쌍둥이가
8개 누적됐고 preview 는 dev 의 조상이 아니게 됐다.

stable 범프를 승격 브랜치가 아니라 preview 위에 커밋하고 main 을 같은 커밋으로
ff 한다. main 은 preview 에 없는 커밋을 가질 수 없으므로 재정렬할 것이 없다.

- 발행 SHA 가 CI 인증 SHA 와 문자 그대로 같아져 publish.yml 의 certified-sha
  트리 대조 우회 장치가 불필요해졌다
- main push 는 --force 를 쓰지 않는다. non-ff 를 git 이 거부하는 것이 이 구조의
  실제 보증이다
- 원격 승격 브랜치를 만들지 않으므로 그 정리 실패 경로도 사라졌다

promotion-realign.test.ts 를 promotion-fast-forward.test.ts 로 교체했다. 실제
git 저장소로 검증하는 방식은 유지하고, squash 가 조상 관계를 끊는다는 것을
음성 대조군(FFP-004)으로 남겨 재도입 시 드러나게 했다.
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lidge-jun
lidge-jun merged commit fdcf4ce into dev Aug 26, 2026
10 checks passed
@lidge-jun
lidge-jun deleted the codex/480-ff-promotion branch August 26, 2026 15:04
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.

2 participants