🤖 🐍
🛠 👨‍💻

🤖

Navigate back to the homepage

GitHub Action과 Poetry를 사용한 파이썬 패키지 개발

Seonghyeon Kim
December 25th, 2019 · 1 min read

Sanic-JWT-Extended를 만들며 처음으로 Poetry와 GitHub Action을 도입해 보았고 굉장히 감동받아 Poetry와 GitHub Action을 소개해 보려고 합니다.

왜 Poetry를 쓰나요?

Poetry는 Javascript의 npm과 yarn 처럼 의존성과 패키지 관리를 동시에 수행합니다. Poetry는 필요한 패키지 간의 의존성을 자동으로 풀어내고, 의존성 트리를 lock 파일에 저장함으로써 의존성이 꼬이는 문제를 막아줍니다. 물론 여기까지는 Pipenv도 충분히 할 수 있습니다.

하지만 Poetry는 의존성-패키지 관리자의 역할 뿐만 아니라 나아가 기존에는 setuptools의 영역이던 프로젝트를 관리할 수 있는 기능을 포함하고 있습니다.

Poetry is a tool for dependency management and packaging in Python.

기존에는 setuptools를 사용해 프로젝트를 관리하고, dependency resolving이 필요하다면 Pipenv를 사용하고, 만든 프로젝트를 pypi에 올리기 위해선 twine이란 도구를 써야 하는 등 하나의 파이썬 프로젝트를 괸리하기 위해 서로 설정을 공유할 수 없는 여러가지 툴들을 사용해야 했습니다.

하지만 Poetry는 pyproject.toml이란 파일을 통해 의존성, 패키지, 그리고 프로젝트를 한곳에서 관리합니다.

이 파일을 통해 프로젝트를 정의했다면 이제는 간단히 poetry install 이란 명령어를 사용해 패키지를 설치할 수 있고 poetry build란 명령어를 사용해 wheel과 sdist를 모두 만들어 낼 수 있으며 poetry publish란 명령어를 통해 pypi든 사설 패키지 저장소든 상관없이 업로드할 수 있습니다.

그리고 이 모든 것을 위해선 단지 Poetry 하나만 설치하면 됩니다.

1[tool.poetry]
2name = "Sanic-JWT-Extended"
3version = "1.0-dev.9"
4description = "Extended JWT integration with Sanic"
5authors = [
6 "Seonghyeon Kim <kim@seonghyeon.dev>"
7]
8license = "MIT"
9readme = "README.md"
10repository = "https://github.com/NovemberOscar/Sanic-JWT-Extended"
11documentation = "https://sanic-jwt-extended.seonghyeon.dev/"
12keywords = ["sanic", "jwt", "json web token"]
13classifiers=[...]
14
15[tool.poetry.dependencies]
16# 생략
17
18[tool.poetry.dev-dependencies]
19# 생략
20
21[build-system]
22requires = ["poetry>=0.12"]
23build-backend = "poetry.masonry.api"

왜 GitHub Action을 쓰나요?

기존에는 CI를 사용하려면 Circle CI, Travis CI 등등의 외부 서비스를 사용해서 테스트와 코드 체크를 수행했습니다. 하지만 GitHub Action이 출시되었고. 외부 서비스에게 전쟁을 선포했습니다.

당연하게도 기존에 다른 서비스들이 제공하던 것처럼 PR과 push에 연결되어 테스트를 수행할 수 있습니다.

추가적으로 여러가지의 환경에서 테스트를 돌릴 수도 있으며, 단계를 구분할 수도 있고, 다른사람들이 만든 액션을 가져다가 사용할 수도 있습니다

test action

아래의 GitHub Action workflow은 다음의 내용들을 수행합니다.

  • 파이썬 3.6과 3.7 환경에서 테스트를 수행
  • poetry를 설치하고 설치된 poetry를 사용해 패키지 설치
  • 테스트를 수행하고 커버리지 추출
  • 만들어진 커버리지 리포트를 codecov에 업로드
1name: Tests
2
3on: [push, pull_request]
4
5jobs:
6 build:
7 runs-on: ubuntu-latest
8 strategy:
9 max-parallel: 4
10 matrix:
11 python-version: [3.6, 3.7]
12
13 steps:
14 - uses: actions/checkout@v1
15 - name: Set up Python ${{ matrix.python-version }}
16 uses: actions/setup-python@v1
17 with:
18 python-version: ${{ matrix.python-version }}
19 - name: Install Poetry
20 run: |
21 curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
22 source $HOME/.poetry/env
23 - name: Install dependencies
24 run: |
25 source $HOME/.poetry/env
26 poetry install
27 - name: Test
28 run: |
29 source $HOME/.poetry/env
30 poetry run pytest --cov=sanic_jwt_extended tests/ --cov-report=xml
31 - name: Upload coverage to Codecov
32 uses: codecov/codecov-action@v1
33 with:
34 token: ${{ secrets.CODECOV_TOKEN }}
35 file: ./coverage.xml
36 flags: unittests

추가적으로 GitHub 내부 서비스 답게 GitHub Action은 repository 내부에서 일어나는 활동에 트리거되어 동작할 수 있습니다.

액션을 트리거할 수 있는 이벤트는 많지만 그중에서 특히 유용한 이벤트는 릴리즈 이벤트입니다. 깃허브의 릴리즈 기능을 사용하면 자동으로 실행되어 PyPI에 패키지를 빌드해 업로드하는 액션을 만들 수도 있습니다.

publish action

아래의 GitHub Action workflow은 다음의 내용들을 수행합니다.

  • 릴리즈가 생성될 때 동작
  • poetry를 설치하고 패키지 설치
  • GitHub secret에 저장된 값을 사용해 pypi 계정 정보를 세팅
  • PyPI에 패키지를 빌드한 후 업로드
1name: Upload to PyPI
2
3on:
4 release:
5 types: [created]
6
7jobs:
8 deploy:
9 runs-on: ubuntu-latest
10
11 steps:
12 - uses: actions/checkout@v1
13 - name: Set up Python 3.7
14 uses: actions/setup-python@v1
15 with:
16 python-version: '3.7'
17 - name: Install Poetry
18 run: |
19 curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
20 source $HOME/.poetry/env
21 - name: Install dependencies
22 run: |
23 source $HOME/.poetry/env
24 poetry install
25 - name: Build and publish
26 run: |
27 source $HOME/.poetry/env
28 poetry config http-basic.pypi ${{ secrets.PYPI_USERNAME }} ${{ secrets.PYPI_PASSWORD }}
29 poetry publish --build

그래서 우리가 뭘 한거죠?

  • setuptools, twine, pipenv를 마음속에 묻고 poetry와 새출발
    • 관리 포인트가 줄고 CI 과정도 단순해짐
    • 다만 GitHub가 pyproject.toml 형식을 인식 못해서 내 패키지를 누가 쓰는가와 내가 뭘 쓰는지 알려주는 기능을 사용할 수 없음
  • Travis CI등 외부 CI를 걷어내고 GitHub Action 도입
    • 자동으로 PR과 push에 반응해 테스트 수행
  • 자동화!
    • 릴리즈를 만들면 자동으로 해당하는 릴리즈를 빌드해 pypi에 업로드

More articles from seonghyeon.dev

어썸한 리드미에 대한 안 어썸한 가이드

이모티콘과 다양한 뱃지들 등등을 활용해 어썸한 리드미를 만들어 개발자들을 끌어들이는 법에 대해 알아봅시다.

December 25th, 2019 · 1 min read

왜 asyncio에 뮤텍스 락이 필요할까?

파이썬 asyncio의 싱글스레드 환경에서의 뮤텍스 락에 대해서 예제 코드와 함께 살펴봅시다.

September 14th, 2019 · 2 min read
© 2019 seonghyeon.dev
Link to $https://twitter.com/NovemberOscar_Link to $https://github.com/NovemberOscarLink to $https://www.linkedin.com/in/novemberoscar/