github action에서 의존성 캐싱하기

itisny·2024년 4월 22일
0
post-custom-banner

❓why

Github Action 활용
action이 실행되고 이를 기다리는 시간은 지루하고 아깝다
하나의 action이 1분 넘게 걸리는데 4명의 팀원들이 한 번씩만 사용한다고 하더라도 5분이 허비된다. 이 시간을 최대한 줄이고 빠른 피드백이 가능한 환경을 만들고 싶었다.

🤷‍♀️ how

기존에 구성된 action을 캐싱을 활용하고 변경사항만 수행하도록 개선하여, action이 시작되고 종료되기까지의 시간을 20s대로 개선하는 과정

🚀 what

문제점

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: 체크아웃 레포지토리
      uses: actions/checkout@v3
      
    - name: 파이썬 설정
      uses: actions/setup-python@v3
      with:
        python-version: '3.11'
        
    - name: 의존성 설치
      run: |
        pip install --upgrade pip
        pip install -r requirements.txt
        
    - name: Run Tests
      run: |
        python manage.py test
      env :
        SECRET_KEY: ${{ secrets.SECRET_KEY }}
        DEBUG: ${{ secrets.DEBUG }}

    - name: 서버 배포
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USER }}
        password: ${{ secrets.SERVER_PASSWORD }}
        script: |
          set -e
          cd /home/ubuntu/DeVtail
          git pull origin main

          echo "SECRET_KEY=\"${{ secrets.SECRET_KEY }}\"" > .env
          echo "DEBUG='${{ secrets.DEBUG }}'" >> .env
          echo "GITHUB_CLIENT_ID='${{ vars.CLIENT_GITHUB_ID }}'" >> .env
          echo "GITHUB_CLIENT_SECRET='${{ vars.CLIENT_GITHUB_SECRET }}'" >> .env
          echo "GITHUB_REDIRECT_URI='${{ vars.REDIRECT_GITHUB_URI }}'" >> .env

          source ../venv/bin/activate
          pip install -r requirements.txt
          python manage.py makemigrations
          python manage.py migrate
          sudo systemctl restart devtail.service

의존성 설치가 현재 기준(24/03/29)으로 약 25초 걸립니다.

워크플로우를 실행할 때마다 이렇게 매번 똑같은 패키지를 내려받으면 여러 가지 측면에서 낭비가 발생합니다. CI가 느려질 뿐만 아니라 네트워크 대역폭을 많이 쓰는 등 결국은 개발 생산성 저하와 유지보수 비용의 증가로 이어질 것입니다.

의존성 캐싱

하지만 우리는 변경사항을 추가할 때 항상 의존성을 함께 변경하진 않습니다. 의존성에 변경사항이 있는 경우에만 새로 설치하고 그렇지 않을 때는 이전에 이미 설치했던 의존성을 재사용하는 방안을 생각했습니다. cache를 활용하여 생각대로 구현할 수 있다는 것을 알게되었습니다.

actions/cache를 활용하여 아래처럼 의존성을 캐싱하는 예시입니다.

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: 체크아웃 레포지토리
      uses: actions/checkout@v3
      
    - name: 파이썬 설정
      id: setup-py
      uses: actions/setup-python@v3
      with:
        python-version: '3.11'

    - name: 의존성 캐싱
      id: cache-venv
      uses: actions/cache@v3
      with:
        path: ./.venv
        key: ${{ runner.os }}-${{ steps.setup-py.outputs.python-version }}-venv-${{ hashFiles('**/requirements.txt') }}
        restore-keys: |
          ${{ runner.os }}-${{ steps.setup-py.outputs.python-version }}-venv-
        
    - name: 의존성 설치
      if: steps.cache-venv.outputs.cache-hit != 'true'
      shell: bash
      run: |
        python -m venv ./.venv
        source ./.venv/bin/activate
        pip install --upgrade pip
        pip install -r requirements.txt
        
    - name: Run Tests
      shell: bash
      run: |
        source ./.venv/bin/activate
        python manage.py test
      env :
        SECRET_KEY: ${{ secrets.SECRET_KEY }}
        DEBUG: ${{ secrets.DEBUG }}

    - name: 서버 배포
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SERVER_HOST }}
        username: ${{ secrets.SERVER_USER }}
        password: ${{ secrets.SERVER_PASSWORD }}
        script: |
          set -e
          cd /home/ubuntu/DeVtail
          git pull origin main

          echo "SECRET_KEY=\"${{ secrets.SECRET_KEY }}\"" > .env
          echo "DEBUG='${{ secrets.DEBUG }}'" >> .env
          echo "GITHUB_CLIENT_ID='${{ vars.CLIENT_GITHUB_ID }}'" >> .env
          echo "GITHUB_CLIENT_SECRET='${{ vars.CLIENT_GITHUB_SECRET }}'" >> .env
          echo "GITHUB_REDIRECT_URI='${{ vars.REDIRECT_GITHUB_URI }}'" >> .env

          source ../venv/bin/activate
          python manage.py makemigrations
          python manage.py migrate
          sudo systemctl restart devtail.service

의존성이 많을수록 캐싱을 받아오는 시간도 비약적으로 늘어나지만 3s 안팎으로 의존성 설치가 완료됩니다. 캐싱이 되지 않을 때는 25초 이상이 걸리는 것과 대조적입니다.

캐싱되기전 (23s 소요)

github action에서 캐싱되기전

캐싱된 후 (3s 소요)

의존성 설치가 필요없는 경우 3초 소요
github action에서 캐싱된 후

⚠️ 주의점

GitHub Action은 각 브랜치의 job마다 새로운 가상머신(runs-on에 명시된 운영체제)이 생성됩니다. 따라서 생성된 직후인 첫번째 commit에는 cache가 없으며 이후 두번째 commit 부터 cache가 존재하여 이를 활용할 수 있습니다.

📌 참고

post-custom-banner

0개의 댓글