《Python实战进阶》No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成

devtools/2025/3/28 17:11:27/

No26: CI/CD 流水线:GitHub Actions 与 Jenkins 集成


摘要

持续集成(CI)和持续部署(CD)是现代软件开发中不可或缺的实践,能够显著提升开发效率、减少错误并加速交付流程。本文将探讨如何利用 GitHub Actions 和 Jenkins 构建高效的 CI/CD 流水线,并通过实战案例展示如何自动化构建、测试和部署 Python 应用程序。无论你是个人开发者还是团队成员,本文都将帮助你掌握 CI/CD 的核心技能,并优化开发工作流。


在这里插入图片描述

核心概念和知识点

1. CI/CD 的基本概念与工作原理

  • 持续集成(CI):开发人员频繁地将代码提交到共享仓库,每次提交都会触发自动化构建和测试,以尽早发现集成问题。
  • 持续部署(CD):在 CI 的基础上,进一步将通过测试的代码自动部署到生产环境或测试环境。
  • 关键组件
    • 版本控制系统(如 Git)
    • 构建工具(如 Docker、Makefile)
    • 自动化测试框架(如 pytest)
    • 部署工具(如 Ansible、Kubernetes)

2. GitHub Actions 的 YAML 配置文件

GitHub Actions 是一个内置于 GitHub 的 CI/CD 工具,使用 .github/workflows 目录下的 YAML 文件定义流水线。其主要特点包括:

  • 支持多种事件触发(如 pushpull_request)。
  • 提供丰富的预定义操作(Actions),可快速实现复杂功能。
  • 易于与 GitHub 仓库集成。

3. Jenkins 的安装、配置与 Pipeline 构建

Jenkins 是一个开源的 CI/CD 工具,支持高度自定义的流水线构建。其主要特性包括:

  • 基于插件的扩展性(如 Git、Docker 插件)。
  • 使用 Groovy 脚本定义 Pipeline。
  • 支持分布式构建环境。

4. 自动化构建、测试与部署

  • 构建:将源代码编译为可执行文件或容器镜像。
  • 测试:运行单元测试、集成测试等,确保代码质量。
  • 部署:将应用发布到目标环境(如云服务器、Kubernetes 集群)。
    在这里插入图片描述

实战案例

1. 使用 GitHub Actions 自动运行单元测试

以下是一个使用 GitHub Actions 自动运行 pytest 单元测试的示例。

项目结构
my_project/
├── src/
│   ├── math_operations.py
├── tests/
│   ├── test_math_operations.py
├── .github/
│   └── workflows/
│       └── ci.yml
被测函数
python"># src/math_operations.py
def add(a, b):return a + bdef subtract(a, b):return a - b
测试代码
python"># tests/test_math_operations.py
import pytest
from src.math_operations import add, subtract@pytest.mark.parametrize("a, b, expected", [(2, 3, 5),(-1, 1, 0),(0, 0, 0)
])
def test_add(a, b, expected):assert add(a, b) == expected@pytest.mark.parametrize("a, b, expected", [(5, 3, 2),(0, 0, 0),(10, 5, 5)
])
def test_subtract(a, b, expected):assert subtract(a, b) == expected
GitHub Actions 配置
# .github/workflows/ci.yml
name: CI Pipelineon:push:branches:- mainpull_request:branches:- mainjobs:test:runs-on: ubuntu-lateststeps:- name: Checkout codeuses: actions/checkout@v3- name: Set up Pythonuses: actions/setup-python@v4with:python-version: '3.9'- name: Install dependenciesrun: |python -m pip install --upgrade pippip install pytest- name: Run testsrun: pytest tests/
运行结果

当代码推送到 main 分支时,GitHub Actions 将自动运行测试并生成报告:

============================= test session starts =============================
collected 6 itemstests/test_math_operations.py ......                                    [100%]============================== 6 passed in 0.03s ==============================

2. 使用 Jenkins 部署 Flask 应用到云服务器

Flask 应用
python"># app.py
from flask import Flaskapp = Flask(__name__)@app.route('/')
def home():return "Hello, CI/CD!"if __name__ == "__main__":app.run(host="0.0.0.0", port=5000)
Jenkins Pipeline
pipeline {agent anystages {stage('Checkout') {steps {git 'https://github.com/your-repo/flask-app.git'}}stage('Build') {steps {sh 'docker build -t flask-app .'}}stage('Test') {steps {sh 'docker run --rm flask-app pytest'}}stage('Deploy') {steps {sh '''docker stop flask-app || truedocker rm flask-app || truedocker run -d --name flask-app -p 5000:5000 flask-app'''}}}
}
运行结果
  • Jenkins 将拉取代码、构建 Docker 镜像、运行测试并部署应用。
  • 访问 http://<server-ip>:5000 可看到 “Hello, CI/CD!”。

3. 集成 Docker 容器化应用的 CI/CD 流程

Dockerfile
FROM python:3.9-slimWORKDIR /appCOPY requirements.txt .
RUN pip install -r requirements.txtCOPY . .CMD ["python", "app.py"]
完整流程
  1. GitHub Actions 运行单元测试。
  2. Jenkins 构建 Docker 镜像并部署到云服务器。
  3. 通过 Docker 实现跨环境一致性。


部署的细节与详细操作流程


1. Jenkins 安装与配置

步骤 1:在云服务器安装 Jenkins
# 更新包列表
sudo apt update# 安装 Java 运行时环境(Jenkins 依赖)
sudo apt install openjdk-11-jdk -y# 添加 Jenkins 官方仓库
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee \/usr/share/keyrings/jenkins-keyring.asc > /dev/null
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \https://pkg.jenkins.io/debian-stable binary/ | sudo tee \/etc/apt/sources.list.d/jenkins.list > /dev/null# 安装 Jenkins
sudo apt update
sudo apt install jenkins -y# 启动 Jenkins 服务
sudo systemctl start jenkins# 设置 Jenkins 开机自启
sudo systemctl enable jenkins

访问 http://<云服务器IP>:8080,按照提示完成初始化配置(需从服务器日志获取初始管理员密码)。

步骤 2:安装必要插件

在 Jenkins 控制台依次安装以下插件:

  • Git:用于拉取代码仓库。
  • Docker:支持 Docker 构建与部署。
  • Pipeline:定义流水线任务。

2. 云服务器准备

步骤 1:安装 Docker
# 安装 Docker
sudo apt install docker.io -y# 启动 Docker 服务
sudo systemctl start docker# 设置 Docker 开机自启
sudo systemctl enable docker# 将当前用户加入 Docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER
newgrp docker  # 立即生效
步骤 2:配置 SSH 无密码登录

在 Jenkins 服务器与目标云服务器之间配置 SSH 免密登录:

# 在 Jenkins 服务器生成 SSH 密钥(如已有可跳过)
ssh-keygen -t rsa -b 4096# 将公钥复制到云服务器
ssh-copy-id user@<云服务器IP>

3. Jenkins 凭据管理

在 Jenkins 控制台添加以下凭据:

  • SSH 用户名与私钥:用于连接云服务器。
  • Docker Hub 凭据(可选):用于推送镜像到 Docker Hub。

4. Jenkins Pipeline 详细配置

Pipeline 脚本优化
pipeline {agent anyenvironment {SERVER_IP = 'your-server-ip'DOCKER_HUB_REPO = 'your-dockerhub-username/flask-app'}stages {stage('Checkout') {steps {git branch: 'main', url: 'https://github.com/your-repo/flask-app.git'}}stage('Build Docker Image') {steps {script {docker.build("${DOCKER_HUB_REPO}:${env.BUILD_ID}")}}}stage('Push Docker Image') {steps {script {docker.withRegistry('https://registry.hub.docker.com', 'docker-hub-credentials-id') {docker.image("${DOCKER_HUB_REPO}:${env.BUILD_ID}").push()}}}}stage('Deploy to Server') {steps {sshagent(['ssh-credentials-id']) {sh """ssh -o StrictHostKeyChecking=no user@${SERVER_IP} 'docker pull ${DOCKER_HUB_REPO}:${env.BUILD_ID} && \docker stop flask-app || true && \docker rm flask-app || true && \docker run -d --name flask-app -p 5000:5000 ${DOCKER_HUB_REPO}:${env.BUILD_ID}'"""}}}}
}

5. 部署验证

  1. 访问应用
    在浏览器输入 http://<云服务器IP>:5000,应显示 “Hello, CI/CD!”。

  2. 查看容器日志

    docker logs flask-app
    

6. 常见问题与解决

问题 1:权限不足
  • 现象:Jenkins 无法执行 Docker 命令。
  • 解决:确保 Jenkins 用户已加入 docker 组:
    sudo usermod -aG docker jenkins
    sudo systemctl restart jenkins
    
问题 2:SSH 连接失败
  • 现象:Jenkins 无法连接到云服务器。
  • 解决
    1. 检查云服务器安全组是否开放 SSH 端口(默认 22)。
    2. 检查 SSH 密钥是否正确配置。

7. 安全加固建议

  • 限制 Jenkins 访问权限:通过 Nginx 反向代理并启用 HTTPS。
  • 定期更新镜像:在 Pipeline 中加入漏洞扫描步骤(如使用 trivy)。
  • 清理旧镜像:定期删除无用的 Docker 镜像以释放空间。

通过以上步骤,您可以实现从代码提交到部署的全自动化流程。如果需要更高级的配置(如蓝绿部署、回滚机制),可进一步探索 Jenkins 的高级特性!

总结

本文通过实战案例展示了如何使用 GitHub Actions 和 Jenkins 构建 CI/CD 流水线。GitHub Actions 适合轻量级的自动化任务,而 Jenkins 提供了更高的灵活性和可扩展性。结合 Docker 容器化技术,可以进一步简化部署流程并提高应用的一致性。
在这里插入图片描述


扩展思考

1. 如何优化 CI/CD 流程以减少资源消耗?

  • 使用缓存机制(如 GitHub Actions 的 cache 功能)避免重复安装依赖。
  • 并行化测试任务以缩短构建时间。
  • 定期清理过期的 Docker 镜像和 Jenkins 构建记录。

2. 探讨多团队协作中的 CI/CD 最佳实践

  • 统一代码风格和测试标准。
  • 使用分支策略(如 GitFlow)管理代码合并。
  • 定期审查 CI/CD 配置文件,确保其适应团队需求。

附录:相关资源

  • GitHub Actions 官方文档
  • Jenkins 官方文档
  • Docker 官方文档

http://www.ppmy.cn/devtools/169181.html

相关文章

枚举的定义及其使用

在Java中&#xff0c;enum&#xff08;枚举&#xff09;是一个特殊的类&#xff0c;用于表示一组常量。enum类型在Java中提供了一种类型安全的方式来定义常量&#xff0c;相比传统的常量&#xff08;如public static final变量&#xff09;&#xff0c;它更加简洁、类型安全&am…

Vue3 基础语法指南:响应式系统与 Ref 应用

1、Reactive 的深度响应式 1.1、基本用法 vue <script setup> import { reactive } from vueconst state reactive({count: 0,user: {name: Alice,age: 30} })const increment () > state.count const updateName () > state.user.name Bob </script>1…

StarRocks 升级注意事项

前段时间升级了生产环境的 StarRocks&#xff0c;从 3.3.3 升级到了 3.3.9&#xff0c;期间还是踩了不少坑所以在这里记录下。 因为我们的集群使用的是存算分离的版本&#xff0c;也是使用官方提供的 operator 部署在 kubernetes 里的&#xff0c;所以没法按照官方的流程进入虚…

人工智能之数学基础:高斯消元法求解线性方程组

本文重点 前面我们已经学习过了矩阵,以及矩阵的一系列含义,相信此时此刻在你的眼中矩阵已经不是一个简单的东西了,它是线性代数中的函数。将线性方程组中的系数组成一个矩阵,就可以通过这个矩阵来求解方程组的解了,本文介绍高斯消元法求解线性方程组。 线性方程组的矩阵…

ES、Kibana一键式部署脚本执行文件,外加IK分词器和拼音分词器

#!/bin/bash# 设置变量 ES_VERSION"7.12.1" KIBANA_VERSION"7.12.1" ES_CONTAINER"es" KIBANA_CONTAINER"kibana" NETWORK_NAME"es-net" ES_DATA_VOLUME"es-data" ES_PLUGINS_VOLUME"es-plugins" ES_PO…

HTML5拖拽功能教程

HTML5拖拽功能教程 简介 HTML5引入了原生拖放(Drag and Drop)API&#xff0c;使开发者能够轻松实现网页中的拖拽功能&#xff0c;无需依赖第三方库。拖拽功能可以大大提升用户体验&#xff0c;适用于文件上传、列表排序、看板系统等多种交互场景。本教程将带您全面了解HTML拖…

数据类设计_图片类设计之7_矩阵图形类设计更新_实战之页面简单设计(前端架构)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 前面讲过的混合类型设计,实际上是矩阵类图形设计(名称已更新).他能够产生的视觉效果是这样的: 注意:外层的矩形边框可以不存在,只是说明了图形存在于一个矩形区…

Java 第十一章 GUI编程(3)

目录 内部类 内部类定义 内部类的特点 匿名内部类 格式&#xff1a; 内部类的意义 实例 内部类 ● 把类定义在另一个类的内部&#xff0c;该类就被称为内部类。 ● 如果在类 Outer 的内部再定义一个类 Inner&#xff0c;此时类 Inner 就称为内部类 &#xff08;或称为嵌…