Communitygithub.com

npm 패키지 출시 강화

npm 패키지를 공개 출시 전에 강화합니다 — 비밀 정보 유출, 런타임 불일치, 타볼 내 불필요한 파일 등을 잡아냅니다. 스킬 호환 에이전트에서 작동합니다.

npm 패키지 출시 강화란 무엇인가요?

이 스킬은 npm 패키지를 로컬에서 잘 작동하는 상태에서 '정직하고, 검사 가능하며, 안전하게 출시할 수 있는' 상태로 업그레이드합니다. 단순한 직관보다 실제 검증을 우선시하여, 패키지 타볼 내용, 런타임 계약, CI, GitHub 설정, 의존성 업데이트 위생 등을 점검합니다. 이 스킬은 npm, pnpm, yarn 등 다양한 패키지 매니저를 지원하며, 감지된 잠금 파일에 따라 명령어를 자동으로 조정합니다. 주요 기능으로는 package.json의 정확성 검증, Node.js 엔진 버전 강제, 타볼 내용 검토, CI/CD 워크플로우 및 Dependabot 설정, GitHub 저장소 보안 강화, 브랜치 보호 규칙 적용, 출시 전 체크리스트 제공 등이 포함됩니다. 또한 출처 증명(provenance)과 같은 고급 기능을 활용한 CI 기반 출시를 권장하여 공급망 보안을 강화합니다. 최종적으로 수행된 모든 검증 항목을 상세히 보고하여 투명성을 보장합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add SSBrouhard/npm-package-release-hardening

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

npm 패키지 출시 강화은(는) 무엇을 하나요?

목표

npm 패키지를 '로컬에서 작동하는 상태'에서 '정직하고, 검사 가능하며 안전하게 출시할 수 있는 상태'로 만듭니다. 단순한 직감보다 실제 검증을 우선시합니다: 패키지 타볼 내용, 런타임 계약, CI, GitHub 설정, 의존성 업데이트 위생.

시작하기

  1. 정확한 저장소 확인:
pwd
git status --short --branch
git remote -v
  1. 패키지 표면 검사:
cat package.json
ls -la
find .github -maxdepth 3 -type f -print 2>/dev/null
  1. 잠금 파일로 패키지 매니저 감지:
  • package-lock.json -> npm
  • pnpm-lock.yaml -> pnpm
  • yarn.lock -> yarn

기본적으로 npm 명령어를 사용하지만, 필요 시 감지된 패키지 매니저에 맞게 변환합니다.

패키지 계약

package.json이 진실을 말하도록 만듭니다:

  • name: 게시 대상이 의도적이며 사용 가능함
  • version: 현재 의도된 게시 버전
  • description, keywords: 레지스트리 검색에 충분히 유용함
  • license: 존재하며 LICENSE와 일치함
  • repository, homepage, bugs: 공개 저장소를 가리킴. 공개 저장소 URL이 아직 확정되지 않은 경우, 조용히 생략하지 말고 명시적으로 출시 전 TODO로 표시
  • type, exports, main, bin: 사용자가 가져오거나 실행할 항목과 일치함
  • files: 타볼을 게시 가능한 아티팩트로 제한함
  • engines.node: 패키지가 실제로 지원하는 최소 런타임
  • prepublishOnly 또는 동등한 스크립트: 오래된 빌드 출력물이 게시되는 것을 방지함

CLI 패키지의 경우, bin 대상이 빌드되었고, 관련성이 있을 때 실행 가능하며, 사용자가 실행할 명령어를 통해 스모크 테스트되었는지 확인합니다.

런타임 최소 버전 규칙

Node 엔진은 약속이지 장식이 아닙니다.

  • engines.node가 >=20이라고 명시하면, CI는 Node 20을 테스트해야 합니다.
  • @types/node를 지원되는 최소 런타임과 동일한 메이저 라인으로 유지합니다.
  • @types/node를 해당 런타임 라인의 최신 패치로 정확히 고정하는 것을 선호합니다.
  • 런타임 최소 버전을 올리지 않는 한 @types/node의 메이저 범프를 위로 병합하지 마십시오.
  • engines.node는 권고사항입니다: npm은 사용자가 engine-strict를 설정하지 않으면 설치를 강제로 막지 않고 경고만 표시하므로, CI에서 최소 버전을 테스트하는 것이 약속을 실제로 강제하는 방법입니다.

이유: Node 타입은 개발 전용이지만 TypeScript가 허용하는 것을 변경합니다. @types/node@26은 Node 20 사용자에게 실패하는 API를 사용하면서 코드가 컴파일되도록 할 수 있습니다.

검증 명령어

npm 프로젝트의 경우:

npm ci
npm run build --if-present
npm test --if-present
npm audit --omit=dev
npm pack --dry-run

pnpm/yarn의 경우, 동등한 install/build/test/audit/pack 명령어를 사용합니다. 감사 지원이 다른 경우, 있는 그대로 말하고 속이지 마십시오.

CLI의 경우, 최소한 하나의 외부 스모크 테스트도 실행합니다:

node dist/path/to/cli.js --help
npm pack --dry-run

실용적이라면, 압축된 .tgz를 임시 디렉터리에 설치하고 사용자와 똑같이 바이너리를 실행합니다.

타볼 검토

npm pack --dry-run은 레지스트리의 진실 표면입니다. 다음을 확인합니다:

  • 빌드 출력물 포함
  • README.md 및 LICENSE 포함
  • 소스 전용 쓰레기, 임시 파일, 테스트, 개인 문서, 픽스처, 로컬 데이터베이스, 비밀 정보 제외
  • 패키지 크기가 합리적임
  • CLI bin 경로가 타볼에 나타남

files가 없으면 추가합니다. .gitignore를 게시 정책으로 의존하지 마십시오.

GitHub 기본 설정

다음을 추가하거나 확인합니다:

  • .github/workflows/ci.yml
  • .github/dependabot.yml
  • .github/CODEOWNERS
  • .github/pull_request_template.md
  • SECURITY.md

GitHub 소유 액션에 대해 현재 지원되는 메이저 버전을 사용합니다. Actions가 액션 런타임이 더 이상 사용되지 않는다고 경고하면, CI 통과 후 액션 메이저를 업데이트합니다.

CI는 일반적으로 다음을 포함해야 합니다:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@CURRENT_MAJOR
      - uses: actions/setup-node@CURRENT_MAJOR
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test --if-present

node-version을 패키지의 지원되는 최소 런타임으로 조정하고, 각 @CURRENT_MAJOR를 액션의 현재 메이저 태그(예: actions/checkout@v4)로 바꿉니다 — 실제 메이저로 고정하고, 플레이스홀더를 커밋하지 마십시오.

Dependabot 기본 설정

패키지 및 GitHub Actions 업데이트를 모두 구성합니다:

version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: weekly
    open-pull-requests-limit: 5
    commit-message:
      prefix: deps
      include: scope

Dependabot이 설정 적용 직후 PR을 열면, 이는 설정이 활성화되었음을 증명하는 것으로 간주합니다. PR을 분류하고, 모든 녹색 체크를 맹목적으로 병합하지 마십시오.

Dependabot 분류

다음 경험 법칙을 사용합니다:

  • 런타임 의존성 패치/마이너: 검사 통과하고 릴리스 노트가 평범하면 병합.
  • 런타임 의존성 메이저: 릴리스 노트 검사 및 실제 패키지 동작 스모크 테스트.
  • 개발 도구 메이저: 빌드/테스트/팩 통과하고 런타임 계약을 변경하지 않으면 병합.
  • 런타임 최소 버전 이상의 @types/node: 닫거나 런타임 최소 버전으로 고정하는 것으로 대체.
  • GitHub Actions 메이저: CI 통과하고 지원 중단 경고를 제거하면 병합.

두 PR이 작은 설정 파일에서 충돌하는 경우, 하나를 병합하고 다른 하나를 업데이트하거나, 두 번째를 직접 적용하고 대체되었음을 명확히 주석을 답니다.

GitHub 원격 강화

저장소/계정이 지원하는 것을 적용한 다음, gh 또는 API 읽기로 실제 설정을 확인합니다.

유용한 설정:

gh repo edit OWNER/REPO \
  --delete-branch-on-merge \
  --enable-squash-merge \
  --enable-merge-commit=false \
  --enable-rebase-merge=false \
  --allow-update-branch

gh api --method PUT repos/OWNER/REPO/vulnerability-alerts --silent
gh api --method PUT repos/OWNER/REPO/automated-security-fixes --silent
gh api --method PUT repos/OWNER/REPO/actions/permissions/workflow \
  -f default_workflow_permissions=read \
  -F can_approve_pull_request_reviews=false --silent

Actions 허용 목록의 경우, 워크플로우가 GitHub 소유 액션만 사용하는 경우에만 선호합니다. 타사 액션이 필요한 경우, 가장 작은 집합을 명시적으로 허용합니다.

공개 저장소는 일반적으로 더 많은 보안 제어를 잠금 해제합니다. 무료 요금제의 비공개 저장소는 다음을 차단할 수 있습니다:

  • 브랜치 보호 또는 규칙 세트
  • 코드 스캐닝
  • 비밀 스캐닝
  • 푸시 보호

차단된 항목을 명확히 알립니다. 사용할 수 없는 제어를 활성화된 것으로 보고하지 마십시오.

브랜치 보호

가능한 경우, 기본 브랜치를 다음으로 보호합니다:

  • 병합 전 풀 리퀘스트 요구
  • CI 상태 확인 요구
  • 프로젝트에 맞는 경우 브랜치가 최신 상태여야 함 요구
  • 대화 해결 요구
  • 강제 푸시 차단
  • 삭제 차단
  • 스쿼시 전용 병합을 사용하는 경우 선형 기록 요구

보호 활성화 후, 사용자가 명시적으로 요청하고 우회를 이해하지 않는 한 main에 직접 푸시하는 것을 중단합니다.

게이트 PR 도구

자동화된 검토/게이트 도구를 사용하는 경우, 게이트가 PR을 생성하도록 요청하기 전에 원격에 기본/베이스 브랜치가 있는지 확인합니다. 비어 있는 새 원격 저장소는 종종 먼저 초기 main 푸시가 필요합니다. 그렇지 않으면 게이트가 기능 브랜치를 검증하고 푸시할 수 있지만, 베이스 ref가 없어 PR 생성에 실패할 수 있습니다.

게시 체크리스트

npm publish 전:

  • npm whoami가 의도된 계정을 표시함
  • npm view PACKAGE_NAME name version이 이름 상태를 확인함
  • 게시될 커밋에서 CI가 통과함
  • npm pack --dry-run이 검토됨
  • README의 설치/사용 예제가 실제 동작과 일치함
  • repository, homepage, bugs가 실제 공개 저장소로 연결됨 (또는 URL이 확정되지 않은 경우 명시적으로 TODO로 표시됨)
  • 출시를 차단하는 Dependabot/보안 알림이 남아 있지 않음
  • 버전 범프가 의도적이며, git에서 태그됨 (git tag vX.Y.Z && git push --tags), CHANGELOG 또는 GitHub 릴리스에 반영됨
  • 범위가 있는 패키지 (@scope/name)는 --access public으로 게시됨 (범위 패키지는 기본적으로 제한/비공개)

웹/패스키/2FA 인증을 사용하는 계정의 경우:

npm publish --auth-type=web

검증 가능한 공급망 링크를 위해 출처 증명(provenance)과 함께 CI에서 게시하는 것을 선호합니다. 출처 증명에는 공개 패키지, GitHub Actions와 같은 지원되는 CI, 작업에 대한 id-token: write 권한이 필요합니다:

npm publish --provenance --access public

게시 후:

npm view PACKAGE_NAME version
npm view PACKAGE_NAME bin files engines repository --json
npx -y PACKAGE_NAME --help

출처 증명과 함께 게시된 경우, 레지스트리가 패키지 페이지에 출처 증명 / 'Built and signed' 증명을 표시하는지 확인합니다.

최종 응답

실제로 검증된 것만 보고합니다:

  • 실행된 패키지 검사
  • 타볼 결과
  • 의존성 PR 결정
  • 생성되거나 병합된 커밋/PR
  • 확인된 GitHub 설정
  • 요금제/가시성에 의해 차단된 제어
  • 게시된 경우 릴리스 태그 및 출처 증명 상태
  • 여전히 사용자 소유인 경우 게시 명령어 또는 게시 후 검증

관련 스킬