iOS

Github Actions를 통한 다국어 자동화 (2) | Submodule 최신화, Slack Webhook

하이D:) 2025. 2. 24. 22:05

 

다국어가 지원되는 프로젝트를 개발하는 것에 있어서 개발자의 노동이 최소화되고 휴먼에러를 축소시킬 수 있도록 하기 위해 어떻게 다국어 리소스 관리를 자동화해야 할 것인가에 대해 알아보고 있다.

 

앞선 내용까지는 1편 을 참고!

 

Git Submodule과 Github Actions를 통한 다국어 자동화 (1)

 

 

이제 localization에 대한 작업을 마친 PR을 자동으로 base branch에 머지하고 & 업데이트된 서브모듈 레포지토리에 대해 메인 레포지토리에 최신화 시켜주는 과정(서브모듈이 최신 커밋을 바라보도록)까지 하면 개발자가 손 델 일 없는 완전한 자동화 완성! 개발자는 UI에 넣을 텍스트에 대해 다국어 key값 혹은 swiftGen을 통해 변환된 static 프로퍼티 이름만 알고 있으면 끝!

 

추가적으로 중간중간 완료된 작업에 대해 팀 메신저에 성공적으로 끝났다고 알림이 오면 좋으니 슬랙 웹훅을 사용해서 특정 작업이 끝나면 팀 메신저에 메시지가 오도록 하는 부분동 알아보겠습니다. 그리고 리디님 글에는 PR을 머지하기 전에 다국어 key의 유효성 검증 같은 부분도 있지만 이번에는 패스! 파이썬 코드를 통해 검증하는 플로우도 넣을 수 있는 것 같다. 역시 안 해봤을 뿐 맘만 먹으면 다 길이 있군..

 

 

📍PR merge

 

일단 pr 머지 하는 작업에 대해 간단히 알아보면, 이전 글에서 SwiftGen을 통해 코드로 변환 후 완료 커밋까지 남겼던 작업을 마치고 아래 job에 대한 스크립트를 실행하면 된다.

 

...

  review-and-merge:
  
    # 선행하는 Job이 성공적으로 완료된 후 실행
    needs: localization
    if: ${{ needs.localization.result == 'success' }}
    
    runs-on: ubuntu-latest
    steps:
      # PR Branch 체크아웃
      - name: Checkout PR branch
        uses: actions/checkout@v3
        with:
          ref: ${{ github.head_ref }}

      # Base Branch에 체크아웃
      - name: Checkout base branch
        uses: actions/checkout@v3
        with:
          path: base_branch
          ref: ${{ github.base_ref }}

      - name: Get First Commit Message
        id: commit
        uses: actions/github-script@v6
        with:
          script: |
            const { data: commits } = await github.rest.pulls.listCommits({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number
            });
            const firstCommit = commits[0];
            core.setOutput('message', firstCommit.commit.message);
            
      
      - name: Merge PR
        id: merge
        uses: actions/github-script@v6
        with:
          script: |
            await github.rest.pulls.merge({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: ${{ github.event.pull_request.number }},
              merge_method: 'squash'
            });
        continue-on-error: true
...

 

 

 

 

📍Slack Webhook

그리고 위의 머지작업이 성공적으로 끝났다는 걸 팀 메신저에 메시지로 알림을 받고 싶다면, 슬랙 웹훅을 통해 구현해 볼 수 있다. 나는 개인 프로젝트라서 슬랙을 사용하고 있진 않았지만 이전 회사에서 사내 워크스페이스에 웹훅 사용했을 때도 개발 환경/상황을 공유하기 유용했기 때문에 혼자 있는 슬랙 채널이라도 만들어서 이번 자동화에도 이 과정을 넣었다.

 

먼저 슬랙 워크스페이스와 그 안에 관련 메시지를 받고 싶은 채널을 만들고 슬랙 웹훅 url 확인하기! 이런 건 사실 방법을 기억하고 있는 게 아니아서 할 때마다 찾아보는 게 국룰 ㅎㅎ (이 블로그를 참고했다!  https://velog.io/@king/slack-incoming-webhook ). 이렇게 웹훅 url 확인하고 GitHub Secret에 저장하면 되는데 Webhook URL을 직접 .yml 워크플로우 파일에 넣으면 보안상 위험하기 때문!

 

위에 작업 (PR merge)가 끝나면 슬랙에 웹훅을 보낼 수 있도록해보자

...
	# 성공시 Slack에 알림
      - name: Notify Slack on Merge Success
        if: steps.merge.outcome == 'success'
        uses: slackapi/slack-github-action@v2.0.0
        with:
          webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
          webhook-type: webhook-trigger
          payload: |
            {
            "text": "🎉 PR Merge Success\n\nPR: ${{ github.event.pull_request.html_url }}\nBranch: `${{ github.head_ref }}`\nCommit: ${{ steps.commit.outputs.message }}"
            }

 

 

 

▶️ localization & review and merge 에 대한 job 모두 성공했을 때

이렇게 각 job 이 순차적으로 완료된 걸 볼 수 있다.

 

▶️ Slack Webhook 전송이 성공했을 때

 

 

이렇게 하면 서브모듈의 업데이트는 끝났죠?

그럼 이제 프로젝트에서 이 서브모듈의 업데이트를 최신화시켜서(메인 레포지토리에서 서브모듈의 최신 커밋 해시를 바라볼 수 있도록) 다국어 리소스를 사용할 수 있도록 해보겠습니다. 이것마저 자동화해 버립시다.

 

 

 

 

📍Dispatch Workflow

서브모듈의 워크플로우에서 어떤 트리거를 줬을 때, 메인 레포지토리의 특정 워크플로우가 반응해서 서브모듈을 최신화하는 코드를 실행하게 된다면?! 이걸 github actions에서는 workflow를 dispatch 한다고 하는 것 같습니다. submodule에서 createWorkflowDispatch 이라는 github API를 실행시키면 됩니다!

 

스크립트에서 보면 createWorkflowDispatch 실행 시, 반응할 레포지토리 owner, 레포지토리 이름, workflow 파일 이름 등을 넣는 걸 볼 수 있습니다. 

 ...
 
  dispatch-main-repo:
  
    # review-and-merge Job이 성공적으로 완료된 후 실행
    needs: review-and-merge
    if: ${{ needs.review-and-merge.result == 'success' }}
    
    runs-on: ubuntu-latest
    steps:
      - name: Trigger Main Repository Workflow
        uses: actions/github-script@v6
        with:
          github-token: ${{ secrets.KOCO_GITHUB_TOKEN }}
          script: |
            await github.rest.actions.createWorkflowDispatch({
              owner: 'yyeonjju',
              repo: 'KoCo-Beauty',
              workflow_id: 'updateSubmodule.yml',
              ref: 'develop',
              inputs: {
                name: 'KoCo Main Repository'
              }
            });

 

 

 

 

 

📍 서브모듈 최신화

위처럼 서브모듈에서 createWorkflowDispatch을 실행해 주면 메인레포지토리에서   workflow_dispatch:를 트리거로 했던 workflow가 실행되게 됩니다. 그럼 실행할 워크플로우의 스크립트는 서브모듈을 최신으로 업데이트시켜주는 코드로 구성하면 되겠죠?

 

on:
  workflow_dispatch:
    inputs:
      name:
        description: 'Input name'
        required: true
        type: string
permissions: write-all
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
          token: ${{ secrets.KOCO_GITHUB_TOKEN }}
      
      - name: Pull & update submodules recursively
        run: |
          git submodule update --init --recursive
          git submodule update --recursive --remote
            
      - name: Commit & push
        id: commit
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: "[Success] complete update submodule"

      - name: Notify Slack on Submodule Update Success
        if: steps.commit.outcome == 'success'
        uses: slackapi/slack-github-action@v2.0.0
        with:
          webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
          webhook-type: webhook-trigger
          payload: |
            {
            "text": "💎 SubModule Update Success"
            }

 

 

여기서도 서브모듈에 대한 업데이트가 성공 시, 슬랙 웹훅을 사용해서 메시지를 받을 수 있도록 했습니다. 그럼 이제 자동화 완료, 이제 개발자가 댜국어를 위해 노력하는 건 최소화되겠네요!

 

 

 

 

📍 요약

이해가 잘 안 되실 분(미래의 나..)을 위해 도식화를 해보았습니다! 

 

1. Lokalise 플랫폼에서 다국어 리소스 생성 및 관리 수행
2. Lokalise 파이프라인을 통한 Submodule의 Pull Request 자동 생성
3. PR 이벤트를 트리거로 Submodule의 Workflow(localization.yml) 실행 
    - SwiftGen을 통해 다국어 리소스의 Type-safe 코드 생성
    - 변경사항 commit & merge 후, Slack Webhook을 통한 작업 완료 알림 전송
    - Submodule 동기화를 위한 메인 레포지토리 Workflow 트리거 발생
4. 메인 레포지토리에서 트리거를 감지 후, Workflow(updateSubmodule.yml) 실행 
    - Submodule 최신 상태 동기화 완료 후, Slack Webhook을 통한 알림 전송