diff --git a/.github/RELEASE_SETUP.md b/.github/RELEASE_SETUP.md index d5112ae..48561b4 100644 --- a/.github/RELEASE_SETUP.md +++ b/.github/RELEASE_SETUP.md @@ -53,10 +53,10 @@ When a PR is merged into `main` or `master`, the release workflow will: 1. Parse the PR title using Conventional Commit style. - Required ticket format: `type: [FEEDS-1234] description` - Keep `feat`/`fix`/`bug` at the beginning of the title -2. Decide the bump type: +2. Decide the bump type from the PR title (the body is not scanned): - `feat:` => minor - `fix:` or `bug:` => patch - - `feat!:` / `fix!:` / `BREAKING CHANGE` => major + - `feat!:` / `fix!:` / `(scope)!:` (the `!` marker) => major 3. Update `composer.json` and `src/Constant.php` via `scripts/release/bump_version.php` 4. Commit version files, create a `vX.Y.Z` tag, create a GitHub release 5. Trigger Packagist update diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d7b3b00..a9bb496 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,13 +71,9 @@ jobs: if: github.event_name == 'pull_request' && steps.already_released.outputs.value != 'true' env: PR_TITLE: ${{ github.event.pull_request.title }} - PR_BODY: ${{ github.event.pull_request.body }} run: | - PR_BODY_FILE=$(mktemp) - printf '%s' "$PR_BODY" > "$PR_BODY_FILE" php scripts/release/bump_version.php \ --title "$PR_TITLE" \ - --body-file "$PR_BODY_FILE" \ --output "$GITHUB_OUTPUT" - name: Determine and apply version bump (manual) diff --git a/README.md b/README.md index 28593f3..4a585d7 100644 --- a/README.md +++ b/README.md @@ -180,10 +180,10 @@ Releases are automated when a pull request is merged into `main` or `master`. - PR titles must follow Conventional Commit format (for example: `feat: ...`, `fix: ...`). - Ticket prefix is required in the subject: `type: [FEEDS-1234] description`. - Keep the commit type first so release automation can parse it. -- Version bump is derived from PR title/body: +- Version bump is derived from the PR title: - `feat:` => minor - `fix:` or `bug:` => patch - - `feat!:` / `fix!:` / `BREAKING CHANGE` => major + - `feat!:` / `fix!:` / `(scope)!:` (the `!` marker) => major - Non-release types like `chore:`, `docs:`, `test:` do not create a release. - The release workflow updates `composer.json` and `src/Constant.php`, pushes a tag, creates a GitHub release, and triggers Packagist. diff --git a/scripts/release/bump_version.php b/scripts/release/bump_version.php index 70a1578..e4e7351 100644 --- a/scripts/release/bump_version.php +++ b/scripts/release/bump_version.php @@ -3,10 +3,9 @@ declare(strict_types=1); /** - * Computes next release version from PR title/body and updates version files. + * Computes next release version from the PR title and updates version files. * Usage: - * php scripts/release/bump_version.php --title "feat: add x" --body "..." --output "$GITHUB_OUTPUT" - * php scripts/release/bump_version.php --title "feat: add x" --body-file "/tmp/body.txt" --output "$GITHUB_OUTPUT" + * php scripts/release/bump_version.php --title "feat: add x" --output "$GITHUB_OUTPUT" */ final class ReleaseScriptException extends RuntimeException { @@ -59,17 +58,12 @@ function findLatestSemverTag(): string return end($versions) ?: '0.0.0'; } -function determineBumpType(string $title, string $body): string +function determineBumpType(string $title): string { + // Breaking changes are signalled only by the `!` marker in the title + // (e.g. `feat!:`). Free-text body/title prose is not trusted: a PR that + // merely mentions the major-bump phrase must not force a major bump. $title = trim($title); - $body = trim($body); - - if ( - preg_match('/BREAKING[ -]CHANGES?/i', $title) === 1 - || preg_match('/BREAKING[ -]CHANGES?/i', $body) === 1 - ) { - return 'major'; - } if (preg_match('/^([a-z]+)(\([^)]+\))?(!)?:/i', $title, $matches) !== 1) { return 'none'; @@ -198,22 +192,7 @@ function writeOutputs(string $outputPath, array $values): void file_put_contents($outputPath, implode(PHP_EOL, $lines) . PHP_EOL, FILE_APPEND); } -function resolveBody(array $argv): string -{ - $bodyFile = getArgValue($argv, 'body-file'); - if ($bodyFile !== '') { - $raw = file_get_contents($bodyFile); - if ($raw === false) { - throw new ReleaseScriptException('Could not read body-file'); - } - return $raw; - } - - return getArgValue($argv, 'body'); -} - $title = getArgValue($argv, 'title'); -$body = resolveBody($argv); $outputPath = getArgValue($argv, 'output'); $manualBump = strtolower(trim(getArgValue($argv, 'manual-bump'))); $useCurrentVersion = strtolower(trim(getArgValue($argv, 'use-current-version', 'false'))) === 'true'; @@ -243,7 +222,7 @@ function resolveBody(array $argv): string exit(0); } -$bump = determineBumpType($title, $body); +$bump = determineBumpType($title); if ($bump === 'none') { writeOutputs($outputPath, [ 'should_release' => 'false',