상세 컨텐츠

본문 제목

Git Action Docker Image 빌드하기 (Test 환경)

Git Action

by Jude_Juu 2024. 11. 23. 00:27

본문

더보기

Pre-Condition 

  1. 원격 푸쉬: PAT(personal access token) 토큰 복사
    • 프로필 → Settings → Developer Settings → Personal access tokens → Tokens (classic) 발급
      • Generate new token → Generate new token
        • Select scopes에서 필요한 Setting 값 선택 후 Token 발급
  2. 레포지토리의 Allow GitHub Actions to create and approve pull requests Check
    • 다른 Repository에 원격 Push 허가 요청
    • 경로: Settings → Actions → General → Workflow Permissions
  3. 변수 저장
    • PAT KEY 변수 저장
    • Repository Settings → 좌측 'Secrets and variables' → Actions / Secrets
  4. 복사 한 Token 붙여넣은 후 저장
  1.  

 

1. Trigger ( Frontend / Backend ↔︎ Docker)

Trigger 발신 → TA-Frontend | TA-Backend
  • repository_dispatch : Trigger 될 이벤트 입력 (script로 실행)
    • main branch in the TA-Backend or TA-Frontend
    • main으로 들어오는 trigger 발생 / pr-merge로 들어오는 trigger 발생 
      const eventType = github.event_name === 'push' 
        ? `trigger-from-$main` 
        : `trigger-from-pr-merge`;
  • github.event.pull_request.merged == true : 실제 PR Merged 수행되었는지 확인
  • github.event.pull_request.base.ref : Branch 정보 전달 → Trigger 될 Repository로 Branch 전달

 

Main branch

  • push 이벤트 발생, pull_request.merged 이벤트가 들어오는 경우,
name: Trigger-docker

on:
  push:
    branches:
      - main  
  pull_request:
    branches:
      - main 
    types:
      - closed 
  workflow_dispatch:

jobs:
  trigger-docker:
    runs-on: ubuntu-latest

    steps:
      # Step 1: Check if PR is Merged
      - name: Check if PR is Merged
        if: ${{ github.event_name == 'pull_request' && github.event.pull_request.merged == true }}
        run: echo "PR merged into main branch: ${{ github.event.pull_request.base.ref }}"

      # Step 2: Trigger Repository Dispatch
      - name: Trigger TA-Docker Workflow for Main
        if: ${{ github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) }}
        uses: actions/github-script@v6
        with:
          script: |
            const isPush = github.event_name === 'push';
            const isPrMerge = github.event_name === 'pull_request' && github.event.pull_request.merged === true;
            const branch = 'main';
            const eventType = isPush
              ? `trigger-from-push-main` 
              : `trigger-from-pr-merge`;

            const payload = {
              branch: branch,
              action_type: github.event_name,
              pr_number: isPrMerge ? github.event.pull_request.number : null,
              merged_by: isPrMerge ? github.event.pull_request.merged_by.login : null
            };

            await github.rest.repos.createDispatchEvent({
              owner: 'junbang-nsuslab',
              repo: 'TA-Docker',
              event_type: eventType,
              client_payload: payload
            });

 

Trigger 수신 → ta-docker

  • repository_dispatch : 발신 Trigger 이벤트 정보 수신 입력
    • 결정 된 이벤트 타입 입력
        repository_dispatch:
          types:
            - trigger-from-push-main 
            - trigger-from-pr-merge
  • TA-Frontend TA-Backend 발신처 script 확인
    • github.event_name == 'push' 이벤트가 Push인지, 아닌지 구분
    • github.event_name == 'pull_request' 현재 실행 중인 이벤트가 Pull Request 이벤트인지 확인
      • github.event.pull_request.merged == true PR이 실제로 병합(Merge)되었는지 확인

 

TA-Docker Job 실행

name: CI/CD workflow

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
    types:
      - closed
  workflow_dispatch:
  repository_dispatch:
    types:
      - trigger-from-push-main
      - trigger-from-pr-merge

jobs:
  trigger-condition:
    runs-on: ubuntu-latest

    steps:
      - name: Skip if not Push, PR Merged, or repository_dispatch
        if: ${{ !(github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) || github.event_name == 'repository_dispatch') }}
        run: |
          echo "This is not a supported event. Skipping..."
          exit 0

      - name: Log Trigger Event
        run: |
          if [[ ${{ github.event_name }} == "push" ]]; then
            echo "Push detected on branch: ${{ github.ref }}"
          elif [[ ${{ github.event_name }} == "pull_request" ]]; then
            echo "PR Merged into branch: ${{ github.event.pull_request.base.ref }}"
          elif [[ ${{ github.event_name }} == "repository_dispatch" ]]; then
            echo "Triggered by repository_dispatch event."
            echo "Event type: ${{ github.event.action }}"
          fi

  trigger-docker:
    runs-on: ubuntu-latest
    steps:
      - name: Handle repository_dispatch Event
        if: ${{ github.event_name == 'repository_dispatch' }}
        run: |
          echo "Handling repository_dispatch event..."
          echo "Branch: ${{ github.event.client_payload.branch }}"
          echo "Action Type: ${{ github.event.client_payload.action_type }}"

2. pr-label-and-push-check ta-docker & Auto Label PR ( TA-Frontend TA-Backend )

pr-label-and-push-check ta-docker

  • Identify Changed Service (Push)
      pr-label-and-push-check:
        needs: trigger-condition
        runs-on: ubuntu-latest
    
        steps:
          - name: Identify Changed Service (Push)
            if: ${{ github.event_name == 'push' }}
            run: |
              CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})
              echo "Changed files: $CHANGED_FILES"
              if echo "$CHANGED_FILES" | grep -q '^backend/'; then
                echo "BUILD_BACKEND=true" >> $GITHUB_ENV
              else
                echo "BUILD_BACKEND=false" >> $GITHUB_ENV
              fi
              if echo "$CHANGED_FILES" | grep -q '^frontend/'; then
                echo "BUILD_FRONTEND=true" >> $GITHUB_ENV
              else
                echo "BUILD_FRONTEND=false" >> $GITHUB_ENV
    
            if: ${{ github.event_name == 'push' }}
            run: |
              echo "Backend build required: ${{ env.BUILD_BACKEND }}"
              echo "Frontend build required: ${{ env.BUILD_FRONTEND }}"

    1. 변경 파일 감지
      CHANGED_FILES=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }})
       
      •  git diff --name-only
        • 이전 커밋(github.event.before) & 현재 커밋(github.sha) 사이의 변경된 파일 목록
          PR_LABELS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            https://api.github.com/repos/$%7B%7B  github.repository }}/issues/${{ github.event.pull_request.number }}/labels | jq -r '.[].name')
        • 이 명령어의 결과 = CHANGED_FILES 변수에 저장하여 이후 변경된 디렉토리나 파일 탐색
    2. 디렉토리 기준 파일 확인
      if echo "$CHANGED_FILES" | grep -q '^backend/'
       
      • grep -q '^backend/'
        • CHANGED_FILES 중 backend/ 디렉토리 내 파일 확인
          eg. backend/api/utils.py 같은 내부 파일이 감지되면 조건 = ‘TRUE’
    3. 결과 환경 변수 설정
      echo "BUILD_BACKEND=false" >> $GITHUB_ENV
      • 변경된 파일이 감지되는 경우 BUILD_BACKEND=true 변수 저장
      • 변경된 파일이 없는 경우 BUILD_BACKEND=false 변수 저장

 

  • Check PR Labels | Log PR Label Match Results
      - name: Check PR Labels
        if: ${{ github.event_name == 'pull_request' && github.event.pull_request.merged == true }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          PR_LABELS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
            -H "Accept: application/vnd.github+json" \
            https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels | jq -r '.[].name')
          echo "PR Labels: $PR_LABELS"
          if echo "$PR_LABELS" | grep -q "backend"; then
            echo "BUILD_BACKEND=true" >> $GITHUB_ENV
          else
            echo "BUILD_BACKEND=false" >> $GITHUB_ENV
          fi
          if echo "$PR_LABELS" | grep -q "frontend"; then
            echo "BUILD_FRONTEND=true" >> $GITHUB_ENV
          else
            echo "BUILD_FRONTEND=false" >> $GITHUB_ENV
    
      - name: Log PR Label Match Results
        if: ${{ github.event_name == 'pull_request' && github.event.pull_request.merged == true }}
        run: |
          echo "Backend build required: ${{ env.BUILD_BACKEND }}"
          echo "Frontend build required: ${{ env.BUILD_FRONTEND }}"
    1. PR Label 가져오기
      • PR의 라벨 정보 → GitHub API 응답 받음
        • jq API 응답으로 라벨 정보 가져옴
          • Label : backend frontend