콘텐츠로 이동

문제 해결

이 가이드는 실제로 가장 자주 부딪히는 실패 모드에 초점을 맞춥니다. 설정 로딩, 버전 관리, 레지스트리 인증, Git 상태, CI 동작입니다.

가장 안전한 진단 명령부터 시작하기

섹션 제목: “가장 안전한 진단 명령부터 시작하기”

실패한 publish를 다시 시도하기 전에 아래 명령부터 실행합니다.

Terminal window
pubm changesets status --verbose
pubm changesets version --dry-run
pubm --dry-run
pubm --mode ci --phase prepare

이 명령들을 함께 보면 다음을 알 수 있습니다.

  • pubm이 어떤 버전을 릴리스하려고 생각하는지
  • 어떤 패키지가 영향을 받는지
  • changelog 내용이 정상인지
  • 자격 증명과 레지스트리 검사가 준비되었는지

증상:

  • release가 publish 전에 멈춥니다.
  • 오류에 더러운 working tree가 언급됩니다.
  • 오류에 잘못된 브랜치가 언급됩니다.

확인할 사항:

  • 로컬 변경을 commit하거나 stash합니다.
  • 예상한 브랜치에 있는지 확인합니다.
  • 의도적인 예외라면 --any-branch가 허용 가능한지 판단합니다.

릴리스 안전성이 약해지는 bypass 플래그는 정말 필요할 때만 표준 워크플로에 넣습니다.

버전 명령에서 changeset을 찾지 못함

섹션 제목: “버전 명령에서 changeset을 찾지 못함”

증상:

  • pubm changesets versionNo changesets found.를 출력합니다.

확인할 사항:

  • .pubm/changesets/에 파일이 있는지 확인합니다.
  • 저장소 루트에서 실행 중인지 확인합니다.
  • .changeset/에서 마이그레이션 중이라면 pubm changesets migrate를 실행합니다.

증상:

  • 예상하지 못한 패키지가 changesets status에 나타납니다.
  • fixed 또는 linked 패키지가 의도치 않게 함께 움직입니다.

확인할 사항:

  • pubm changesets status --verbose를 실행합니다.
  • pubm.config.*fixedlinked 그룹을 확인합니다.
  • 저장소가 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 대상만 실패하고 npm은 성공합니다.

확인할 사항:

  • JSR_TOKEN을 확인합니다.
  • pubm --mode ci --phase prepare를 실행합니다.
  • 패키지 메타데이터가 jsr에 유효한지 확인합니다.

pubm은 여러 대상을 동시에 publish하므로, 실패한 레지스트리를 바로잡아야 합니다. 무작정 다시 시도하면 부분 릴리스 혼란만 커집니다.

증상:

  • Rust 패키지 publish가 실패합니다.
  • 한 crate는 성공했지만, 나중 순서의 다른 crate가 막힙니다.

확인할 사항:

  • CARGO_REGISTRY_TOKEN을 확인합니다.
  • crate 의존성 순서와 버전이 유효한지 확인합니다.
  • pubm.config.*의 패키지별 registries 덮어쓰기를 확인합니다. 추론을 쓰는 경우라면 매니페스트 파일도 함께 확인합니다.

순서가 중요할 때 Rust publish는 순차적으로 진행됩니다. 이것은 정상이며, 보통 pubm이 의존성 정합성을 지키고 있다는 뜻입니다.

pubm 내부에서 빌드나 테스트 단계가 실패함

섹션 제목: “pubm 내부에서 빌드나 테스트 단계가 실패함”

증상:

  • release가 테스트나 빌드 도중 멈춥니다.
  • 오류 메시지가 underlying script를 다시 실행하라고 제안합니다.

할 일:

  1. 스크립트를 직접 다시 실행합니다.
  2. 실제 빌드 또는 테스트 실패를 수정합니다.
  3. pubm을 다시 시도합니다.

예:

Terminal window
pnpm run test
pnpm run build

스크립트 이름이 다르면 설정이나 CLI 플래그와 맞춥니다.

Terminal window
pubm --test-script test:ci --build-script build:release

증상:

  • 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 환경에 필요한 토큰이 모두 들어 있는지 확인합니다.

증상:

  • 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 상태를 확인합니다.
  • 어떤 단계가 먼저 실패했는지 이해한 뒤에만 다시 실행합니다.

중요한 것은 롤백 메시지보다 원래 원인을 진단하는 일입니다.

증상:

  • 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가 실패했고 보수적으로 복구하고 싶다면:

Terminal window
git status
git tag --sort=-creatordate | head
pubm changesets status --verbose
pubm changesets version --dry-run
pubm --dry-run
pubm --mode ci --phase prepare

실제 publish는 dry-run과 CI 준비 출력이 다시 말이 될 때만 재실행합니다.