本文目录导读:

我来详细介绍PHP自动化语义发布的实现方法:
语义化版本(SemVer)基础
// 语义化版本格式:MAJOR.MINOR.PATCH // MAJOR: 不兼容的API修改 // MINOR: 向后兼容的功能性新增 // PATCH: 向后兼容的问题修正
自动化版本管理工具
1 使用 semantic-release
// package.json (在PHP项目中使用)
{
"scripts": {
"semantic-release": "semantic-release"
},
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/git"
]
}
2 PHP专用工具:Conventional Commits
{
"require-dev": {
"symplify/monorepo-builder": "^10.0",
"semver/semver": "^3.0"
}
}
实现自动化发布脚本
1 基础发布脚本
<?php
// publish.php
class SemanticPublisher
{
private $versionFile;
private $changelogFile;
public function __construct($versionFile = 'VERSION', $changelogFile = 'CHANGELOG.md')
{
$this->versionFile = $versionFile;
$this->changelogFile = $changelogFile;
}
public function publish()
{
// 获取当前版本
$currentVersion = $this->getCurrentVersion();
// 分析提交信息
$newVersion = $this->analyzeCommits($currentVersion);
// 更新版本号
$this->updateVersion($newVersion);
// 生成变更日志
$this->generateChangelog($newVersion);
// 创建Git标签
$this->createGitTag($newVersion);
echo "Published version: {$newVersion}\n";
}
private function getCurrentVersion()
{
if (file_exists($this->versionFile)) {
return trim(file_get_contents($this->versionFile));
}
return '0.0.0';
}
private function analyzeCommits($currentVersion)
{
// 获取最新提交
$commits = $this->getGitLog();
$major = $minor = $patch = 0;
foreach ($commits as $commit) {
if (preg_match('/^BREAKING CHANGE:/', $commit)) {
$major++;
} elseif (preg_match('/^feat\(/', $commit)) {
$minor++;
} elseif (preg_match('/^fix\(/', $commit)) {
$patch++;
}
}
list($curMajor, $curMinor, $curPatch) = explode('.', $currentVersion);
return ($curMajor + $major) . '.' .
($curMinor + $minor) . '.' .
($curPatch + $patch);
}
private function getGitLog($from = null, $to = 'HEAD')
{
$cmd = "git log --oneline";
if ($from) {
$cmd .= " $from..$to";
}
return explode("\n", shell_exec($cmd));
}
private function updateVersion($newVersion)
{
file_put_contents($this->versionFile, $newVersion);
// 更新composer.json版本
$composer = json_decode(file_get_contents('composer.json'), true);
$composer['version'] = $newVersion;
file_put_contents('composer.json', json_encode($composer, JSON_PRETTY_PRINT));
}
private function generateChangelog($newVersion)
{
$changelog = "# Changelog\n\n";
$changelog .= "## {$newVersion} ({date('Y-m-d')})\n\n";
$commits = $this->getGitLog($this->getLastTag());
foreach ($commits as $commit) {
$changelog .= "- {$commit}\n";
}
file_put_contents($this->changelogFile, $changelog);
}
private function createGitTag($version)
{
$commands = [
"git add {$this->versionFile} {$this->changelogFile} composer.json",
"git commit -m \"chore: release {$version}\"",
"git tag v{$version}",
"git push origin main --tags"
];
foreach ($commands as $cmd) {
shell_exec($cmd);
}
}
private function getLastTag()
{
return trim(shell_exec('git describe --tags --abbrev=0'));
}
}
// 执行发布
$publisher = new SemanticPublisher();
$publisher->publish();
2 使用Composer脚本自动化
// composer.json
{
"scripts": {
"pre-release": "php scripts/pre-release.php",
"post-release": "php scripts/post-release.php",
"release": [
"@pre-release",
"php scripts/publish.php",
"@post-release"
]
}
}
提交信息规范化
1 创建Git提交钩子
<?php
// .git/hooks/commit-msg
class CommitValidator
{
public function validate($message)
{
$patterns = [
'feat' => '/^feat(\(.+\))?: /',
'fix' => '/^fix(\(.+\))?: /',
'docs' => '/^docs(\(.+\))?: /',
'style' => '/^style(\(.+\))?: /',
'refactor' => '/^refactor(\(.+\))?: /',
'test' => '/^test(\(.+\))?: /',
'chore' => '/^chore(\(.+\))?: /',
'BREAKING CHANGE' => '/^BREAKING CHANGE: /'
];
foreach ($patterns as $type => $pattern) {
if (preg_match($pattern, $message)) {
return true;
}
}
return false;
}
}
// 检查提交信息
$message = file_get_contents($argv[1]);
$validator = new CommitValidator();
if (!$validator->validate($message)) {
echo "Error: Commit message must follow conventional format\n";
echo "Example: feat(api): add new endpoint\n";
exit(1);
}
集成GitHub Actions
# .github/workflows/release.yml
name: Release
on:
push:
branches: [ main ]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- name: Install dependencies
run: composer install
- name: Run Semantic Release
run: |
composer config version
php scripts/semantic-release.php
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.RELEASE_TAG }}
body_path: CHANGELOG.md
自动化发布辅助函数
<?php
// SemanticHelper.php
class SemanticHelper
{
// 分析提交类型
public function analyzeCommitType($commitMessage)
{
if (preg_match('/breaking change/i', $commitMessage)) {
return 'major';
}
if (preg_match('/^feat/i', $commitMessage)) {
return 'minor';
}
if (preg_match('/^fix|^bug|^hotfix/i', $commitMessage)) {
return 'patch';
}
return null;
}
// 生成变更日志
public function generateChangelog($commits, $version, $date)
{
$changelog = "\n## $version ($date)\n\n";
$categories = [
'Features' => 'feat',
'Bug Fixes' => 'fix',
'Documents' => 'docs',
'Refactoring' => 'refactor',
'Tests' => 'test',
'Style' => 'style',
'Chores' => 'chore'
];
foreach ($categories as $title => $prefix) {
$items = array_filter($commits, function($commit) use ($prefix) {
return strpos($commit, $prefix . ':') === 0 ||
strpos($commit, $prefix . '(') === 0;
});
if (!empty($items)) {
$changelog .= "### $title\n";
foreach ($items as $item) {
$changelog .= "- $item\n";
}
$changelog .= "\n";
}
}
return $changelog;
}
// 更新版本配置文件
public function updateVersionConfig($filePath, $newVersion)
{
$config = json_decode(file_get_contents($filePath), true);
$config['version'] = $newVersion;
file_put_contents($filePath, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
// 推送通知
public function sendReleaseNotification($version, $changelog)
{
// 可以集成Slack、Telegram、邮件等通知
$message = "🚀 New Release v$version\n\n" . substr($changelog, 0, 500);
// 发送到Slack
if (getenv('SLACK_WEBHOOK')) {
file_get_contents(getenv('SLACK_WEBHOOK'), false, stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode(['text' => $message])
]
]));
}
}
}
使用PHP库简化流程
<?php
// 使用semver库
require 'vendor/autoload.php';
use SemVer\SemVer;
class AutomatedReleaser
{
public function determineNextVersion($currentVersion, $commits)
{
$semver = new SemVer($currentVersion);
$type = 'patch'; // 默认patch
foreach ($commits as $commit) {
if (preg_match('/breaking/i', $commit)) {
$type = 'major';
break;
} elseif (preg_match('/^feat/i', $commit)) {
$type = 'minor';
}
}
switch ($type) {
case 'major':
return $semver->major()->value;
case 'minor':
return $semver->minor()->value;
default:
return $semver->patch()->value;
}
}
}
完整示例配置文件
// semantic-release.php
<?php
return [
'project' => 'my-php-app',
'version_file' => 'VERSION',
'changelog_file' => 'CHANGELOG.md',
'git' => [
'branch' => 'main',
'commit_prefix' => 'chore: release'
],
'releases' => [
'auto_version' => true,
'generate_changelog' => true,
'create_git_tag' => true,
'push_to_remote' => true
],
'notifications' => [
'slack_webhook' => env('SLACK_WEBHOOK'),
'telegram_bot' => env('TELEGRAM_BOT'),
'email' => env('RELEASE_EMAIL')
],
'plugins' => [
'post_release' => [
'php scripts/deploy.php',
'composer dump-autoload --optimize'
]
]
];
通过这些工具和方法,你可以实现自动化的语义化发布流程,核心要点包括:规范化的提交信息、自动版本计算、变更日志生成、Git标签和发布管理。