개발

NPM publish github actions로 자동화

배우겠습니다 2024. 9. 21. 22:22
name: Release

on:
  push:
    branches:
      - main

jobs:
  release:
    permissions:
      contents: write

    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '20'

      - name: Config identity
        run: |
          git config --global user.email "${{ secrets.ADMIN_EMAIL }}"
          git config --global user.name "${{ secrets.ADMIN_NAME }}"

      - name: Create and checkout release branch
        run: |
          git checkout -b release

      - name: Get NPM package version
        id: get_version
        run: |
          PACKAGE_NAME="relation-map"
          VERSION=$(npm view $PACKAGE_NAME version)
          echo "npm_version=$VERSION" >> $GITHUB_ENV

      - name: Update package.json version
        run: |
          npm version ${{ env.npm_version }} --no-git-tag-version

      - name: Clean working tree
        run: |
          if [ -z "$(git status --porcelain)" ]; then
            echo "Working tree is clean. Skipping git add and commit."
          else
            git add .
            git commit -m "fix: clean working tree"
          fi

      - name: Bump version and create new tag
        run: |
          npm version patch -m "chore(release): bump version to %s"

      - name: Create .npmrc file
        run: |
          echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc

      - name: Publish to npm
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npm publish

문제

  1. 내가 코드를 바꿀때마다 npm run build 명령을 해야한다.
  2. package.json에서 버전을 올린뒤 커밋하고 푸쉬하고
  3. npm publish를 해야한다.

이를 자동화할 수 없을까?

문제 해결

배포가될떄마다 Npm login을 하는 것은 귀찮고 보안상 미심쩍다.

  • 이를 위해 NPM_TOKEN이 존재한다.
  • npm에서 직접 발급받을 수도 있고 로컬에서도 받을 수 있는 것 처럼 보인다.
  • publish 권한의 토큰을 발급해 github secret에 적용한다.

NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}로는 충분하지 않다.

      - name: Create .npmrc file
        run: |
          echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc
  • 해당 step이 없다면 권한 오류가 발생할 것이다.
  • npm 패키지 정보를 관리하는 .npmrc 파일을 생성해야한다.
  • 이곳에서 인증정보를 설정해야한다.근데 버전업 해줘야하잖아?

npm view $PACKAGE_NAME version

  • 원격 레지스트리 버전을 가져온다.
  • 그 뒤 npm version 명령어로 버전을 최신 버전으로 동기화해준다.

npm version patch

  • 해당 명령어는 patch version을 1 올려준다.
  • 자동적으로 버전 변경에 대한 커밋을 올린다. 하지만 push는 별도로 해야한다.

git config identity

  • npm version 명령어는 working tree가 clean해야하므로 해당 명령어 전 깨끗하게 만들어줘야한다.
  • add 와 commit을 위해 git config --global user.email & name을 설정해준다.

왜 default branch에 직접 push안하지?

  • default branch에 보호 규칙이 설정돼있기 때문이다.
  • 만약 admin(나)는 그냥 push해도 되지만 github actions 환경에선 github-actions[bot]이 push하기 때문에 문제가 발생한다.
  • bot에 대한 bypass 설정은 github actions team plan부터 가능하다.
  • 이를 위해 보호 규칙을 해제하는건 수지타산이 결코 맞지 않다.
  • 따라서 우회책이 필요하다.

별도 branch 생성

  • main으로 부터 release란 브랜치를 생성 후 checkout한다.
  • 해당 브랜치에서 Publish까지 진행한다.
  • npm version 명령어는 working tree가 clean하지 않다면 오류가 발생한다. 종종 해당 오류가 발생해 조건적으로 working tree를 clean하게 만들어줘야한다.
  • 실질적인 코드 변경사항은 이미 default branch에 다 merge된 이후고 해당 branch는 npm version 명령어로 인한 package.json의 version만 변경해 올릴 것이라 문제는 크지 않을 것이라 판단했다.
  • 코드를 직접 변경하고 깃을 조작하므로 permission write를 설정했다.
  • 어차피 push는 할 필요 없다. 오로지 publish를 위한 임시 브랜치이다.

만약에 major 및 minor 버전을 바꾸려면?

  • 이 경우는 사람이 직접 바꿔줘야한다고 생각해 내가 package.json을 건드릴 것이다.
  • CD로 인해 버전이 0.0.1이 오를 것이지만 영향이 크지 않다고 생각한다.

아니 그럼 브랜치 만들 필요가 있나?

  • 맞다. 문제있는 레거시 CD로 인해 별도 브랜치를 조작하는 로직이 많아 남겨두었다. 추후 수정할 계획이다.