Backgrounds
현재 사내 서비스에서 공통적으로 쓰이는 모듈들을 github package로 제공하고 있습니다.
git flow 전략에 따라 develop - staging - production 환경으로 구성되어 있으며,
각 개발 사항을 develop branch에 병합한 뒤, staging 환경에서 테스트한 후, production branch에 병합합니다.
이때 해당 패키지의 새로운 버전을 publish 하기 위해서는 다음과 같은 과정이 필요합니다.
- production 브랜치 내 PR 생성 → review 및 merge
- 개발자 local 환경에서 production branch 이동 → build + publish
- 해당 배포 사항 직접 공지
Problems
위 과정에는 다음과 같은 문제점이 존재합니다.
- PR 병합과 별개로 build가 이뤄지다 보니 해당 개발자 local 환경에 따라 build 결과물이 달라질 가능성이 존재
- 패키지 업데이트 시, 매번 직접 publish 명령어를 실행하는 문제
- 배포 후 slack 등을 통해 직접 알림 하는 문제
Solutions
위와 같은 문제점을 해결하기 위해
build → publish (패키지 업데이트) → release (tag 및 github releaes 생성) 의 과정을 자동화하고자 했습니다.
팀 내부적으로
- production branch의 결과물을 publish에 사용한다
- production branch는 PR을 통해서만 변경사항이 발생한다
라는 규칙이 존재했기 때문에
- git actions 적용
- production branch에 PR이 병합될 경우, workflow 실행
- 해당 workflow를 통해 build + 버전 업 + publish + release 자동화
- release 시 slack 메시지 전송
의 흐름으로 기존의 publish 과정을 자동화할 수 있으리라 생각했습니다!
Implements
1. workflows 생성
workflow를 생성합니다.
// publish-release.yml
name: Publish-Release
on:
pull_request:
branches: ['production']
types: [closed]
해당 workflow는
1) production branch에서 2) PR이 close 될 때 실행!
이때 정확한 workflow 실행 조건은 PR이 단순 종료된 것이 아닌, 정상적으로 병합되었을 때이므로...
// publish-release.yml
name: Publish-Release
on:
pull_request:
branches: ['production']
types: [closed]
jobs:
build_and_publish:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
해당 job에 merge 여부 조건을 추가해 줬습니다.
2. 기본 steps 작성
// publish-release.yml
name: Publish-Release
on:
pull_request:
branches: ['production']
types: [closed]
jobs:
build_and_publish:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '20'
- name: Create .npmrc
run: |
echo "//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
- name: Get Env
run: |
touch ./.env.production
echo "${{secrets.PRODUCTION_ENV}}" > ./.env.production
shell: bash
기본 step들을 작성해 준 모습이며, env와 관련된 부분들은(Create .npmrc, Get Env)
2024.03.25 - [source-code/etc] - [Github Actions] Workflows에서 복수개 env variables 사용하기
위 글을 참고하면 됩니다!
3. package 버전 업데이트 하기
현재 패키지 매니저로 yarn을 사용하고 있는데
yarn의 경우(npm도 마찬가지지만) 이전 버전과 동일한 값으로 패키지 업데이트를 할 수 없습니다!
하지만 제가 원하는 것은 PR 병합 시 해당 workflow에서 자동으로 publish를 실행하는 것이었으므로...
- PR 생성 시 title에 업데이트할 version을 명시한다 (xxx.xxx.xxx 형태)
- PR 병합 후 workflow에서 PR title 속 version 정보를 조회한다
- 해당 version 정보로 패키지를 업데이트한다
위 단계를 통해 새로운 버전으로 패키지 업데이트가 이뤄질 수 있도록 했습니다.
// publish-release.yml
name: Publish-Release
on:
pull_request:
branches: ['production']
types: [closed]
jobs:
build_and_publish:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '20'
- name: Create .npmrc
run: |
echo "//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
- name: Get Env
run: |
touch ./.env.production
echo "${{secrets.PRODUCTION_ENV}}" > ./.env.production
shell: bash
- name: Extract version from commit message
run: |
VERSION=$(echo '${{ github.event.pull_request.title }}' | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
echo "##[set-output name=version;]$VERSION"
id: extract_version_name
- name: Update package version
run: yarn version --new-version ${{ steps.extract_version_name.outputs.version }} --no-git-tag-version
- name: Publish package
run: yarn publish
Extract version from commit message step 에서
해당 PR의 title에 접근(github.event.pull_request.title),
버저닝 관련 문자열을 추출해 version 이라는 변수에 저 정했습니다!
이후 Update package version 에서
이전 extract_version_name step에서 저장한 버전을 조회(steps.extract_version_name.outputs.version)한 뒤,
yarn version --new-version 명령어를 통해 해당 값으로 새로운 버전을 업데이트해줬습니다!
(위 명령어 실행 시 package.json의 version 값이 갱신됩니다)
이후 yarn publish 명령어를 사용하면, 정상적으로 패키지 배포가 이뤄짐을 확인할 수 있습니다!
// package.json
"scripts": {
"build:prod": "tsc && DOTENV_CONFIG_PATH=.env.production node -r dotenv/config scripts/esbuild.config.js",
"prepublish": "yarn build:prod && yarn publish"
},
저 같은 경우 package.json 내 prepublish에 build도 실행했기 때문에
step에서 yarn publish만 실행해 줘도, 새롭게 build 한 결과물이 publish 되었습니다.
(그렇지 않다면, workflow에 publish전 build를 실행하는 step을 추가하면 되겠죠)
4. tag 추가 및 release
패키지가 업데이트된 경우, 해당 패키지 사용자들에게 공유가 필요한데
→ github release를 통해 릴리즈 노트를 작성하면 되겠죠!
// publish-release.yml
name: Publish-Release
on:
pull_request:
branches: ['production']
types: [closed]
jobs:
build_and_publish:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '20'
- name: Create .npmrc
run: |
echo "//npm.pkg.github.com/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrc
- name: Get Env
run: |
touch ./.env.production
echo "${{secrets.PRODUCTION_ENV}}" > ./.env.production
shell: bash
- name: Extract version from commit message
run: |
VERSION=$(echo '${{ github.event.pull_request.title }}' | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
echo "##[set-output name=version;]$VERSION"
id: extract_version_name
- name: Update package version
run: yarn version --new-version ${{ steps.extract_version_name.outputs.version }} --no-git-tag-version
- name: Publish package
run: yarn publish
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.extract_version_name.outputs.version }}
release_name: v${{ steps.extract_version_name.outputs.version }}
body: ${{ github.event.pull_request.body }}
draft: false
prerelease: false
Create release 에서 actions/create-release@v1 를 사용해 release를 생성해 준 모습!
이때 해당 릴리즈 노트의 body 값으로, 병합된 PR의 body 데이터를 사용했습니다.
PR 병합만 했을 뿐인데
build → 패키지 버전 업 → publish → tagging 및 releaes note 작성까지 자동으로 완료되었습니다. 성공!
'source-code > etc' 카테고리의 다른 글
[Github Actions] release assets에 build 결과물 zip 업로드하기 (0) | 2024.05.05 |
---|---|
[Github Actions] Workflows에서 복수개 env variables 사용하기 (1) | 2024.03.25 |
[python] pdf 파일 내 특정 키워드 찾아 추출하기 (1) | 2023.12.05 |