diff --git a/.github/workflows/publish-npm-react-zpl.yml b/.github/workflows/publish-npm-react-zpl.yml index b10708b..352f09f 100644 --- a/.github/workflows/publish-npm-react-zpl.yml +++ b/.github/workflows/publish-npm-react-zpl.yml @@ -39,6 +39,11 @@ jobs: publish: needs: test runs-on: ubuntu-latest + # provenance(--provenance)의 OIDC 서명에 id-token이 필요하다. test 잡은 + # 쓰지 않으므로 워크플로 기본값(contents: read)을 두고 여기서만 부여한다. + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v6 @@ -60,6 +65,26 @@ jobs: run: pnpm --filter @zpl-kit/react-zpl build - name: Publish - run: pnpm --filter @zpl-kit/react-zpl publish --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + NAME="$(node -p "require('./apps/react-zpl/package.json').name")" + VERSION="$(node -p "require('./apps/react-zpl/package.json').version")" + # 이미 올라간 버전이면 재발행하지 않는다. npm은 덮어쓰기를 막으므로 + # 재실행·재태그 시 잡 전체가 실패하는 걸 방지한다. + if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then + echo "이미 publish된 버전: ${NAME}@${VERSION} — 스킵" + exit 0 + fi + # 프리릴리즈(0.1.0-rc.1 등)는 latest가 아닌 rc dist-tag로 발행한다. + case "$VERSION" in + *-*) NPM_TAG="rc" ;; + *) NPM_TAG="latest" ;; + esac + # workspace:^ 의존성은 pnpm publish가 발행 시 범위 핀으로 치환한다. + # --provenance: id-token 권한으로 공급 출처 증명을 첨부. + pnpm --filter @zpl-kit/react-zpl publish \ + --no-git-checks \ + --provenance \ + --tag "${NPM_TAG}" diff --git a/.github/workflows/publish-npm-zpl-core.yml b/.github/workflows/publish-npm-zpl-core.yml index eb30b41..9769b1b 100644 --- a/.github/workflows/publish-npm-zpl-core.yml +++ b/.github/workflows/publish-npm-zpl-core.yml @@ -39,6 +39,11 @@ jobs: publish: needs: test runs-on: ubuntu-latest + # provenance(--provenance)의 OIDC 서명에 id-token이 필요하다. test 잡은 + # 쓰지 않으므로 워크플로 기본값(contents: read)을 두고 여기서만 부여한다. + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v6 @@ -57,6 +62,25 @@ jobs: run: pnpm --filter @zpl-kit/zpl-core build - name: Publish - run: pnpm --filter @zpl-kit/zpl-core publish --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + NAME="$(node -p "require('./apps/zpl-core/package.json').name")" + VERSION="$(node -p "require('./apps/zpl-core/package.json').version")" + # 이미 올라간 버전이면 재발행하지 않는다. npm은 덮어쓰기를 막으므로 + # 재실행·재태그 시 잡 전체가 실패하는 걸 방지한다. + if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then + echo "이미 publish된 버전: ${NAME}@${VERSION} — 스킵" + exit 0 + fi + # 프리릴리즈(0.1.0-rc.1 등)는 latest가 아닌 rc dist-tag로 발행한다. + case "$VERSION" in + *-*) NPM_TAG="rc" ;; + *) NPM_TAG="latest" ;; + esac + # --provenance: id-token 권한으로 공급 출처 증명을 첨부. + pnpm --filter @zpl-kit/zpl-core publish \ + --no-git-checks \ + --provenance \ + --tag "${NPM_TAG}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2ef997e..092ea16 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,10 +6,8 @@ on: - 'zpl-core/v*' - 'react-zpl/v*' -# GitHub Release 생성(contents)과 npm provenance 서명(id-token)에 필요한 최소 권한. permissions: contents: write - id-token: write concurrency: group: github-release-${{ github.ref }} @@ -50,57 +48,9 @@ jobs: echo "태그 버전($TAG_VER)과 package.json 버전($VER)이 다릅니다: $TAG" exit 1 fi - # 프리릴리즈(0.1.0-rc.1 등)는 latest가 아닌 rc dist-tag로 발행한다. - # 그러지 않으면 `npm install @zpl-kit/react-zpl`이 RC를 집어간다. - case "$VER" in - *-*) NPM_TAG="rc" ;; - *) NPM_TAG="latest" ;; - esac echo "name=${NAME}" >> "$GITHUB_OUTPUT" echo "version=${VER}" >> "$GITHUB_OUTPUT" echo "title=${NAME} v${VER}" >> "$GITHUB_OUTPUT" - echo "npmtag=${NPM_TAG}" >> "$GITHUB_OUTPUT" - - - uses: pnpm/action-setup@v4 - - - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc - cache: pnpm - registry-url: https://registry.npmjs.org - - - name: 의존성 설치 - run: pnpm install --frozen-lockfile - - # exports가 dist를 가리키므로 발행 전 빌드가 반드시 선행되어야 한다. - # `...` 선택자로 대상 패키지의 워크스페이스 의존성(react-zpl→zpl-core)까지 - # 위상 순서대로 함께 빌드한다. - - name: 빌드 - env: - NAME: ${{ steps.meta.outputs.name }} - run: pnpm --filter "${NAME}..." build - - - name: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NAME: ${{ steps.meta.outputs.name }} - VERSION: ${{ steps.meta.outputs.version }} - NPM_TAG: ${{ steps.meta.outputs.npmtag }} - run: | - set -euo pipefail - # 이미 올라간 버전이면 재발행하지 않는다. npm은 덮어쓰기를 막으므로 - # 태그 재푸시·재실행 시 워크플로 전체가 실패하는 걸 방지한다. - if npm view "${NAME}@${VERSION}" version >/dev/null 2>&1; then - echo "이미 publish된 버전: ${NAME}@${VERSION} — 스킵" - exit 0 - fi - # --no-git-checks: 태그 detached 체크아웃 + 빌드 산출물 때문에 필요. - # --provenance: id-token 권한으로 공급 출처 증명을 첨부. - # workspace:* 의존성은 pnpm publish가 발행 시 실제 버전으로 치환한다. - pnpm --filter "${NAME}" publish \ - --no-git-checks \ - --provenance \ - --tag "${NPM_TAG}" - name: GitHub Release 생성 env: