삽질도사

[안드로이드] ci/cd 사용 및 슬랙 메시지 보내기 본문

안드로이드

[안드로이드] ci/cd 사용 및 슬랙 메시지 보내기

전성진블로그 2025. 4. 10. 13:37

 

파일구성

 

위 같은 파일 구성을 가지고 있습니다.

기능 별로 파일을 나눠서 등록된 job 내에서 알맞게 사용중입니다. 

아래가 cd 파일입니다.

# 워크플로우 이름: 빌드, 배포 및 릴리스
name: Build, Distribute & Release

# 워크플로우가 실행되는 조건
on:
 push:
   tags:
     - 'v*'  # v로 시작하는 태그가 푸시될 때 실행 (예: v1.0.0)
 workflow_dispatch:  # GitHub Actions에서 수동으로 워크플로우를 실행할 수 있게 함

# 워크플로우에서 실행할 작업들
jobs:
 # 환경 및 버전 정보를 추출하는 작업
 extract-environment:
   runs-on: ubuntu-latest  # 우분투 최신 버전에서 실행
   outputs:  # 이 작업에서 다른 작업으로 전달할 출력값 정의
     version_name: ${{ steps.extract_version.outputs.version_name }}  # 추출된 버전 이름
     environment: ${{ steps.extract_version.outputs.environment }}  # 결정된 환경 (dev/prod)
     build_type: ${{ steps.extract_version.outputs.build_type }}  # 빌드 타입 (debug/release)
   steps:
     - uses: actions/checkout@v4  # 코드 저장소 체크아웃
     - name: set up JDK 17  # JDK 17 설정
       uses: actions/setup-java@v4
       with:
         java-version: '17'
         distribution: 'temurin'  # 테무린(이클립스 오픈 JDK) 배포판 사용
         cache: gradle  # Gradle 의존성 캐싱

     - name: Extract version and determine environment  # 버전 추출 및 환경 결정 단계
       id: extract_version
       run: |
         # local.properties 파일에 SDK 디렉토리 및 비밀 정보 설정
         echo sdk.dir=${{ vars.ANDROID_HOME }} >> local.properties
         echo '${{ secrets.LOCAL_PROPERTIES }}' >> local.properties
         
         # gradlew 스크립트를 실행하여 버전 정보 추출 (정규식 사용)
         VERSION=$(./gradlew getVersion | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
         echo "version_name=$VERSION" >> $GITHUB_OUTPUT
         
         # 버전 형식에 따른 환경 결정
         if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
           # 네 번째 숫자가 있으면 개발 버전으로 설정 (ex: 2.25.0303.100)
           echo "environment=dev" >> $GITHUB_OUTPUT
           echo "build_type=debug" >> $GITHUB_OUTPUT
         else
           # 네 번째 숫자가 없으면 운영 버전으로 설정 (ex: 2.25.0)
           echo "environment=prod" >> $GITHUB_OUTPUT
           echo "build_type=release" >> $GITHUB_OUTPUT
         fi
 
 # 안드로이드 APK 빌드 작업
 android-build:
   needs: [extract-environment]  # 환경 추출 작업이 완료된 후 실행
   name: Build Android APK
   uses: ./.github/workflows/reusable-android-build.yml  # 재사용 가능한 워크플로우 호출
   secrets:
     inherit  # 상위 워크플로우의 시크릿을 상속
   with:  # 재사용 워크플로우에 전달할 파라미터
     build_type: ${{ needs.extract-environment.outputs.build_type }}  # 빌드 타입
     environment: ${{ needs.extract-environment.outputs.environment }}  # 환경
     distribution_groups: ''  # 배포 그룹 (비어있음)
 
 # GitHub 릴리스 생성 작업
 create-release:
   needs: [android-build, extract-environment]  # 빌드와 환경 추출 작업이 완료된 후 실행
   name: Create GitHub Release
   if: ${{ needs.extract-environment.outputs.environment == 'prod' }}  # 운영 환경인 경우에만 실행
   uses: ./.github/workflows/reusable-github-release.yml  # 재사용 가능한 워크플로우 호출
   with:
     version: ${{ needs.extract-environment.outputs.version_name }}  # 버전 이름
     release_body_path: .github/release_body.md  # 릴리스 설명 마크다운 파일 경로
   permissions:
     contents: write  # GitHub 저장소 컨텐츠 쓰기 권한 부여
 
 # Slack 알림 전송 작업
 send-slack-notification:
   needs: [android-build, extract-environment]  # 빌드와 환경 추출 작업이 완료된 후 실행
   name: Send Slack Notification
   if: ${{ success() }}  # 이전 작업들이 모두 성공한 경우에만 실행
   uses: ./.github/workflows/reusable-slack-deploy-message-to-all.yml  # 재사용 워크플로우 호출
   secrets: inherit  # 상위 워크플로우의 시크릿을 상속
   with:
     env: ${{ needs.extract-environment.outputs.environment }}  # 환경 정보
     release_version: ${{ needs.extract-environment.outputs.version_name }}  # 릴리스 버전

 

설명은 주석으로 달았습니다.

생소한 문법이지만 한번 해보면 직접 생각해서 만들어야 하는 부분 보다는 위 같은 코드가 지원하는 문법과 함수를 알맞게 사용하는 부분이 더 많습니다.

 

주요 사항: 

needs: 모든 job 들은 needs 라는 것을 사용해서 동기적으로 처리가 가능합니다.

uses: 모듈화된 파일을 함수처럼 뽑아서 사용이 가능합니다.

with: 다음 작업에서 필요한 인수를 전달할 때 사용합니다.

secrets: 키값과 같은 숨은 값들을 전달하고자 하는 것들을 전달할 때 사용하며, inherit 으로 상위 플로우의 시크릿을 상속해서 전달할 수도 있습니다. 

 

secrets은 아래와 같인 깃허브에서 정의가 가능합니다. 

 

슬랙 메시지 파일입니다.

# 워크플로우 이름: 모든 채널에 Slack 배포 성공 메시지를 보내는 재사용 가능한 워크플로우
name: Reusable Workflow To Send Slack Deploy Success Message To All

# 워크플로우 트리거 설정
on:
 workflow_call:  # 다른 워크플로우에서 호출할 수 있도록 설정
   inputs:  # 워크플로우 호출 시 입력 받을 매개변수 정의
     env:  # 환경 설정 (dev, prod 등)
       type: string
       required: true
       default: dev  # 기본값은 dev
     release_version:  # 릴리스 버전 정보
       type: string
       required: true

# 워크플로우에서 실행할 작업들
jobs:
 # 모든 채널에 배포 성공 메시지를 보내는 작업
 send-slack-when-deploy-success-to-all:
   name: Send Success Message To All
   runs-on: ubuntu-latest  # 우분투 최신 버전에서 실행
   environment: webhook  # 환경 설정 (GitHub의 환경 설정 사용)
   env:
     ENV: ${{ inputs.env == 'dev' && '개발' || inputs.env == 'prod' && '운영' || '테스트' }}  # 환경 이름을 한글로 변환
   steps:
     - name: Checkout Github Repository  # GitHub 저장소 체크아웃
       uses: actions/checkout@v4
       
     - name: Generate Slack Update Block  # Slack 메시지에 포함될 업데이트 내용 블록 생성
       id: generate-update-block
       run: |
         # deploy_info.yml 파일에서 update: 섹션 아래의 내용을 추출
         UPDATES=$(awk 'BEGIN {inSection=0} 
           /^update:/ {inSection=1; next}  # update: 섹션 시작을 찾음
           inSection && /^[^[:space:]]/ {inSection=0}  # 다음 섹션 시작이면 종료
           inSection && /^[[:space:]]/ {  # 들여쓰기된 줄이면 처리
             gsub(/^[[:space:]]+/, "", $0);  # 앞쪽 공백 제거
             sub(/^[^:]+:[[:space:]]*/, "", $0);  # 키: 부분 제거
             print  # 내용만 출력
           }' .github/config/deploy_info.yml)
         
         # 업데이트 내용이 없으면 빈 블록 설정
         if [ -z "$UPDATES" ]; then
           echo "No updates found."
           echo "UPDATE_BLOCK=" >> $GITHUB_ENV
           exit 0
         fi
         
         # JSON 형식의 Slack 블록 생성 시작
         JSON='{"type": "rich_text_list", "style": "bullet", "indent": 0, "elements": ['
         IS_START=1
         
         # 각 업데이트 항목을 JSON 요소로 변환
         while IFS= read -r line; do
           formatted_update_detail=$(echo "$line" | sed 's/"/\\"/g')  # 따옴표 이스케이프
         
           # 첫 번째 항목이 아니면 쉼표 추가
           if [ $IS_START -eq 0 ]; then
             JSON="${JSON},"
           fi
         
           # 텍스트 요소 추가
           JSON="${JSON}{\"type\": \"rich_text_section\", \"elements\": [{\"type\": \"text\", \"text\": \"${formatted_update_detail}\"}]}"
           IS_START=0
         done <<< "$UPDATES"
         
         # JSON 블록 완성
         JSON="${JSON}]}"
         echo "UPDATE_BLOCK=${JSON}" >> $GITHUB_ENV
       shell: bash
       
     - name: Send Message When Deployment Succeed For All  # 배포 성공 메시지를 Slack에 전송
       uses: slackapi/slack-github-action@v2.0.0  # Slack API GitHub 액션 사용
       with:
         method: chat.postMessage  # Slack API 메서드
         token: ${{ secrets.SLACK_BOT_TOKEN }}  # Slack 봇 토큰
         payload: |  # Slack 메시지 페이로드
           {
             "channel": "${{ secrets.SLACK_API_DEPLOY_ALL }}",  # 메시지를 보낼 Slack 채널 ID
             "text": "${{ vars.TEAM_NAME }} 배포 알림",  # 알림 메시지 텍스트
             "blocks": [  # Slack 블록 키트를 사용한 메시지 포맷팅
               {
                 "type": "header",  # 헤더 블록
                 "text": {
                   "type": "plain_text",
                   "text": "[ ${{ vars.TEAM_NAME }} ]",  # 팀 이름을 헤더로 표시
                   "emoji": true
                 }
               },
               {
                 "type": "rich_text",  # 리치 텍스트 블록
                 "elements": [
                   {
                     "type": "rich_text_section",  # 서버 환경 정보
                     "elements": [
                       {
                         "type": "text",
                         "text": "서버 환경: ${{ env.ENV }}"
                       }
                     ]
                   },
                   {
                     "type": "rich_text_section",  # 배포 버전 정보
                     "elements": [
                       {
                         "type": "text",
                         "text": "배포 버전: ${{ inputs.release_version }}"
                       }
                     ]
                   },
                   {
                     "type": "rich_text_section",  # 변경 사항 헤더
                     "elements": [
                       {
                         "type": "text",
                         "text": "주요 변경 사항"
                       }
                     ]
                   },
                   ${{ env.UPDATE_BLOCK }}  # 앞서 생성한 업데이트 블록 삽입
                 ]
               }
             ]
           }

 

위 코드도 마찬가지로 모든 설명이 주석에 있습니다.

 

주요사항:

payload: 슬랙 메시지에 담고자하는 메시지 형식을 등록할 수 있습니다.

token: 슬랙 채널마다 고유의 ID 값을 가지는데 이를 깃허브 시크릿에 등록해서 사용이 가능합니다.

 

 

참고: 

https://rien-atelier.tistory.com/183