[DEVOPS-004][기초] 코드 변경마다 빌드와 테스트 자동 실행하기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[DEVOPS-004][기초] 코드 변경마다 빌드와 테스트 자동 실행하기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 227회 작성일 26-08-31 11:35

본문

[이번 수업]
CI(지속적 통합)는 코드 변경을 자주 합치고 자동 빌드·테스트로 문제를 빠르게 찾는 방식입니다. 작은 Python 코드와 테스트를 로컬에서 실행한 뒤, 같은 검사를 pull request마다 수행하는 GitHub Actions 파일을 작성합니다. 실제 저장소에는 올리지 않습니다.

[선수지식]
DEVOPS-001~003의 Git·브랜치 기초와 Python 실행 방법을 알면 됩니다. YAML은 들여쓰기로 구조를 표현하는 설정 파일 형식입니다.

[학습목표]
1. workflow, event, job, runner, step의 관계를 설명한다.
2. 로컬과 CI에서 같은 테스트 명령을 실행한다.
3. 읽기 전용 권한과 실패 차단 원칙을 적용한다.

[핵심개념]
워크플로(workflow)는 `.github/workflows`에 저장하는 자동화 전체입니다. push나 pull_request 이벤트가 시작 신호이고, job은 runner(실행 머신)에서 동작합니다. job 안의 step은 기본적으로 순서대로 실행됩니다.

빌드는 소스가 실행 가능한 상태인지 확인하는 과정입니다. Python 예제는 `compileall`로 문법과 바이트코드 생성을 확인합니다. 테스트는 결과가 요구사항과 같은지 검사합니다. 명령의 종료 코드가 0이 아니면 step과 job이 실패하여 병합 전에 문제를 보여줍니다. 같은 명령을 로컬에서 먼저 실행하면 수정이 빠릅니다.

예제는 main push와 pull request에 반응합니다. `permissions: contents: read`는 자동 발급되는 `GITHUB_TOKEN`의 콘텐츠 권한을 읽기로 제한합니다. `timeout-minutes`는 멈춘 작업을 종료합니다.

[따라하기]
연습 폴더에 calculator.py를 만듭니다.

```python
def add(left, right):
    return left + right
```

`tests/test_calculator.py`를 만듭니다.

```python
import unittest
from calculator import add

class CalculatorTest(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(2, 3), 5)

if __name__ == "__main__":
    unittest.main()
```

`.github/workflows/ci.yml`에는 다음을 저장합니다.

```yaml
name: python-ci
on:
  pull_request:
  push:
    branches: [main]
permissions:
  contents: read
jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-python@v5
        with:
          python-version: "3.13"
      - name: Compile
        run: python -m compileall -q .
      - name: Test
        run: python -m unittest discover -s tests -v
```

macOS/Linux는 `python3 -m compileall -q .`와 `python3 -m unittest discover -s tests -v`, Windows는 앞의 `python3` 대신 `py`를 사용합니다. `Ran 1 test`와 `OK`가 나오면 정상입니다. GitHub runner에서는 YAML의 `python` 명령이 실행됩니다.

[흔한 실수]
로컬과 CI 명령이 다르면 한쪽에서만 실패합니다. 테스트 이름이 `test*.py` 패턴과 다르면 발견되지 않습니다. 실패 step에 `continue-on-error`를 붙이면 성공처럼 보일 수 있습니다. Python·action 버전을 명시하지 않으면 재현성이 낮아집니다.

[보안 주의]
비밀번호와 토큰을 YAML·로그에 쓰지 마세요. 비밀은 저장소 Secrets에 보관하고 필요한 job에만 전달합니다. `GITHUB_TOKEN` 권한은 최소화하세요. 외부 action은 출처를 검토하고 운영에서는 전체 commit SHA 고정을 고려합니다. 신뢰하지 않는 PR 코드를 비밀이 있는 `pull_request_target`이나 사내 self-hosted runner에서 실행하지 마세요.

[직접 해볼 과제]
1. `subtract` 함수와 테스트를 추가해 총 2개 테스트를 통과시키세요.
2. 예상값을 일부러 6으로 바꿔 실패를 확인한 뒤 복구하세요.
3. Python 3.12와 3.13 matrix를 적용할 위치를 찾아보세요.

[확인문제]
1. workflow를 시작시키는 저장소 활동을 무엇이라고 하나요?
2. 테스트 명령이 종료 코드 1을 반환하면 job은 어떻게 되나요?
3. `permissions: contents: read`를 명시하는 이유는 무엇인가요?

[다음 학습]
다음 순환은 SEC-004 입력 검증과 SQL 인젝션 방어입니다. DevOps 트랙은 DEVOPS-005 아티팩트와 캐시 관리로 이어집니다.

[공식 참고 자료]
https://docs.github.com/en/actions/get-started/understand-github-actions
https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
https://docs.github.com/en/actions/tutorials/build-and-test-code/python
https://docs.github.com/en/actions/reference/security/secure-use
https://docs.python.org/3/library/unittest.html

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
2,142
어제
5,103
최대
16,772
전체
773,196
Copyright © 소유하신 도메인. All rights reserved.