Storybook, NPM 배포 통합하기

Geonyeol Ryu·2023년 5월 16일
2
post-thumbnail

계기

이번에 처음으로 NPM 라이브러리를 개발하면서 Chromatic을 이용해 storybook을 배포하는데는 성공했지만, 매번 빌드 후 다시 push하는 과정이 귀찮았다. 따라서 github action과 Chromatic CI/CD를 활용해 배포 자동화를 시도했다.


기존 과정

name: 'react-scatter-graphy storybook deploy'

on: push

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - run: yarn
      - uses: chromaui/action@v1
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          token: ${{ secrets.GITHUB_TOKEN }}

github action에 CHROMATIC_PROJECT_TOKEN을 등록하고, GITHUB_TOKEN은 자동으로 발급받기에 등록하지 않았다.

이 전에 vite.config.ts에서 publicDir을 false로 지정했기에 storybook도 마찬가지로 public이 포함되지 않는 문제점이 발생했지만, storybook 폴더에 따로 assets를 두는 방식으로 변경해 해결하였다.

몇 번의 삽질 끝에 master branch에 push 했을 때 storybook의 배포가 자동화되는 과정을 적용할 수 있었다. 다만 여기서 큰 문제점은 배포된 storybook 링크를 package.json에 업데이트 해야하는 점이었다. 그렇다면 과정은 이렇게 될 것이다.

  1. 기능 구현 및 테스트
  2. npm publish
  3. dist 폴더 재생성
  4. dist와 구현한 기능들 push
  5. storybook chromatic을 통해 배포
  6. 배포된 storybook 링크 package.json에 업데이트
  7. 배포된 링크 최신화를 위한 npm re-publish

이 과정에서 npm에 다시 publish하는 것이 매우 비효율적이라는 생각이 들었다. 그래서 다시 publish하지 않고 npm 사이트의 ‘Homepage’ 부분만 업데이트 하는 방법이 있는지 공식 문서도 찾아보고 삽질도 계속 한 결과…

내가 못 찾은 걸수도 있지만 대략 8시간 정도 삽질했는데도 방법을 찾을 수 없었다. 그나마 최적화 할 수 있는 방법은 storybook 빌드를 위한 브랜치를 따로 구분하여 그 브랜치에서 push나 merge될 때만 storybook CI/CD를 실행하는 방법인데, 처음에는 굳이 라는 생각이 들었다. 어차피 새 기능을 구현할 때 마다 스토리북을 다시 배포해야하는 것은 똑같으니 npm에 다시 publish해야 한다는 것은 변하지 않았다.

반대로 push 후 CI/CD pipeline에서 npm publish하는 방법도 생각해 보았는데, npm publish 후 생성되는 build 폴더를 github repository의 dist에 push해야 하므로 무한 반복의 굴레가 될 것이 눈에 선했다..


CI/CD pipeline 내부에서 npm publish하기

하지만 문득 CI/CD pipeline 내에서 npm publish와 그로 인해 생성된 build 결과값을 github repository에 push하는 과정까지 자동화할 수 있지 않을까 라는 생각이 들어 시도해보았다.

name: 'react-scatter-graphy storybook deploy and npm publish'

on:
  push:
    branches:
      - deploy

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - run: yarn
      - uses: chromaui/action@v1
        id: chromatic
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          token: ${{ secrets.GITHUB_TOKEN }}
      - run: |
          npm config set '//registry.npmjs.org/:_authToken' ${{ secrets.NPM_AUTH_TOKEN }}
          npm config set access public
      - run: |
          sed -i "s|CHROMATIC_HOMEPAGE|${{ steps.chromatic.outputs.storybookUrl }}|" package.json
      - run: yarn publish:npm-outDir
	  - run: |
          sed -i "s|${{ steps.chromatic.outputs.storybookUrl }}|CHROMATIC_HOMEPAGE|" package.json
      - run: cp -R build/* $GITHUB_WORKSPACE/dist/
  1. 모든 push 마다 storybook 배포 및 npm publish 하는 것은 비효율적이라 생각되어 deploy 브랜치에 push될 때만 해당 pipeline이 동작하도록 했다.
  2. 현재 이 pipeline을 제외한 workflow가 없기에 새로운 workflow에 일반적으로 추천되는 actions/checkout@v2 를 사용했다.
  3. npm config set 부분은 npm publish를 위한 권한을 얻기 위해 설정해주는 과정이고, CHROMATIC_PROJECT_TOKEN과 마찬가지로 NPM_AUTH_TOKEN은 Github repository secrets에 설정해 놓았다.
  4. sed -i "s|CHROMATIC_HOMEPAGE|${{ steps.chromatic.outputs.storybookUrl }}|" package.json command는 가장 골치 아팠던 부분이다…
    우선 sed 명령어는 vi 편집기처럼 원하는 문자열을 치환하거나 삭제하는 등의 작업을 수행할 수 있는 리눅스 명령어이다. 위 라인을 자세히 설명하면 package.json 파일의 “homepage”: “CHROMATIC_HOMEPAGE”부분을 찾아 CHROMATIC_HOMEPAGEchromaui/action@v1 의 결과로 생성된 outputs 중 storybookUrl로 변경한다는 명령어이다. 이를 위해 chromaui/action@v1에 chromatic이라는 id를 부여했다.
  5. yarn publish:npm-outDir package.json에서 이를 위한 scripts를 따로 생성해야 했는데, 이유는 잘 모르겠지만 dist 값이 이미 존재해서 에러가 발생하는 것 같았다. yarn clean을 통해 rimraf dist를 수행하도록 지정해놨지만 동작하지 않으니 temp-dist라는 폴더에 빌드된 값을 저장하도록 새 scripts를 만들었다.
  6. 그 후 마지막으로 cp -R build/* $GITHUB_WORKSPACE/dist/ 를 통해 github repository의 dist를 build의 값으로 덮어쓰도록 했다.

동적으로 잘 바뀐 모습 ㅎㅎ

중간에 sed 명령어를 작성할 때 “homepage”: “CHROMATIC_HOMEPAGE”을 통째로 변경하려 했을 때 오류로 인해 package.json 파일이 길어진다던가 기존 scripts로는 복사가 되지 않는 점이라던가의 문제점도 있었지만, 결론적으로 다행히 Homepage는 동적으로 잘 변경되었고, 자동화가 완성되었다.

.
.
.

고 생각했지만 마지막 cp -R temp-dist/ $GITHUB_WORKSPACE/dist/ command로는 내 github repository에 자동으로 업데이트가 되지 않았다. 빌드 후 나온 dist 폴더를 Github repository의 dist에 덮어 씌워야 하는데 이 과정이 동작하지 않았다. 그래서 Github repository에 secrets으로 GIT_AUTH_TOKEN을 등록해주고, 다음과 같은 command를 chromatic.yml 파일에 추가해 주었다.

      - uses: LasyIsLazy/github-upload-action@v0.1.0
        with:
          access-token: ${{ secrets.GIT_AUTH_TOKEN }}
          file-path: build/
          owner: rjsduf0503
          repo: react-scatter-graphy
          remote-dir: dist
          commit-message: 'build: automate deploy dist'
          branch-name: dist-build

테스트 결과.. 잘 동작한다!!

응..? 근데 커밋 수가 이상한 것 같은데...

config 설정 후 직접 add, commit, push하기

원인 모를 커밋이 여러개 생성되어서 LasyIsLazy/github-upload-action 대신 아래와 같이 직접 config 설정 후 add, commit, push하는 코드로 변경하였다.

name: 'react-scatter-graphy storybook deploy and npm publish'

on:
  push:
    branches:
      - deploy

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
          persist-credentials: false
          repository: rjsduf0503/react-scatter-graphy
          token: ${{ secrets.GIT_AUTH_TOKEN }}
      - run: yarn
      - run: mkdir -p dist
      - uses: chromaui/action@v1
        id: chromatic
        with:
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
          token: ${{ secrets.GITHUB_TOKEN }}
      - run: |
          npm config set '//registry.npmjs.org/:_authToken' ${{ secrets.NPM_AUTH_TOKEN }}
          npm config set access public
      - run: |
          sed -i "s|CHROMATIC_HOMEPAGE|${{ steps.chromatic.outputs.storybookUrl }}|" package.json
      - run: yarn publish:npm-outDir
      - run: |
          sed -i "s|${{ steps.chromatic.outputs.storybookUrl }}|CHROMATIC_HOMEPAGE|" package.json
      - run: cp -R build/* dist/
      - run: |
          git config --global user.name "류건열"
          git config --global user.email "rjsduf0503@naver.com"
      - run: |
          git add dist
          git commit -am 'build: automate deploy dist'
          git push -f https://${{ secrets.GIT_AUTH_TOKEN }}@github.com/rjsduf0503/react-scatter-graphy.git HEAD:dist-build

user.name과 user.email 부분 역시 Github secrets로 등록하여 감출 수 있지만, 어차피 이미 package.json에 올라간 정보라 의미 없다고 생각하여 딱히 감추진 않았다.



이번엔 진짜 잘 동작한다.

결론

이로 인해 내 배포 과정은 다음과 같이 자동화되었다.

  1. 기능 구현 및 테스트
  2. package.json의 버전 변경 후 deploy branch에 push
  3. 자동으로 Chromatic CI/CD pipeline 내부에서
    1. storybook 배포
    2. 배포된 페이지로 package.json의 homepage 부분 변경
    3. npm publish
    4. 기존 값(CHROMATIC_HOMEPAGE)으로 package.json의 homepage 부분 변경
    5. publish후 나온 build 파일로 github repository의 dist 변경
  4. dist-build에서 master로 pull request & merge
  5. local에서 변경사항 pull

References

https://www.chromatic.com/docs/github-actions#prerequisites
https://github.com/actions/checkout/tree/releases/v2

0개의 댓글