`Python`的`CI/CD`:`Jenkins`、`GitLab CI`和`GitHub Actions`的`集成`。

好的,让我们开始吧。

Python CI/CD 集成:Jenkins、GitLab CI 和 GitHub Actions

大家好,今天我们要探讨的是 Python 项目的持续集成/持续部署(CI/CD),以及如何将三个流行的工具——Jenkins、GitLab CI 和 GitHub Actions——集成到我们的开发流程中。

为什么需要 CI/CD?

在深入讨论具体工具之前,我们先简单回顾一下 CI/CD 的重要性。CI/CD 的目标是自动化软件交付流程,使其更快、更频繁、更可靠。对于 Python 项目而言,这意味着:

  • 自动化测试: 每次代码更改都会自动运行单元测试、集成测试等,尽早发现问题。
  • 自动化构建: 将 Python 代码及其依赖项打包成可部署的格式。
  • 自动化部署: 将构建好的应用程序部署到目标环境(例如,测试环境、生产环境)。
  • 快速反馈: 开发人员可以快速获得代码更改的反馈,减少修复问题所需的时间。
  • 提高效率: 自动化流程减少了手动操作,提高了开发团队的效率。
  • 降低风险: 通过自动化测试和部署,降低了引入错误的风险。

Jenkins:老牌 CI/CD 霸主

Jenkins 是一个开源的自动化服务器,它可以自动化构建、测试和部署软件。它的优势在于高度的可配置性和丰富的插件生态系统。

Jenkins 安装和配置

  1. 安装 Jenkins: 可以通过多种方式安装 Jenkins,例如使用包管理器(如 apt、yum)或 Docker。

    # 使用 apt 安装 Jenkins (Ubuntu/Debian)
    sudo apt update
    sudo apt install openjdk-11-jdk  # 确保安装了 Java
    wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
    sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
    sudo apt update
    sudo apt install jenkins
  2. 配置 Jenkins: 安装完成后,访问 http://localhost:8080(默认端口)并按照提示进行配置。初次启动时,需要从指定文件中获取管理员密码。

Jenkins Pipeline 配置

Jenkins Pipeline 使用 Groovy 脚本定义 CI/CD 流程。

  1. 创建 Jenkinsfile: 在 Python 项目的根目录下创建一个名为 Jenkinsfile 的文件。

  2. 定义 Pipeline:Jenkinsfile 中定义 Pipeline 的各个阶段。

    pipeline {
        agent any  // 在任何可用的 agent 上运行
    
        stages {
            stage('Checkout') {
                steps {
                    git url: 'https://github.com/your-username/your-python-project.git', branch: 'main'
                }
            }
    
            stage('Install Dependencies') {
                steps {
                    sh 'python3 -m venv venv'
                    sh 'source venv/bin/activate'
                    sh 'pip install -r requirements.txt'
                }
            }
    
            stage('Run Tests') {
                steps {
                    sh 'source venv/bin/activate'
                    sh 'pytest' // 假设使用 pytest 作为测试框架
                }
            }
    
            stage('Build') {
                steps {
                   sh 'source venv/bin/activate'
                   sh 'python setup.py sdist'
                }
            }
    
            stage('Deploy') {
                steps {
                    // 添加部署步骤,例如上传到 PyPI 或部署到服务器
                    echo 'Deploying...'
                    // 示例:上传到 TestPyPI
                    sh 'source venv/bin/activate'
                    sh 'pip install twine'
                    sh 'twine upload --repository testpypi dist/*'
    
                }
            }
        }
    
        post {
            always {
                echo 'Pipeline finished'
                // 清理步骤(可选)
            }
            success {
                echo 'Pipeline succeeded'
            }
            failure {
                echo 'Pipeline failed'
            }
        }
    }

    说明:

    • agent any: 指定 Pipeline 在任何可用的 agent 上运行。
    • stages: 定义 Pipeline 的各个阶段,例如 Checkout、Install Dependencies、Run Tests、Build、Deploy。
    • steps: 在每个阶段中执行的步骤,例如使用 sh 命令执行 shell 脚本。
    • post: 定义在 Pipeline 结束后执行的步骤,例如发送通知或清理资源。always 总是执行,success 仅在成功时执行,failure 仅在失败时执行。
  3. 创建 Jenkins Job: 在 Jenkins 中创建一个新的 Pipeline job,并配置它从 SCM(例如 Git)拉取 Jenkinsfile

  4. 触发构建: 可以手动触发构建,或者配置 Jenkins 在代码提交时自动触发构建。

Jenkins 插件

Jenkins 拥有丰富的插件,可以扩展其功能。一些常用的 Python CI/CD 插件包括:

  • Git Plugin: 用于从 Git 仓库拉取代码。
  • Python Plugin: 用于管理 Python 环境和依赖项。
  • pytest Plugin: 用于运行 pytest 测试。
  • Slack Notification Plugin: 用于发送 Slack 通知。
  • Email Extension Plugin: 用于发送 Email 通知。

Jenkins 示例:使用 Docker 镜像进行测试

为了隔离测试环境,可以使用 Docker 镜像来运行测试。

  1. 创建 Dockerfile: 在项目根目录下创建一个 Dockerfile

    FROM python:3.9-slim-buster
    
    WORKDIR /app
    
    COPY requirements.txt .
    
    RUN pip install --no-cache-dir -r requirements.txt
    
    COPY . .
    
    CMD ["pytest"]
  2. 修改 Jenkinsfile:

    pipeline {
        agent {
            dockerfile true // 使用 Dockerfile 构建镜像
        }
    
        stages {
            stage('Run Tests') {
                steps {
                    sh 'pytest'
                }
            }
        }
    }

GitLab CI:与 GitLab 集成紧密的 CI/CD

GitLab CI 是 GitLab 内置的 CI/CD 工具。它与 GitLab 仓库紧密集成,易于使用和配置。

GitLab CI 配置

  1. 创建 .gitlab-ci.yml 文件: 在 Python 项目的根目录下创建一个名为 .gitlab-ci.yml 的文件。

  2. 定义 CI/CD Pipeline:.gitlab-ci.yml 文件中定义 CI/CD Pipeline。

    stages:
      - test
      - build
      - deploy
    
    before_script:
      - python3 -m venv venv
      - source venv/bin/activate
      - pip install -r requirements.txt
    
    test:
      stage: test
      script:
        - pytest
    
    build:
      stage: build
      script:
        - python setup.py sdist
      artifacts:
        paths:
          - dist/*.tar.gz
    
    deploy:
      stage: deploy
      script:
        - echo "Deploying..."
        - pip install twine
        - twine upload --repository testpypi dist/*.tar.gz
      only:
        - main # 只在 main 分支上部署

    说明:

    • stages: 定义 Pipeline 的阶段,例如 test、build、deploy。
    • before_script: 在每个 job 之前执行的脚本,例如创建虚拟环境并安装依赖项。
    • test: 定义测试 job,使用 pytest 命令运行测试。
    • build: 定义构建 job,使用 python setup.py sdist 命令构建可分发的包,并将 dist/*.tar.gz 文件作为 artifacts 保存。
    • deploy: 定义部署 job,使用 twine 命令将包上传到 TestPyPI。only: - main 指定只在 main 分支上执行部署。
    • artifacts: 定义 job 生成的工件,可以在后续 job 中使用。
  3. 提交代码:.gitlab-ci.yml 文件提交到 GitLab 仓库。

  4. 查看 Pipeline: GitLab 会自动检测到 .gitlab-ci.yml 文件,并根据其内容创建 CI/CD Pipeline。可以在 GitLab 界面中查看 Pipeline 的状态和日志。

GitLab CI 示例:使用 Docker 镜像进行测试

stages:
  - test

test:
  image: python:3.9-slim-buster
  stage: test
  before_script:
    - pip install -r requirements.txt
  script:
    - pytest

说明:

  • image: 指定使用的 Docker 镜像。

GitHub Actions:GitHub 官方的 CI/CD

GitHub Actions 是 GitHub 官方提供的 CI/CD 工具,它与 GitHub 仓库紧密集成,易于使用和配置。

GitHub Actions 配置

  1. 创建 workflow 文件: 在 GitHub 仓库的 .github/workflows 目录下创建一个 YAML 文件,例如 python-ci.yml

  2. 定义 workflow: 在 YAML 文件中定义 workflow。

    name: Python CI
    
    on:
      push:
        branches: [ main ]
      pull_request:
        branches: [ main ]
    
    jobs:
      build:
    
        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 venv venv
            source venv/bin/activate
            python -m pip install --upgrade pip
            pip install -r requirements.txt
        - name: Lint with flake8
          run: |
            source venv/bin/activate
            flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
        - name: Test with pytest
          run: |
            source venv/bin/activate
            pytest
        - name: Build package
          run: |
            source venv/bin/activate
            python setup.py sdist
        - name: Upload package to TestPyPI
          uses: pypa/gh-action-pypi-publish@release/v1
          with:
            password: ${{ secrets.TEST_PYPI_API_TOKEN }}
            repository_url: https://test.pypi.org/legacy/
            verbose: true

    说明:

    • name: workflow 的名称。
    • on: 触发 workflow 的事件,例如 push 和 pull request。
    • jobs: 定义 workflow 的 job。
    • runs-on: 指定运行 job 的环境,例如 ubuntu-latest。
    • steps: 定义 job 的步骤。
    • uses: 使用 GitHub Actions 提供的 action,例如 actions/checkout@v3 用于检出代码,actions/setup-python@v3 用于设置 Python 环境。
    • run: 运行 shell 命令。
    • secrets: 使用 GitHub Secrets 存储敏感信息,例如 TestPyPI API token。需要先在 GitHub 仓库的 Settings -> Secrets 中添加名为 TEST_PYPI_API_TOKEN 的 secret。
  3. 提交代码: 将 workflow 文件提交到 GitHub 仓库。

  4. 查看 workflow: GitHub 会自动检测到 workflow 文件,并根据其内容创建 CI/CD Pipeline。可以在 GitHub 仓库的 Actions 选项卡中查看 workflow 的状态和日志。

GitHub Actions 示例:使用 Docker 镜像进行测试

name: Python CI

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

jobs:
  build:
    runs-on: ubuntu-latest
    container:
      image: python:3.9-slim-buster

    steps:
    - uses: actions/checkout@v3
    - name: Install dependencies
      run: |
        pip install --upgrade pip
        pip install -r requirements.txt
    - name: Test with pytest
      run: |
        pytest

说明:

  • container: 指定使用的 Docker 镜像。

对比:Jenkins vs GitLab CI vs GitHub Actions

特性 Jenkins GitLab CI GitHub Actions
易用性 配置复杂,需要学习 Groovy 相对简单,使用 YAML 相对简单,使用 YAML
集成性 需要手动集成,生态丰富 与 GitLab 紧密集成 与 GitHub 紧密集成
扩展性 插件生态丰富 通过 .gitlab-ci.yml 扩展 通过 GitHub Marketplace Actions 扩展
成本 开源,免费 开源,免费(有付费版本) 免费(有限制,超出限制收费)
适用场景 需要高度定制和灵活性的项目 使用 GitLab 的项目 使用 GitHub 的项目
Docker 支持 良好,可以通过插件或手动配置实现 良好,可以直接在 .gitlab-ci.yml 中指定 Docker 镜像 良好,可以直接在 workflow 文件中指定 Docker 镜像
社区支持 庞大,活跃 活跃 快速增长

集成策略选择

选择哪个 CI/CD 工具取决于你的具体需求和环境。

  • 如果你已经在使用 GitLab,那么 GitLab CI 是一个不错的选择。 它与 GitLab 紧密集成,易于使用和配置。
  • 如果你已经在使用 GitHub,那么 GitHub Actions 是一个不错的选择。 它与 GitHub 紧密集成,而且 GitHub Marketplace 提供了丰富的 Actions 可以使用。
  • 如果你需要高度定制和灵活性的 CI/CD 流程,或者你的项目不在 GitLab 或 GitHub 上,那么 Jenkins 可能更适合你。 Jenkins 拥有丰富的插件和强大的配置能力,可以满足各种复杂的 CI/CD 需求。

最佳实践

  • 保持 Jenkinsfile.gitlab-ci.yml 或 GitHub Actions workflow 文件简洁易懂。 将复杂的逻辑分解成小的、可重用的函数或脚本。
  • 使用虚拟环境隔离依赖项。 确保每个 job 都在一个干净的环境中运行。
  • 尽早运行测试。 在代码提交后立即运行单元测试,尽早发现问题。
  • 使用代码静态分析工具(例如 Flake8、Pylint)检查代码质量。 确保代码符合编码规范。
  • 使用 Docker 镜像隔离测试环境。 确保测试环境与生产环境一致。
  • 使用 secrets 管理敏感信息。 不要将密码、API token 等敏感信息硬编码到 CI/CD 配置文件中。
  • 监控 CI/CD Pipeline 的状态。 及时发现和解决问题。
  • 自动化部署到不同的环境(例如,测试环境、生产环境)。 确保部署流程的一致性和可靠性。
  • 为你的CI/CD流水线编写单元测试。 确保你的自动化流程能够正常运作。

示例项目结构

your-python-project/
├── .github/workflows/python-ci.yml   # GitHub Actions workflow 文件
├── .gitlab-ci.yml                 # GitLab CI 配置文件
├── Jenkinsfile                     # Jenkins Pipeline 配置文件
├── Dockerfile                      # Dockerfile
├── requirements.txt                # 依赖项列表
├── setup.py                        # setup 文件
├── your_package/                    # Python 包
│   ├── __init__.py
│   ├── module1.py
│   └── module2.py
├── tests/                          # 测试目录
│   ├── __init__.py
│   └── test_module1.py
└── README.md

持续演进和改进

CI/CD 不是一劳永逸的解决方案。随着项目的演进,你需要不断地调整和改进 CI/CD 流程,以适应新的需求和挑战。定期评估你的 CI/CD 流程,并寻找改进的机会。

三种工具,各有千秋

Jenkins, GitLab CI, 和 GitHub Actions 各有优势,选择哪个取决于你的项目需求和使用的平台。集成 CI/CD 到 Python 开发流程中能显著提高开发效率和代码质量。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注