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


카일스쿨 유튜브 채널을 만들었습니다. 데이터 사이언스, 성장, 리더십, BigQuery 등을 이야기할 예정이니, 관심 있으시면 구독 부탁드립니다 :)

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

이 글이 도움이 되셨거나 다양한 의견이 있다면 댓글 부탁드립니다 :)

Buy me a coffeeBuy me a coffee





© 2017. by Seongyun Byeon

Powered by zzsza