-
GitHub Actions Auto taggingInfra/Git 2024. 11. 17. 14:40
서비스를 운영하며 배포 시 Release와 Tag를 직접 만들었습니다. 매번 Release와 Tag를 수동으로 생성하다 보니 불편함을 느끼게 되었고 이를 자동화하기 위해 GitHub Actions를 활용해 보았습니다.
GitHub Actions workflow 작성
운영 중인 서비스의 구조는 monorepo 구조로 하나의 repository에서 3개의 서비스를 운영 중입니다. 해당 구조에 맞게 자동으로 Release와 Tag를 각각 생성을 해야 되므로 아래와 같은 조건이 필요했습니다.
1. 각 서비스 배포 시 사용하기 위해 재사용이 가능
2. commit message를 통해 versioning (but commit message에 version에 대한 내용이 없더라도 동작)
3. 배포 완료 시 Release와 Tag 생성해당 조건을 고려하여 GitHub Actions workflow를 작성해 보겠습니다.
※ versioning은 Semantic Versioning 규칙을 따릅니다.
# ./.github/workflows/auto-tag.yml name: Create release Tag on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: version information extraction run: | if [[ '${{ github.event.head_commit.message }}' =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then echo "version=$(echo '${{ github.event.head_commit.message }}' | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')" >> $GITHUB_OUTPUT else git fetch --all --tags tag=$(git tag --list "v*" --sort=-v:refname | head -1 | cut -d 'v' -f2) tag=${tag:-0.0.0} major=$(echo $tag | cut -d '.' -f1 ) minor=$(echo $tag | cut -d '.' -f2 ) patch=$(echo $tag | cut -d '.' -f3 ) echo "version=$(echo $major.$minor.$((patch+1)))" >> $GITHUB_OUTPUT fi id: extraction_version - name: create release tag uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.TOKEN_FOR_GITHUB }} with: tag_name: v${{ steps.extraction_version.outputs.version }} release_name: Release v${{ steps.extraction_version.outputs.version }}
flow는 아래와 같이 진행됩니다.
특정 브랜치(main)에 merge
⇒
1. commit message에 version을 기입했을 경우 해당 version 추출
2. commit message에 version이 없을 경우 기존 tag 정보에서 version 추출(tag가 없을 경우 0.0.0) 한 뒤 해당 version의 Patch version을 1 증가
⇒
추출된 version으로 Release와 Tag 생성GitHub의 Actions marketplace에는 mathieudutour/github-tag-action라는 자동으로 Release와 Tag를 만들어주는 툴이 있지만 하나의 repository에서 서비스에 맞게 각각 Release와 Tag를 생성해야 하므로 사용하지 못했습니다.
Release와 Tag 생성에 조건이 없다면 간편하게 mathieudutour/github-tag-action를 이용하는 것도 좋은 방법입니다.
Reusing workflows
위에서 작성한 workflow는 현재 구조에 해당하는 조건을 모두 충족시키지 못하고 있습니다. GitHub의 Reusing workflows 문서를 참고하여 workflow를 재사용 가능하도록 수정해 보겠습니다.
# ./.github/workflows/auto-tag.yml name: Create release Tag on: workflow_call: inputs: branch: required: true type: string jobs: create_release_tag: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: version information extraction run: | if [[ '${{ github.event.head_commit.message }}' =~ [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} ]]; then echo "version=$(echo '${{ github.event.head_commit.message }}' | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')" >> $GITHUB_OUTPUT else git fetch --all --tags tag=$(git tag --list "${{ inputs.branch }}/*" --sort=-v:refname | head -1 | cut -d 'v' -f2) tag=${tag:-0.0.0} major=$(echo $tag | cut -d '.' -f1 ) minor=$(echo $tag | cut -d '.' -f2 ) patch=$(echo $tag | cut -d '.' -f3 ) echo "version=$(echo $major.$minor.$((patch+1)))" >> $GITHUB_OUTPUT fi id: extraction_version - name: create release tag uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.TOKEN_FOR_GITHUB }} with: tag_name: ${{ inputs.branch }}/v${{ steps.extraction_version.outputs.version }} release_name: Release ${{ inputs.branch }} v${{ steps.extraction_version.outputs.version }}
처음 작성한 workflow와 다르게 트리거가 걸리는 부분이 달라졌습니다. on에서 workflow_call을 포함시켜 입력값을 받도록 설정합니다. 해당 입력값을 토대로 서비스에 맞는 Release와 Tag를 생성하도록 합니다.
해당 workflow를 적용시켜 보겠습니다.
# ./.github/workflows/build.yml name: Service Deploy on: push: branches: - <trigger branch> jobs: build: ... # 작성한 workflow 적용 release: # PRD 환경에서만 동작이 필요할 경우 조건식 추가 if: github.ref == 'refs/heads/<trigger branch>' needs: build uses: ./.github/workflows/auto-tag.yml with: branch: <service name> secrets: inherit
배포가 정상적으로 동작한 뒤 Release와 Tag가 생성 되도록 needs: build를 추가하여 build job의 동작이 정상적으로 끝나면 동작하도록 하였습니다. Release와 Tag를 생성하는 workflow에서 GitHub token이 필요하므로 secrets에 접근할 수 있도록 secrets: inherit도 추가해 줍니다.
이제 GitHub Actions을 실행하면 정상적으로 동작하는 것을 확인할 수 있습니다.
마무리
운영 중인 서비스마다 배포 시 수동으로 Release와 Tag를 생성하는 것이 귀찮아서 시작하게 된 작업이었습니다. 하지만 레퍼런스를 찾다 보니 생각보다 많은 사람들이 해당 부분에 대해서 니즈를 가지고 있었고 다양한 방식으로 tagging을 하고 있음을 알 수 있었습니다. 게으름이 개발자를 성장시킨다는 말이 일리가 있는 작업이었습니다.
참고 자료
https://docs.github.com/en/actions/sharing-automations/reusing-workflows
'Infra > Git' 카테고리의 다른 글
Monorepo에서 다른 패키지를 참조하여 빌드할 때 GitHub Actions 작성 방법 (0) 2025.03.30 Git Repository copy (1) 2024.12.08 GitHub 2FA(2단계 인증) 설정 (0) 2024.07.28 Github PR Reviewer 자동 추가하기 (1) 2024.01.27