PHP自动化构建与持续交付流水线
自动化构建和持续交付是现代软件开发的基础设施。今天说说PHP项目的构建、测试、部署流水线的各个阶段。
构建阶段包括代码检查、依赖安装、静态分析和单元测试。
```php
// 构建状态追踪
class BuildPipeline
{
private string $buildId;
private string $branch;
private string $commit;
private array $stages = [];
private string $status = 'pending';
private ?string $error = null;
public function __construct(string $branch, string $commit)
{
$this->buildId = date('Ymd') . '_' . uniqid();
$this->branch = $branch;
$this->commit = $commit;
}
public function runStage(string $name, callable $stage): bool
{
echo "\n=== {$name} ===\n";
$startTime = microtime(true);
try {
$stage();
$duration = round((microtime(true) - $startTime) * 1000);
$this->stages[] = ['name' => $name, 'status' => 'success', 'duration' => $duration];
echo " 完成 ({$duration}ms)\n";
return true;
} catch (\Exception $e) {
$duration = round((microtime(true) - $startTime) * 1000);
$this->stages[] = ['name' => $name, 'status' => 'failed', 'duration' => $duration];
$this->error = $e->getMessage();
$this->status = 'failed';
echo " 失败: {$e->getMessage()}\n";
return false;
}
}
public function execute(array $stages): void
{
echo "构建 #{$this->buildId} 开始\n";
echo "分支: {$this->branch}, 提交: {$this->commit}\n";
foreach ($stages as $name => $stage) {
if (!$this->runStage($name, $stage)) {
echo "\n构建失败\n";
$this->status = 'failed';
return;
}
}
$this->status = 'success';
echo "\n构建成功\n";
}
public function getSummary(): array
{
$totalDuration = array_sum(array_column($this->stages, 'duration'));
return [
'build_id' => $this->buildId,
'branch' => $this->branch,
'commit' => $this->commit,
'status' => $this->status,
'stages' => $this->stages,
'total_duration_ms' => $totalDuration,
'error' => $this->error,
];
}
}
$build = new BuildPipeline('main', 'abc1234');
$build->execute([
'语法检查' => function () {
exec('php -l src/index.php 2>&1', $output, $code);
if ($code !== 0) throw new \RuntimeException(implode("\n", $output));
},
'依赖安装' => function () {
exec('composer install --no-dev --no-progress 2>&1', $output, $code);
if ($code !== 0) throw new \RuntimeException('Composer安装失败');
},
'单元测试' => function () {
exec('vendor/bin/phpunit --no-coverage 2>&1', $output, $code);
if ($code !== 0) throw new \RuntimeException('单元测试失败');
},
]);
print_r($build->getSummary());
?>
>
版本号管理和自动发布:
```php
class VersionManager
{
private string $versionFile;
private array $version;
public function __construct(string $versionFile = 'VERSION')
{
$this->versionFile = $versionFile;
$this->version = $this->load();
}
private function load(): array
{
if (file_exists($this->versionFile)) {
$content = trim(file_get_contents($this->versionFile));
$parts = explode('.', $content);
return [
'major' => (int)($parts[0] ?? 1),
'minor' => (int)($parts[1] ?? 0),
'patch' => (int)($parts[2] ?? 0),
];
}
return ['major' => 1, 'minor' => 0, 'patch' => 0];
}
public function getVersion(): string
{
return "{$this->version['major']}.{$this->version['minor']}.{$this->version['patch']}";
}
public function bumpMajor(): string
{
$this->version['major']++;
$this->version['minor'] = 0;
$this->version['patch'] = 0;
return $this->save();
}
public function bumpMinor(): string
{
$this->version['minor']++;
$this->version['patch'] = 0;
return $this->save();
}
public function bumpPatch(): string
{
$this->version['patch']++;
return $this->save();
}
private function save(): string
{
$version = $this->getVersion();
file_put_contents($this->versionFile, $version);
return $version;
}
public function generateChangelog(array $changes): string
{
$date = date('Y-m-d');
$version = $this->getVersion();
$log = "## [{$version}] - {$date}\n\n";
foreach ($changes as $type => $items) {
if (!empty($items)) {
$log .= "### {$type}\n";
foreach ($items as $item) {
$log .= "- {$item}\n";
}
$log .= "\n";
}
}
$changelogFile = 'CHANGELOG.md';
$existing = file_exists($changelogFile) ? file_get_contents($changelogFile) : '';
file_put_contents($changelogFile, $log . $existing);
return $version;
}
}
$version = new VersionManager();
echo "当前版本: {$version->getVersion()}\n";
$changes = [
'新增' => ['用户注册功能', '订单导出功能'],
'修复' => ['修复了分页bug', '修复了登录超时问题'],
];
$newVersion = $version->generateChangelog($changes);
echo "新版本: {$newVersion}\n";
// 自动打Tag
$tag = "v{$newVersion}";
exec("git tag -a {$tag} -m 'Release {$tag}'");
exec("git push origin {$tag}");
echo "Git Tag: {$tag}\n";
?>
构建产物管理和自动化部署脚本:
```php
class ArtifactManager
{
private string $artifactDir;
public function __construct(string $artifactDir = '/var/www/artifacts')
{
$this->artifactDir = rtrim($artifactDir, '/');
if (!is_dir($this->artifactDir)) mkdir($this->artifactDir, 0755, true);
}
public function build(string $sourceDir, string $version): string
{
$artifactName = "app-{$version}.tar.gz";
$artifactPath = "{$this->artifactDir}/{$artifactName}";
$exclude = ['--exclude=.git', '--exclude=node_modules', '--exclude=tests'];
$excludeStr = implode(' ', $exclude);
exec("tar -czf {$artifactPath} {$excludeStr} -C {$sourceDir} . 2>&1", $output, $code);
if ($code !== 0) {
throw new \RuntimeException("构建失败: " . implode("\n", $output));
}
echo "构建产物: {$artifactPath} (" . round(filesize($artifactPath) / 1024 / 1024, 2) . "MB)\n";
return $artifactPath;
}
public function deploy(string $artifact, string $targetDir): void
{
if (!file_exists($artifact)) {
throw new \RuntimeException("构建产物不存在: {$artifact}");
}
if (!is_dir($targetDir)) mkdir($targetDir, 0755, true);
exec("tar -xzf {$artifact} -C {$targetDir} 2>&1", $output, $code);
if ($code !== 0) {
throw new \RuntimeException("部署失败: " . implode("\n", $output));
}
$this->setPermissions($targetDir);
echo "部署完成: {$targetDir}\n";
}
private function setPermissions(string $dir): void
{
exec("chmod -R 755 {$dir}");
if (is_dir("{$dir}/storage")) {
exec("chmod -R 775 {$dir}/storage");
}
}
}
?>
自动化构建和持续交付是DevOps实践的核心。自动化流水线确保代码质量,减少人工操作,加快交付速度。构建、测试、部署的自动化程度越高,团队的交付效率也就越高。
PHP自动化构建与持续交付流水线
张小明
前端开发工程师
JoyAI-Image-Edit模型部署指南:从开发到生产的完整流程
JoyAI-Image-Edit模型部署指南:从开发到生产的完整流程 【免费下载链接】JoyAI-Image-Edit-Diffusers 项目地址: https://ai.gitcode.com/jd-x-opensource/JoyAI-Image-Edit-Diffusers 想要快速掌握先进的AI图像编辑技术吗?JoyAI-Image-Edit作为…
微信小程序逆向工程完全指南:Wedecode工具深度解析与实战应用
微信小程序逆向工程完全指南:Wedecode工具深度解析与实战应用 【免费下载链接】wedecode 全自动化,微信小程序 wxapkg 包 源代码还原工具, 线上代码安全审计,支持 Windows, Macos, Linux 项目地址: https://gitcode.com/gh_mirrors/we/wede…
PHP混沌工程与故障注入测试
PHP混沌工程与故障注入测试混沌工程通过主动引入故障来验证系统的容错能力。故障注入可以测试系统在异常情况下的表现。今天说说PHP中实现混沌工程和故障注入的方法。故障注入是在代码层面模拟各种异常情况,验证系统的容错逻辑。phpclass ChaosEngine { private arr…
5G速率上不去?从PDSCH码率控制算法入手,看懂调度器的‘小心思’
5G速率优化实战:解码PDSCH码率控制算法的底层逻辑当你在5G现网测试中盯着屏幕上始终无法突破的吞吐率曲线时,是否思考过调度器背后的决策机制?作为无线网络优化的核心战场,PDSCH码率控制算法直接决定了空口传输效率的天花板。本文…
Linux下大恒GigE相机驱动安装避坑指南:从下载到成功采集图像的完整流程
Linux下大恒GigE相机驱动安装实战:从零到图像采集的完整解决方案工业视觉领域的开发者们,是否曾在Linux系统下为GigE相机的驱动安装抓耳挠腮?大恒(Daheng Imaging)作为国内机器视觉领域的重要厂商,其GigE接…
保姆级教程:在Windows上用Python调用SUMO的TraCI接口(含环境变量配置避坑指南)
Windows下Python与SUMO的TraCI接口实战指南:从零配置到避坑全解析 当交通仿真遇上Python自动化,SUMO的TraCI接口便成为研究者手中的瑞士军刀。但无数新手在Windows系统配置的第一步就遭遇滑铁卢——环境变量报错、路径识别失败、依赖项缺失等问题层出不…