최근 작성하는 프로젝트들이 비슷한 형식으로 구성되어 CI/CD 를 GitHub Actions 를 활용하고 있습니다.
간단한 단계는 기본적으로 제공되는 GitHub Actions 패키지를 활용하고, 필요로 하는 특정 기능은 검색해보니 대부분 공개된 패키지가 존재합니다.
몇몇 시행착오를 거쳐 .NET 5 백엔드 응용프로그램과 React 프론트엔드 응용프로그램을 빌드하고, 태그한 후 GitHub Release Draft 를 작성하고, 태그된 커밋을 기준으로 도커 이미지를 빌드해서 레지스트리에 게시하게 구성된 GitHub Actions 입니다.
대상 프로젝트:
- 백엔드: .NET 5
- 프론트엔드: React
- 게시: Docker registry
구성된 저장소:
📢 GitHub Actions
아래와 같이 두개의 워크플로우로 나눠서 작성되었으며, 두 워크플로우는 서로 의존하지 않습니다.
Workflows:
- Build and tag
- Docker image
Build and Tag
name: Build and tag
on:
push:
branches:
- main # Default release branch
tags:
- "!*"
jobs:
build:
name: build
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: setup Node
uses: actions/setup-node@v2
with:
node-version: '14'
- name: build ClientApp
run: |
cd src/Sample.App/ClientApp
npm install
npm run build
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
- name: package-version
run: grep '<Version>' < src/Sample.App/Sample.App.csproj | echo "::set-output name=version::$(sed 's/.*<Version>\(.*\)<\/Version>/\1/')"
id: get_package_version
- name: set-version
run: echo "PACKAGE_VERSION=${{ steps.get_package_version.outputs.version }}" >> $GITHUB_ENV
- name: package-version-to-git-tag
uses: pkgdeps/git-tag-action@v2
with:
github_token: ${{ secrets.GH_TOKEN }}
github_repo: ${{ github.repository }}
version: ${{ env.PACKAGE_VERSION }}
git_commit_sha: ${{ github.sha }}
git_tag_prefix: "v"
- name: Release Drafter
id: release_drafter
uses: release-drafter/release-drafter@v5
with:
config-name: release-drafter.yml
version: ${{ env.PACKAGE_VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
빌드를 확인하고, Semver 형식의 태그를 추가합니다.
태그는 백엔드의 시작프로젝트로 설정되는 프로젝트의 버전 Version
요소를 참조합니다.
백엔드의 시작 프로젝트로 설정되는 프로젝트 파일(.csproj)에 반드시 <Version>
요소가 존재해야 합니다.
예)
<Version>1.0.0</Version>
빌드, 태그 액션은 하나의 작업으로 구성되어 있고, 작업은 여러 단계로 구성됩니다.
액션은 메인 브랜치에 커밋이 전송되었을 때 시작됩니다. 메인 브랜치에 태그가 전송된 경우에는 시작되지 않습니다.
작업은 아래 단계가 순서대로 실행됩니다.
- 체크아웃 메인 브랜치의 내용을 복제합니다.
- .NET 5 도구를 설치합니다.
- Nodejs 도구를 설치합니다.
- 클라이언트 응용프로그램 디렉터리에서 npm 패키지를 설치하고, npm run build 스크립트를 실행해서 클라이언트 응용프로그램을 번들링합니다.
- dotnet 의존 패키지를 설치합니다.
- dotnet 프로젝트를 빌드합니다.
- 백엔드 시작 프로젝트의 버전을 환경변수에 저장합니다.
- 환경변수에 저장된 버전값으로 태그를 작성합니다.
git tag
- 작성된 태그와 연결된 릴리즈 초안을 작성합니다.
Docker image
name: docker image
on:
push:
tags:
- 'v*.*.*'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
-
name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
# list of Docker images to use as base name for tags
images: |
${{ secrets.DOCKER_REGISTRY_URI }}/${{ github.repository }}
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
type=sha
labels: |
org.opencontainers.image.title=Sample File Share
org.opencontainers.image.description=File sharing sample web app
org.opencontainers.image.vendor=bbonkr
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to Registry
uses: docker/login-action@v1
with:
registry: ${{ secrets.DOCKER_REGISTRY_URI }}
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
메인 브랜치에 태그가 전송되면 도커 이미지를 빌드한 후 레지스트리에 새 이미지를 전송합니다.
도커 이미지의 버전은 액션 트리거인 태그가 사용됩니다.
빌드, 태그 액션은 하나의 작업으로 구성되어 있고, 작업은 여러 단계로 구성됩니다.
액션은 저장소에 v*.*.*
형식의 태그가 전송되었을 때 시작됩니다.
작업은 아래 단계가 순서대로 실행됩니다.
- 체크아웃 메인 브랜치의 내용을 복제합니다.
- 도커 메타데이터를 수집합니다.
- 도커 이미지를 빌드하기 위해 QEMU 도구를 설치합니다.
- 도커 이미지를 빌드하기 위해 Buildx 도구를 설치합니다.
- 레지스트리에 로그인합니다.
- 도커 이미지를 빌드하고, 인증된 레지스트리에 이미지를 게시합니다.
👏 Conclusion
이렇게 구성해두면, 버전별 출시정보와 도커 이미지를 레지스트리에서 확인할 수 있습니다.