문제 해결
이 가이드는 실제로 가장 자주 부딪히는 실패 모드에 초점을 맞춥니다. 설정 로딩, 버전 관리, 레지스트리 인증, Git 상태, CI 동작입니다.
가장 안전한 진단 명령부터 시작하기
섹션 제목: “가장 안전한 진단 명령부터 시작하기”실패한 publish를 다시 시도하기 전에 아래 명령부터 실행합니다.
pubm changesets status --verbosepubm changesets version --dry-runpubm --dry-runpubm --mode ci --phase prepare이 명령들을 함께 보면 다음을 알 수 있습니다.
pubm이 어떤 버전을 릴리스하려고 생각하는지- 어떤 패키지가 영향을 받는지
- changelog 내용이 정상인지
- 자격 증명과 레지스트리 검사가 준비되었는지
Git 상태 때문에 publish가 막힘
섹션 제목: “Git 상태 때문에 publish가 막힘”증상:
- release가 publish 전에 멈춥니다.
- 오류에 더러운 working tree가 언급됩니다.
- 오류에 잘못된 브랜치가 언급됩니다.
확인할 사항:
- 로컬 변경을 commit하거나 stash합니다.
- 예상한 브랜치에 있는지 확인합니다.
- 의도적인 예외라면
--any-branch가 허용 가능한지 판단합니다.
릴리스 안전성이 약해지는 bypass 플래그는 정말 필요할 때만 표준 워크플로에 넣습니다.
버전 명령에서 changeset을 찾지 못함
섹션 제목: “버전 명령에서 changeset을 찾지 못함”증상:
pubm changesets version이No changesets found.를 출력합니다.
확인할 사항:
.pubm/changesets/에 파일이 있는지 확인합니다.- 저장소 루트에서 실행 중인지 확인합니다.
.changeset/에서 마이그레이션 중이라면pubm changesets migrate를 실행합니다.
잘못된 패키지가 bump됨
섹션 제목: “잘못된 패키지가 bump됨”증상:
- 예상하지 못한 패키지가
changesets status에 나타납니다. - fixed 또는 linked 패키지가 의도치 않게 함께 움직입니다.
확인할 사항:
pubm changesets status --verbose를 실행합니다.pubm.config.*의fixed와linked그룹을 확인합니다.- 저장소가
independent인지fixed버전 관리를 쓰는지 확인합니다.
워크스페이스 구조가 복잡하다면, 탐지에만 의존하지 말고 packages를 명시적으로 설정합니다.
설정 파일을 로드하지 못함
섹션 제목: “설정 파일을 로드하지 못함”증상:
- 릴리스 파이프라인이 시작되기 전에 startup이 실패합니다.
- 설정 import 또는 번들링 관련 오류가 납니다.
확인할 사항:
- 설정 파일 이름이 지원되는 이름 중 하나인지 확인합니다.
@pubm/core에서defineConfig를 import합니다.- 설정 모듈 최상단에서 무거운 런타임 작업을 제거합니다.
- 필요한 곳에만 선택적 의존성이 설치되어 있는지 확인합니다.
좋은 설정 파일은 대부분 선언적입니다. 파일이 애플리케이션 코드처럼 보이기 시작하면, 헬퍼를 더 작은 모듈로 분리하고 평가를 예측 가능하게 유지합니다.
npm publish가 인증 또는 권한 오류로 실패함
섹션 제목: “npm publish가 인증 또는 권한 오류로 실패함”증상:
- 401 또는 403 응답
- OTP, 2FA, publish 권한 관련 메시지
확인할 사항:
NODE_AUTH_TOKEN을 확인합니다.- 토큰에 해당 패키지의 publish 권한이 있는지 확인합니다.
- CI에서는 자동화 호환 토큰을 우선 사용합니다.
- 패키지 접근 수준이 레지스트리 기대값과 맞는지 확인합니다.
저장소가 scoped public 패키지를 publish한다면, 해당 패키지가 npm에서 public이어야 하는지도 확인합니다.
jsr publish가 실패함
섹션 제목: “jsr publish가 실패함”증상:
- jsr 대상만 실패하고 npm은 성공합니다.
확인할 사항:
JSR_TOKEN을 확인합니다.pubm --mode ci --phase prepare를 실행합니다.- 패키지 메타데이터가 jsr에 유효한지 확인합니다.
pubm은 여러 대상을 동시에 publish하므로, 실패한 레지스트리를 바로잡아야 합니다. 무작정 다시 시도하면 부분 릴리스 혼란만 커집니다.
crates.io publish가 실패함
섹션 제목: “crates.io publish가 실패함”증상:
- Rust 패키지 publish가 실패합니다.
- 한 crate는 성공했지만, 나중 순서의 다른 crate가 막힙니다.
확인할 사항:
CARGO_REGISTRY_TOKEN을 확인합니다.- crate 의존성 순서와 버전이 유효한지 확인합니다.
pubm.config.*의 패키지별registries덮어쓰기를 확인합니다. 추론을 쓰는 경우라면 매니페스트 파일도 함께 확인합니다.
순서가 중요할 때 Rust publish는 순차적으로 진행됩니다. 이것은 정상이며, 보통 pubm이 의존성 정합성을 지키고 있다는 뜻입니다.
pubm 내부에서 빌드나 테스트 단계가 실패함
섹션 제목: “pubm 내부에서 빌드나 테스트 단계가 실패함”증상:
- release가 테스트나 빌드 도중 멈춥니다.
- 오류 메시지가 underlying script를 다시 실행하라고 제안합니다.
할 일:
- 스크립트를 직접 다시 실행합니다.
- 실제 빌드 또는 테스트 실패를 수정합니다.
pubm을 다시 시도합니다.
예:
pnpm run testpnpm run build스크립트 이름이 다르면 설정이나 CLI 플래그와 맞춥니다.
pubm --test-script test:ci --build-script build:releasecontents publish가 동작하지 않음
섹션 제목: “contents publish가 동작하지 않음”증상:
- publish 명령이 기대한 파일을 찾지 못합니다.
- root에서는 동작하지만
dist/에서는 실패합니다.
확인할 사항:
contents가 최종 publish 디렉터리를 가리키는지 확인합니다.- build 단계가 publish 시작 전에 그 디렉터리를 만드는지 확인합니다.
- 대상 디렉터리에 선택한 레지스트리가 기대하는 매니페스트 파일이 있는지 확인합니다. (npm은
package.json, jsr은jsr.json또는deno.json/deno.jsonc, crates는Cargo.toml)
contents는 런타임 파이프라인의 working directory를 바꿉니다. 단순한 출력 폴더가 아니라 publish root로 취급해야 합니다.
CI가 로컬 실행과 다르게 동작함
섹션 제목: “CI가 로컬 실행과 다르게 동작함”증상:
- 로컬 publish는 성공합니다.
- CI publish는 실패하거나 멈춥니다.
이유:
- CI에서는 프롬프트가 비활성화됩니다.
- 토큰은 환경 변수나 이전 secret sync에서 와야 합니다.
- 얕은 checkout은 태그 인식 흐름을 자주 깨뜨립니다.
확인할 사항:
- 로컬에서
pubm --mode ci --phase prepare를 실행합니다. - CI에서는 전체 Git 히스토리를 사용합니다.
- job 환경에 필요한 토큰이 모두 들어 있는지 확인합니다.
GitHub Release 문제
섹션 제목: “GitHub Release 문제”증상:
- release 생성이 실패합니다.
- release 메타데이터가 불완전해 보입니다.
확인할 사항:
- repository remote 메타데이터가 유효한지 확인합니다.
- Git 태그가 존재하고 push되어 있는지 확인합니다.
- 일반 publish 흐름과
--mode ci --phase publish를 구분합니다.
pubm은 GitHub API를 통해 GitHub Release를 만듭니다. 로컬 모드에서 GITHUB_TOKEN이 없으면 토큰을 입력하거나, 브라우저에서 draft를 열거나, 건너뛸 수 있습니다. --mode ci --phase publish는 파이프라인의 일부로 GitHub Release를 생성합니다.
롤백이 일어나고 저장소 상태가 헷갈림
섹션 제목: “롤백이 일어나고 저장소 상태가 헷갈림”증상:
- publish가 실행 도중 실패했습니다.
- 태그나 커밋이 만들어졌다가 제거되었습니다.
할 일:
git tag로 현재 태그를 확인합니다.git status로 working tree 상태를 확인합니다.- 어떤 단계가 먼저 실패했는지 이해한 뒤에만 다시 실행합니다.
중요한 것은 롤백 메시지보다 원래 원인을 진단하는 일입니다.
롤백 unpublish 후 버전 소진
섹션 제목: “롤백 unpublish 후 버전 소진”증상:
- publish가 실패하고 롤백이 실행되어 npm에서 패키지를 unpublish했거나 crates.io에서 yank했습니다.
- 같은 버전으로 다시 publish하려 하면 이미 사용 중인 버전이라는 오류가 납니다.
무슨 일이 일어났는가:
npm unpublish는 패키지 tarball을 삭제하지만 버전 번호는 영구적으로 예약됩니다. 재사용할 수 없습니다. crates.io의 cargo yank도 해당 버전을 사용 불가로 표시합니다.
할 일:
- 새 버전으로 올리고(예:
1.2.3대신1.2.4) 다시 publish합니다. - CI에서는 버전 소진을 방지하기 위해 unpublish가 기본적으로 건너뜁니다.
--dangerously-allow-unpublish를 사용하거나 config에서rollback.dangerouslyAllowUnpublish: true로 설정하면 활성화됩니다.
이슈를 열어야 할 때
섹션 제목: “이슈를 열어야 할 때”다음 정보를 포함해서 문제를 재현할 수 있다면 이슈를 엽니다.
- 정확한 명령
- 관련 설정
- 대상 레지스트리
- 기대한 동작
- 실제 동작과 오류 출력
특히 가치가 큰 버그 보고는 다음 경우입니다.
- JS와 Rust가 섞인 저장소
- 플러그인이 제공하는 레지스트리
- 설정 로더의 엣지 케이스
- 부분 실패 후의 롤백 동작
유용한 복구 워크플로
섹션 제목: “유용한 복구 워크플로”release가 실패했고 보수적으로 복구하고 싶다면:
git statusgit tag --sort=-creatordate | headpubm changesets status --verbosepubm changesets version --dry-runpubm --dry-runpubm --mode ci --phase prepare실제 publish는 dry-run과 CI 준비 출력이 다시 말이 될 때만 재실행합니다.