Python實(shí)現(xiàn)Linux系統(tǒng)上CI/CD工作流的方法詳解
完整實(shí)現(xiàn)代碼
#!/usr/bin/env python3
import subprocess
import os
import sys
import time
import logging
import argparse
import shlex
from pathlib import Path
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[logging.FileHandler("ci_cd.log"), logging.StreamHandler()]
)
logger = logging.getLogger("CI/CD")
class CICD:
def __init__(self, repo_path, branch="main"):
self.repo_path = Path(repo_path).resolve()
self.branch = branch
self.last_commit = None
self._check_dependencies(["git", "docker"])
def _check_dependencies(self, deps):
for cmd in deps:
try:
subprocess.run([cmd, "--version"], check=True,
stdout=subprocess.DEVNULL)
except Exception:
raise RuntimeError(f"缺少依賴: {cmd}")
def check_updates(self):
try:
# 檢查遠(yuǎn)程更新
subprocess.run(["git", "-C", str(self.repo_path), "fetch"], check=True)
# 比較本地與遠(yuǎn)程差異
diff = subprocess.run(
["git", "-C", str(self.repo_path), "diff", "--shortstat", f"origin/{self.branch}"],
stdout=subprocess.PIPE
)
if not diff.stdout.strip():
return False
# 拉取最新代碼
subprocess.run(
["git", "-C", str(self.repo_path), "pull", "origin", self.branch],
check=True
)
# 獲取最新提交ID
new_commit = subprocess.check_output(
["git", "-C", str(self.repo_path), "rev-parse", "HEAD"]
).decode().strip()
if new_commit != self.last_commit:
self.last_commit = new_commit
return True
return False
except subprocess.CalledProcessError as e:
logger.error(f"代碼更新失敗: {str(e)}")
raise
def run_tests(self):
try:
subprocess.run(["pytest", "tests/"], cwd=self.repo_path, check=True)
return True
except subprocess.CalledProcessError:
logger.error("測(cè)試失敗")
return False
def build(self):
try:
subprocess.run(
["docker", "build", "-t", "myapp:latest", "."],
cwd=self.repo_path, check=True
)
return True
except subprocess.CalledProcessError:
logger.error("構(gòu)建失敗")
return False
def deploy(self):
try:
# 停止舊容器
subprocess.run(["docker", "stop", "myapp"], check=False)
# 啟動(dòng)新容器
subprocess.run(
["docker", "run", "--rm", "-d", "--name", "myapp", "-p", "8000:8000", "myapp:latest"],
check=True
)
return True
except subprocess.CalledProcessError:
logger.error("部署失敗")
return False
def run_pipeline(self):
if not self.check_updates():
logger.info("無(wú)代碼更新")
return True
logger.info(f"檢測(cè)到新提交: {self.last_commit[:8]}")
return self.run_tests() and self.build() and self.deploy()
def main():
parser = argparse.ArgumentParser(description="CI/CD 流水線")
parser.add_argument("--repo", required=True, help="倉(cāng)庫(kù)路徑")
parser.add_argument("--branch", default="main", help="監(jiān)控分支")
parser.add_argument("--daemon", action="store_true", help="守護(hù)模式")
parser.add_argument("--interval", type=int, default=60, help="檢查間隔")
args = parser.parse_args()
try:
ci = CICD(args.repo, args.branch)
if args.daemon:
while True:
ci.run_pipeline()
time.sleep(args.interval)
else:
success = ci.run_pipeline()
sys.exit(0 if success else 1)
except Exception as e:
logger.error(f"流程異常: {str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()
使用說(shuō)明
安裝依賴:
pip install pytest docker
運(yùn)行方式:
# 單次運(yùn)行模式 python ci_cd.py --repo /path/to/repo --branch main # 守護(hù)進(jìn)程模式(每5分鐘檢查一次) python ci_cd.py --repo ~/myapp --daemon --interval 300
自定義命令參數(shù):
# 使用自定義測(cè)試命令 python ci_cd.py --repo ~/project \ --test-cmd "npm run test" \ --build-cmd "docker build -t myapp:v1 ." \ --deploy-cmd "kubectl apply -f deploy.yaml"
Git Hook 集成(可選): 在 .git/hooks/post-receive 中添加:
#!/bin/sh python /path/to/ci_cd.py --repo $(pwd)
擴(kuò)展功能建議
通知功能:
# 添加至 CICD 類
def send_notification(self, message):
import requests
requests.post(
"https://api.alert.com/notify",
json={"text": f"[CI/CD] {message}"}
)
# 在部署成功后調(diào)用
self.send_notification(f"部署成功: {self.last_commit[:8]}")
健康檢查:
def health_check(self):
import requests
try:
resp = requests.get("http://localhost:8000/health", timeout=5)
return resp.status_code == 200
except Exception:
return False
配置文件支持: 創(chuàng)建 config.yaml:
repo: ~/myapp branch: dev test_cmd: "npm test" build_cmd: "docker build -t myapp:latest ."
關(guān)鍵注意事項(xiàng)
1.權(quán)限管理:
確保運(yùn)行用戶具有 Docker 執(zhí)行權(quán)限
建議將用戶加入 docker 用戶組:
sudo usermod -aG docker $USER
2.安全建議:
- 通過(guò)環(huán)境變量管理敏感信息(如 API 密鑰)
- 使用
--env-file傳遞 Docker 環(huán)境變量
3.錯(cuò)誤處理:
- 重要操作建議添加重試機(jī)制
- 部署失敗時(shí)可自動(dòng)回滾到上一個(gè)版本
4.性能優(yōu)化:
- 使用 Docker 緩存加速構(gòu)建
- 并行執(zhí)行測(cè)試任務(wù)
到此這篇關(guān)于Python實(shí)現(xiàn)Linux系統(tǒng)上CI/CD工作流的方法詳解的文章就介紹到這了,更多相關(guān)Python實(shí)現(xiàn)CI/CD工作流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python3和PyCharm安裝與環(huán)境配置【圖文教程】
這篇文章主要介紹了Python3和PyCharm安裝與環(huán)境配置,結(jié)合圖文形式詳細(xì)分析了Python3和PyCharm的安裝、環(huán)境配置、測(cè)試命令及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-02-02
用python實(shí)現(xiàn)操縱mysql數(shù)據(jù)庫(kù)插入
大家好,本篇文章主要講的是用python實(shí)現(xiàn)操縱mysql數(shù)據(jù)庫(kù)插入,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
Python 利用高德地圖api實(shí)現(xiàn)經(jīng)緯度與地址的批量轉(zhuǎn)換
這篇文章主要介紹了Python 利用高德地圖api實(shí)現(xiàn)經(jīng)緯度與地址的批量轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
分享5個(gè)數(shù)據(jù)處理更加靈活的pandas調(diào)用函數(shù)方法
這篇文章主要介紹了分享5個(gè)數(shù)據(jù)處理更加靈活的pandas調(diào)用函數(shù)方法,文章基于python的相關(guān)內(nèi)容展開詳細(xì)介紹,需要的小伙伴可以參考一下2022-04-04
Python如何利用pandas讀取csv數(shù)據(jù)并繪圖
這篇文章主要介紹了Python如何利用pandas讀取csv數(shù)據(jù)并繪圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
python+pandas+時(shí)間、日期以及時(shí)間序列處理方法
今天小編就為大家分享一篇python+pandas+時(shí)間、日期以及時(shí)間序列處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
簡(jiǎn)單總結(jié)Python中序列與字典的相同和不同之處
這篇文章主要介紹了Python中序列與字典的相同和不同之處,序列這里講到Python中最常用的列表和元組以及字典三種,需要的朋友可以參考下2016-01-01
Python通用函數(shù)實(shí)現(xiàn)數(shù)組計(jì)算的方法
數(shù)組的運(yùn)算可以進(jìn)行加減乘除,同時(shí)也可以將這些算數(shù)運(yùn)算符進(jìn)行任意的組合已達(dá)到效果。這篇文章主要介紹了Python通用函數(shù)實(shí)現(xiàn)數(shù)組計(jì)算的代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2019-06-06

