GitHub Action 사용법 정리


  • GitHub Action 사용법 및 cron 사용 방법에 대해 정리한 글입니다
    • GitHub Action으로 YES24 IT 신간을 파이썬으로 크롤링 후 Issue에 업로드하는 예제가 있습니다
    • GitHub action with cron, GitHub action python

GitHub Action

  • 공식 홈페이지, 공식 문서
  • 소프트웨어 workflow를 자동화할 수 있도록 도와주는 도구
  • Workflow의 대표적인 예
    • 1) Test Code
      • ex) 특정 함수의 return 값이 어떻게 나오는지 확인하는 테스트 코드
      • ex) df의 타입이 pd.DataFrame이 맞는가?
      • ex) value1에 특정 값이 들어가는가?
      • 쿼리를 날리고 데이터가 맞는지 정합성 체크하는 것도 일종의 테스트
    • 2) 배포
      • 서버에 새로운 기능, 버전 등을 배포
    • 3) 기타 자동화하고 싶은 스크립트
      • 주기적으로 데이터를 수집해 처리
    • 4) 다양한 파이썬 버전에서 실행되는지 확인
  • CI나 CD는 아래 글을 참고해도 좋음
  • 가격
    • Public repo : 무료, 단 limit이 있음
    • Private repo : 링크 참고
  • 사용할 수 있는 한도
    • Workflow는 하나의 Repo에 최대 20개까지 등록 가능
    • Workflow 안에 존재하는 Job은 6시간동안 실행될 수 있고, 초과시 자동으로 중지됨
    • GitHub Free는 Storage 한도 500MB, 월에 실행 시간 2,000분
      • GitHub Pro는 Storage 한도 1GB, 월에 실행 시간 3,000분




GitHub Action Core 개념

  • GitHub Action을 이해하기 위해서 알아야 하는 개념은 Workflow, Event, Job, Step, Action, Runner 등이 있음
  • 1) Workflow
    • 여러 Job으로 구성되고, Event에 의해 트리거될 수 있는 자동화된 프로세스
    • 최상위 개념
    • Workflow 파일은 YAML으로 작성되고, GitHub Repository의 .github/workflows 폴더 아래에 저장됨
  • 2) Event
    • Workflow를 Trigger(실행)하는 특정 활동이나 규칙
    • 예를 들어 다음과 같은 상황을 사용할 수 있음
      • 특정 브랜치로 Push하거나
      • 특정 브랜치로 Pull Request하거나
      • 특정 시간대에 반복(Cron)
      • Webhook을 사용해 외부 이벤트를 통해 실행
    • 자세한 내용은 Events that trigger workflows 참고
  • 3) Job
    • Job은 여러 Step으로 구성되고, 가상 환경의 인스턴스에서 실행됨
    • 다른 Job에 의존 관계를 가질 수 있고, 독립적으로 병렬 실행도 가능함
  • 4) Step
    • Task들의 집합으로, 커맨드를 날리거나 action을 실행할 수 있음
  • 5) Action
    • Workflow의 가장 작은 블럭(smallest portable building block)
    • Job을 만들기 위해 Step들을 연결할 수 있음
    • 재사용이 가능한 컴포넌트
    • 개인적으로 만든 Action을 사용할 수도 있고, Marketplace에 있는 공용 Action을 사용할 수도 있음
  • 6) Runner
    • Gitbub Action Runner 어플리케이션이 설치된 머신으로, Workflow가 실행될 인스턴스
    • Github에서 호스팅해주는 GitHub-hosted runner와 직접 호스팅하는 Self-hosted runner로 나뉨
    • GitHub-hosted runner는 Azure의 Standard_DS2_v2로 vCPU 2, 메모리 7GB, 임시 스토리지 14GB




GitHub Action 생성하는 흐름

  • 1) 코드 작성
  • 2) 코드 작성 후, Workflow 정의
  • 3) 정상 작동하는지 Test

Workflow 정의하기

  • 기본적인 방법 : .github/worfklows 폴더 안에 .yml 파일을 생성 => 템플릿 활용하면 좋음
  • GitHub Repo에서 Actions 클릭
  • Set up this workflow 클릭하면 간단한 workflow 생성할 수 있음
  • yml 파일 예시
    • Master 브랜치에 Push 또는 Pull Request가 올 경우 실행되는 CI란 이름을 갖는 Workflow
      name: CI
    	
      on:
        push:
          branches: [ master ]
        pull_request:
          branches: [ master ]
    	
      jobs:
        build:
          runs-on: ubuntu-latest
    	
          steps:
          - uses: actions/checkout@v2
    	
          - name: Run a one-line script
            run: echo Hello, world!
    	
          - name: Run a multi-line script
            run: |
              echo Add other actions to build,
              echo test, and deploy your project.
    
  • name : Workflow의 이름을 지정
  • on

      on:
        push:
          branches: [ master ]
        pull_request:
          branches: [ master ]
    
    • Event에 대해 작성하는 부분
    • 어떤 조건에 Workflow를 Trigger 시킬지
    • push(Branch or Tag), pull_request, schedule을 사용할 수 있음
      • 단, 다른 CI/CD 도구에 있는 즉시 실행 버튼은 없음(추후에 생길 수도?)
    • 단일 Event를 사용할 수도 있고, array로 작성할 수도 있음

        on: push
        # 또는
        on: [pull_request, issues]
      
  • jobs

      jobs:
            build:
              runs-on: ubuntu-latest
    		
              steps:
              - uses: actions/checkout@v2
              - name: Run a one-line script
                run: echo Hello, world!
    
              - name: Run a multi-line script
                run: |
                  echo Add other actions to build,
                  echo test, and deploy your project.
    
    • Workflow는 다양한 Job으로 구성됨
    • 여러 Job이 있을 경우, Default로 병렬 실행
    • build라는 job을 생성하고, 그 아래에 2개의 step이 존재하는 구조
    • runs-on은 어떤 OS에서 실행될지 지정
    • strategy - matrix 인자를 사용하면 어떤 파이썬 버전에서 테스트할지 확인할 수 있음. 자세한 내용은 밑 예제를 통해 확인할 수 있음
    • 위 예제에선 run할 때 env(환경 변수)를 설정하는 예제가 없는데, 밑에서 환경 변수를 등록하는 방법에 대해 안내할 예정
    • steps의 uses는 어떤 액션을 사용할지 지정함. 이미 만들어진 액션을 사용할 때 지정




GitHub Action with Python

  • 간단한 예제
    • Workflow 예시 중 Python으로 작성된 것은 Publish Python Package, Python application, Python package 등이 있음
    • 여기선 Python package를 예시로 사용함
  • GitHub Repository 생성 후, hello.py 생성 후 Push

      # hello.py
      print("Hello world")
    
  • GitHub Repository에서 Actions 클릭 - New workflow - Continuous integration workflows 더보기 - Python package - Set up the workflow
  • 생성된 yaml 파일 아래에 pip install하는 부분과 pytest를 지우고, python3 hello.py 실행하도록 수정
    • 템플릿 코드를 조금만 수정함
    • python3 hello.py를 다양한 파이썬 버전에서 실행함
      • strategy: matrix: python-version에서 3.5, 3.6, 3.7, 3.8를 지정함
        strategy: 
            matrix: 
                python-version: [3.5, 3.6, 3.7, 3.8]
      
  • Master로 Push하면 Latest commit 왼쪽에 노란색 아이콘이 생김. 이건 현재 작업 중임을 의미함
  • 아이콘(노란색 아이콘 또는 초록색 체크)을 클릭하면 작업 상태를 확인할 수 있음
  • Details를 클릭하면
    • 로그를 확인할 수 있음

  • 간단하게 Python 스크립트를 실행한다면, Python application을 사용해도 충분함
      name: Python application
    	
      on:
        push:
          branches: [ master ]
        pull_request:
          branches: [ master ]
    	
      jobs:
        build:
    	
          runs-on: ubuntu-latest
    	
          steps:
          - uses: actions/checkout@v2
          - name: Set up Python 3.7
            uses: actions/setup-python@v2
            with:
              python-version: 3.7
          - name: Install dependencies
            run: |
              python -m pip install --upgrade pip
              pip install flake8 pytest
              if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
          - name: Lint with flake8
            run: |
              # stop the build if there are Python syntax errors or undefined names
              flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
              # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
              flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
          - name: Test echo
            run: |
              echo "hi" 
          - name: Test python -h
            run: |
              python3 -h
    




YES24의 IT 신간 도서 40개를 주기적으로 확인하는 GitHub Action 만들기

  • GitHub Action with Python에서 코드를 확인할 수 있음
    • 매일 오전 9시에 YES24 IT 신간 40개를 찾아, 해당 책과 가격을 GitHub Issue에 업로드
  • 코드는 매우 간단해서, 코드보단 Action Workflow에 대해 다룸

      name: yes24_crawler
    	
      on:
        schedule:
          - cron: '0 0 * * *'
    	
      jobs:
        build:
          runs-on: ubuntu-latest
          steps:
          - uses: actions/checkout@v2
          - name: Set up Python
            uses: actions/setup-python@v2
            with:
              python-version: 3.7
          - name: Install dependencies
            run: |
              python -m pip install --upgrade pip
              if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
          - name: Run main.py
            run: |
              python main.py
            env:
              MY_GITHUB_TOKEN: \$
    
  • schedule의 cron에 cron 표현을 등록. UTC 시간대라 한국 시간으론 9시를 의미함
    • 단, 테스트해보니 약간의 지연 시간이 있음(이건 사용량이 많아서 그럴수도..?)
  • requirements.txt에 있는 패키지를 설치하고 main.py를 실행함
    • 여기서 run 아래에 env 인자에 환경 변수를 넘겨줌
    • 환경 변수를 넘겨줄 때 Secrets에 저장함
    • MY_GITHUB_TOKEN을 secrets.MY_GITHUB_TOKEN 저장한 값을 활용함
    • 자세한 내용은 GitHub Action with Python Code 참고




Secret Key 저장하기

  • 클라우드의 저장소에 데이터를 저장하거나, Dockerhub에 접근하는 등을 할 때 고유한 Key가 필요할 수 있음
    • 이런 경우 Secrets에 등록해서 사용할 수 있음
  • 아래 흐름은 위에 있는 YES24 크롤링처럼 Issue에 작성하는 경우의 예고, GitHub Access Token이 필요하지 않는 작업이면 2)부터 확인하면 됨
  • 1) GitHub Access Token 생성하기
    • GitHub Issue를 남기기 위해 GitHub Access Token이 필요함
    • Settings - Developer settings - Personal access tokens - Generate new token 클릭
    • 체크박스에 필요한 권한 체크. repo, workflow 설정 후 저장
    • Value 복사하기
  • 2) Secret Key 등록하기
    • Repository의 Settings - 왼쪽에 Secrets 클릭
    • New secret 클릭하고 Name과 Value 입력하기
    • Repository access 쪽으로 가면, access policy를 정할 수 있음
    • workflow에서 사용할 땐 $ 으로 사용하고, python에선 os.getenv(변수 이름)으로 사용
  • 더 자세한 내용은 Creating and storing encrypted secrets 참고




Job의 의존 관계 설정하기

  • yaml 파일에서 jobs쪽에 needs를 사용해 의존 관계를 설정할 수 있음

      jobs:
        job1:
        job2:
          needs: job1
        job3:
          needs: [job1, job2]
    
  • job1은 job2이 시작되기 전에 성공적으로 완료되어야 하고, job3은 job1과 job2이 모두 완료될 때까지 기다림
  • 더 자세한 내용은 공식 문서 참고




Artifact 저장하기

  • Artifact는 job끼리 데이터를 공유하거나, workflow가 완료된 후 데이터를 저장할 수 있게 해줌
  • upload-artifactdownload-artifact Action을 사용함
  • Workflow에서 생성된 파일을 Upload하고, 다른 job에서 사용할 경우 업로드된 파일을 Download해서 사용함
  • 예제는 총 3개의 job으로 구성되고, job_1에서 math-homework.txt 파일을 생성하고 업로드
    • job_2는 job_1에서 업로드한 파일을 다운로드하고 연산한 후, 다시 업로드
    • job_3은 job_2에서 업로드한 파일을 다운받아 출력
  • 코드에서 유심히 볼 부분은 uses: actions/upload-artifact@v1, uses: actions/download-artifact@v1 이 부분
    • uses에 어떤 액션을 사용할지 지정해서 인자만 입력해 활용함(라이브러리처럼)
  • 결과
  • workflow yaml 파일

      name: Share data between jobs
    	
      on: [push]
    	
      jobs:
        job_1:
          name: Add 3 and 7
          runs-on: ubuntu-latest
          steps:
            - shell: bash
              run: |
                expr 3 + 7 > math-homework.txt
            - name: Upload math result for job 1
              uses: actions/upload-artifact@v1
              with:
                name: homework
                path: math-homework.txt
    	
        job_2:
          name: Multiply by 9
          needs: job_1
          runs-on: windows-latest
          steps:
            - name: Download math result for job 1
              uses: actions/download-artifact@v1
              with:
                name: homework
            - shell: bash
              run: |
                value=`cat homework/math-homework.txt`
                expr $value \* 9 > homework/math-homework.txt
            - name: Upload math result for job 2
              uses: actions/upload-artifact@v1
              with:
                name: homework
                path: homework/math-homework.txt
    	
        job_3:
          name: Display results
          needs: job_2
          runs-on: macOS-latest
          steps:
            - name: Download math result for job 2
              uses: actions/download-artifact@v1
              with:
                name: homework
            - name: Print the final result
              shell: bash
              run: |
                value=`cat homework/math-homework.txt`
                echo The result is $value
    
  • 더 자세한 내용은 Persisting workflow data using artifacts 참고




정리

  • GitHub Action은 Workflow 자동화를 위한 도구
  • CI/CD에서 활용할 수 있고, cron으로 스케쥴을 설정할 수 있음
    • 단, 즉시 실행 버튼은 없음
    • cron은 한국 시간 오전 9시로 지정하면 9시 15분쯤 실행되는 지연 현상이 발견됨
  • 암호화된 변수를 사용하고 싶으면 Secrets에 저장 가능
  • 의존 관계를 표시할 땐 job에서 needs 키워드 사용
  • Data를 공유하고 싶은 경우 upload-artifact와 download-artifact 사용
  • 관련 자료가 많이 없어 공식 문서를 잘 보면 좋음
  • 누군가 만들어둔 action을 활용하면 쉽게 자동화 가능
  • 추가적으로 관심이 있으시면 DevOps with GitHub Action을 추천드립니다 :)
  • GitHub Actions by Example : 이 링크를 가시면 여러 예제를 쉽게 확인할




Reference


카일스쿨 유튜브 채널을 만들었습니다. 데이터 분석, 커리어에 대한 내용을 공유드릴 예정입니다.

PM을 위한 데이터 리터러시 강의를 만들었습니다. 문제 정의, 지표, 실험 설계, 문화 만들기, 로그 설계, 회고 등을 담은 강의입니다

이 글이 도움이 되셨거나 의견이 있으시면 댓글 남겨주셔요.

Buy me a coffeeBuy me a coffee





© 2017. by Seongyun Byeon

Powered by zzsza