# GitLab CI/CD Pipeline for AI Expert Course
# 16주 완성 AI 전문가 양성 과정 프로젝트

# 사용할 Docker 이미지 정의
image: python:3.11-slim

# 파이프라인 단계 정의
stages:
  - setup
  - quality
  - test
  - security
  - validate

# 캐시 설정으로 빌드 시간 단축
cache:
  paths:
    - .venv/
    - .cache/pip

# 공통 변수 설정
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
  POETRY_CACHE_DIR: "$CI_PROJECT_DIR/.cache/poetry"
  POETRY_VENV_IN_PROJECT: "true"

# 의존성 설치 및 환경 설정
setup:
  stage: setup
  before_script:
    - apt-get update && apt-get install -y curl git
    - pip install --upgrade pip
    - pip install poetry
  script:
    - cd "ai lecture"
    - poetry config virtualenvs.in-project true
    - poetry install --with dev
  artifacts:
    paths:
      - ai lecture/.venv/
    expire_in: 1 hour
  only:
    - merge_requests
    - main
    - develop

# 코드 포맷팅 검사 (Black)
format_check:
  stage: quality
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - black --check --diff .
  allow_failure: false
  only:
    - merge_requests
    - main
    - develop

# 코드 린팅 검사 (Ruff)
lint_check:
  stage: quality
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - ruff check .
  allow_failure: false
  only:
    - merge_requests
    - main
    - develop

# 타입 검사 (MyPy)
type_check:
  stage: quality
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - mypy source_code/ --ignore-missing-imports
  allow_failure: true  # 타입 힌트가 완전하지 않을 수 있으므로 실패 허용
  only:
    - merge_requests
    - main
    - develop

# 단위 테스트 실행
unit_tests:
  stage: test
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - pytest source_code/ -v --cov=source_code --cov-report=xml --cov-report=term
  coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: ai lecture/coverage.xml
    paths:
      - ai lecture/coverage.xml
    expire_in: 1 week
  only:
    - merge_requests
    - main
    - develop

# API 테스트 (FastAPI 앱 테스트)
api_tests:
  stage: test
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - pytest source_code/08_model_serving_with_fastapi/ -v
    - pytest source_code/09_production_ready_api/ -v
  allow_failure: false
  only:
    - merge_requests
    - main
    - develop

# Jupyter Notebook 유효성 검사
notebook_validation:
  stage: validate
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
    - pip install nbval
  script:
    - find source_code/ -name "*.ipynb" -exec python -m nbconvert --to notebook --execute --inplace {} \;
  allow_failure: true  # 노트북 실행에 외부 의존성이 있을 수 있으므로 실패 허용
  only:
    - merge_requests
    - main
    - develop

# 마크다운 링크 검증
markdown_links:
  stage: validate
  image: node:18-alpine
  before_script:
    - npm install -g markdown-link-check
  script:
    - cd "ai lecture"
    - find . -name "*.md" -not -path "./node_modules/*" -not -path "./.git/*" | xargs markdown-link-check --config .mlc_config.json
  allow_failure: true  # 외부 링크가 일시적으로 접근 불가할 수 있으므로 실패 허용
  only:
    - merge_requests
    - main
    - develop

# 보안 취약점 스캔 (Bandit)
security_scan:
  stage: security
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - bandit -r source_code/ -f json -o bandit-report.json || true
    - bandit -r source_code/ -f txt
  artifacts:
    paths:
      - ai lecture/bandit-report.json
    expire_in: 1 week
  allow_failure: true  # 보안 이슈가 있어도 파이프라인은 계속 진행
  only:
    - merge_requests
    - main
    - develop

# 의존성 보안 검사 (Safety)
dependency_security:
  stage: security
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
    - pip install safety
  script:
    - safety check --json --output safety-report.json || true
    - safety check
  artifacts:
    paths:
      - ai lecture/safety-report.json
    expire_in: 1 week
  allow_failure: true  # 의존성 보안 이슈가 있어도 파이프라인은 계속 진행
  only:
    - merge_requests
    - main
    - develop

# 멀티 Python 버전 테스트 (병렬 실행)
.python_test_template: &python_test
  stage: test
  dependencies:
    - setup
  before_script:
    - pip install poetry
    - cd "ai lecture"
    - poetry install --with dev
  script:
    - poetry run pytest source_code/ -v
  only:
    - merge_requests
    - main
    - develop

python_3.9:
  <<: *python_test
  image: python:3.9-slim

python_3.10:
  <<: *python_test
  image: python:3.10-slim

python_3.11:
  <<: *python_test
  image: python:3.11-slim

python_3.12:
  <<: *python_test
  image: python:3.12-slim

# 배포 준비 단계 (main 브랜치에서만 실행)
prepare_release:
  stage: validate
  dependencies:
    - setup
  before_script:
    - cd "ai lecture"
    - source .venv/bin/activate
  script:
    - echo "프로덕션 배포 준비 완료"
    - echo "모든 품질 검사 통과"
    - poetry build
  artifacts:
    paths:
      - ai lecture/dist/
    expire_in: 1 month
  only:
    - main

# 파이프라인 성공 시 알림
success_notification:
  stage: .post
  script:
    - echo "🎉 AI Expert Course 파이프라인이 성공적으로 완료되었습니다!"
    - echo "📊 커버리지 리포트: $CI_PIPELINE_URL"
    - echo "🔒 보안 스캔 완료"
    - echo "✅ 모든 품질 검사 통과"
  when: on_success
  only:
    - merge_requests
    - main
    - develop 