CI/CD, Github Actions

newhyork·2022년 7월 31일
0

CI


Continuous Integration

  • 버그를 수정하거나 기능을 개발하는 등, 코드의 변경 사항들을
    merge 등의 event에 따라 자동으로 build 및 test 할 수 있도록 하는 pipeline이다.
  • 보통 현업에서는 다음과 같이 사용하곤 한다.
    • 앞서 PR에서 approve을 받으면 build 및 test를 하게 되고,
      이를 통과하면 merge 버튼이 활성화 되면서 가능해지게 한다.
      • merge 이후에도, 그에 따른 build 및 test를 하곤 한다.
        이를 통과하면 CD로 넘어간다.
    • unprotected/protected branch에 따라 다르게,
      그리고 PR/push/merge 등 event에 따라 다르게 pipeline을 구성할 수 있다.
  • 개발자가 매번 일일이 손수 위 과정을 하지 않고, 정해진 과정에 따라 자동으로 진행되게 한다.
  • CI를 사용함에 따라 개발자들은 코드 변경 사항을 주기적으로 빈번하게 merge해도
    그에 따른 cost가 거의 없게 되므로, 그 때 그 때 merge 할 수 있게 함에 따라
    merge conflict 발생 가능성을 낮출 수 있다는 이점이 있다.

CD


Continuous Delivery/Deployment

  • CD는 release → deploy 하는 pipeline이다.
    • Delivery: release를 검증하고 수동으로 deploy한다.
      즉, repository에 release하는 것까지만 자동화하고, production에 deploy는 수동으로 한다.
    • Deployment: release와 함께 자동으로 deploy한다.
      즉, production에 deploy하는 것까지 자동화한다.

Github Actions


  • Github에서 제공하는 것으로, 별도의 외부 서버 없이 CI/CD pipeline을 구축할 수 있다.

concepts


events

  • 원하는 작업들을, ‘어떤 일’이 발생했을 때 수행할 지 정한다.
  • Github에서 발생하는 대부분의 event가 대상이다.
    • ex) PR을 특정 branch로 merge 할 때, commit을 push 할 때, issue를 생성할 때 등
    • cron을 이용한 특정 시간, 혹은 webhook을 통한 외부 event도 trigger가 될 수 있다.
  • event는 하나 이상의 workflow를 가질 수 있다.

workflows

  • 앞서 event가 발생했을 때, ‘어떤 작업들’을 수행할 지 정한다.
  • workflow는 하나 이상의 job을 가질 수 있으며, 이를 병렬 혹은 순차적으로 실행한다.

jobs

  • workflow 내에서, ‘하나의 작업으로써 어떤 일련의 과정’을 수행할 지 정한다.
    • ex) build, test, deploy 등
  • 각 job은 하나의 steps을 가질 수 있으며, 이를 순차적으로 실행한다.
  • runner: job이 실행될 때, 이를 하나씩 맡아 독립적으로 실행한다. (병렬)
    • VM 내지는 Docker container로 볼 수 있다.
    • ex) ubuntu

steps

  • job-steps 내에서, ‘-’ 하나가 하나의 step에 해당된다.
    • 각 step으로는 shell script, 명령어, actions 등이 쓰인다.
      • actions: 흔히 사용하는 명령들을 이미 잘 만들어 공개해 놓은 component이다.
        - 대표적으로 actions/checkout@v3 가 있는데, 이는 runner에서
        해당 repository에 접근하여, 특정 브랜치에 checkout(switch)할 수 있게 한다.
        - {owner}/{repo}@{ref|version} 형식이다.
    • key로써 actions는 uses, 나머지는 run을 사용한다.

usage


  • repository 루트 디렉터리에 .github/workflows/를 만들고, 여기에
    workflow에 해당하는 .yml 파일을 만들어 CI/CD pipeline을 작성한다.
    • Github에서도 해당 repository의 Actions 탭에서 작성할 수 있다.
  • Github repository에서 Actions 탭으로 이동하면,
    기본적인 .yml template을 제공하며 해당 repository 성격에 맞게 추천해준다.
    • 우측 marketplace에서 다양한 actions를 검색하여 step에 사용할 수 있다.
  • secret_key 등의 환경 변수는 해당 repository의 Settings 탭 Security-Secrets에 저장하고
    ${{secrets.<secret_variable_name>}}으로 참조하여 사용하곤 한다.

example

# .github/workflows/workflow.yml
name: {workflow_name}

on:
  {event}:
    branches: [ "{branch_name}" ]

jobs:
  {job}:
    runs-on: {runner}
    steps:
    - uses: {actions}
    - run: {cmd or shell script}

practice

1.

# app/app.py
from flask import Flask


def create_app():
    app = Flask(__name__)
    return app


app = create_app()


@app.route('/')
def get_home_page():
    return 'hello world!'


def calculate_division(a, b):
    return a / b


if __name__ == "__main__":
    app.run()


# test/test_.py
from app.app import calculate_division


def test_calcualte_division():
    assert calculate_division(4, 2) == 2
# .github/workflows/main-workflow.yml
name: main-ci-workflow-practice

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.9
      uses: actions/setup-python@v3
      with:
        python-version: "3.9"
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
    - name: Test with pytest
      run: |
        python -m pytest
- pytest에 PYTHONPATH가 없어서 ModuleNotFoundError가 발생할 수 있으므로,
  pytest 대신 python -m pytest로 테스트를 실행한다. 
  • 간단히, 테스트 함수가 있는 App과 test를 실행하는 CI workflow를 작성한다.
    • main branch에 대해, push 혹은 PR 시 workflow를 실행한다.
    • merge commit이 발생한다면, 이 또한 해당 remote branch의 push event에 해당된다
  • workflow를 작성하고 remote repo에 최초로 commit-push하면, workflow가 실행된다.

2.

1) main branch에 PR을 하기 위한 dev branch를 만든다.
2) dev branch로 이동하여 일부러 실패하는 TC로 수정한 후, main branch로 PR을 시도한다.
3) merge conflict가 없어서 merge는 할 수 있을지라도, workflow failed가 발생한다.
4) 성공하는 TC로 수정하고 다시 push하면, workflow가 다시 실행되며 성공한다.

3.

  • 현업에서는 이러한 workflow와 함께, main branch 등을 protect하기 위해
    해당 repo의 Settings/Branches에서 다양한 정책을 설정해두곤 한다.
  • private repo라면, public으로 변경해줘야 이 정책이 제대로 동작한다. (무료 계정 恨)
    • 하지만 PR 작성자가 스스로 approve는 할 수 없으므로, 제한적인 부분이 있다.

0개의 댓글