diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 900d71e..789f62d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,13 +68,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" ruby scripts/release/bump_version.rb \ --title "$PR_TITLE" \ - --body-file "$PR_BODY_FILE" \ --output "$GITHUB_OUTPUT" - name: Determine version bump (manual) diff --git a/README.md b/README.md index 9c87cf7..a7aeb8a 100644 --- a/README.md +++ b/README.md @@ -352,14 +352,14 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/getstr Releases use two paths, both handled by `.github/workflows/release.yml`: -- **Default**: automatic release when a PR is merged to `main`/`master`. The PR title (and body) drives the semver bump. +- **Default**: automatic release when a PR is merged to `main`/`master`. The PR title drives the semver bump. - **Fallback**: manual release via the `Release` workflow's `workflow_dispatch` (admin use). Select a `version_bump` (`patch`/`minor`/`major`). `use_current_version=true` skips the bump and publishes whatever is already in `lib/getstream_ruby/version.rb`. Automatic semver bump rules: - `feat:` -> minor - `fix:` (or `bug:`) -> patch -- `feat!:`, `(scope)!:`, or `BREAKING CHANGE` in the PR body/title -> major +- `feat!:` or `(scope)!:` (the `!` marker) -> major PRs with any other prefix do not trigger a release. diff --git a/scripts/release/bump_version.rb b/scripts/release/bump_version.rb index e5e41ee..7bf0829 100755 --- a/scripts/release/bump_version.rb +++ b/scripts/release/bump_version.rb @@ -15,9 +15,10 @@ def find_latest_semver_tag versions.max_by { |version| version.split('.').map(&:to_i) } end -def determine_bump_type(title, body) - return 'major' if body.match?(/BREAKING[ -]CHANGE/i) || title.match?(/BREAKING[ -]CHANGE/i) - +def determine_bump_type(title) + # 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 "BREAKING CHANGE" must not force a major bump. match = title.strip.match(/^([a-z]+)(\([^)]+\))?(!)?:/i) return 'none' unless match @@ -76,8 +77,6 @@ def truthy?(value) options = { title: '', - body: '', - body_file: '', output: '', manual_bump: '', use_current_version: 'false', @@ -86,8 +85,6 @@ def truthy?(value) OptionParser.new do |opts| opts.on('--title TITLE') { |value| options[:title] = value } - opts.on('--body BODY') { |value| options[:body] = value } - opts.on('--body-file FILE') { |value| options[:body_file] = value } opts.on('--output FILE') { |value| options[:output] = value } opts.on('--manual-bump TYPE') { |value| options[:manual_bump] = value } opts.on('--use-current-version VAL') { |value| options[:use_current_version] = value } @@ -123,13 +120,7 @@ def truthy?(value) exit(0) end -body = if options[:body_file].empty? - options[:body].to_s - else - File.read(options[:body_file]) - end - -bump = determine_bump_type(options[:title].to_s, body.to_s) +bump = determine_bump_type(options[:title].to_s) if bump == 'none' write_outputs(options[:output], { 'should_release' => 'false',