Skip to content

Commit

Permalink
Add support for pre-release versions (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouball authored Jan 7, 2024
1 parent c82e1d4 commit 80da449
Show file tree
Hide file tree
Showing 68 changed files with 1,701 additions and 941 deletions.
1 change: 1 addition & 0 deletions .yardopts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
--hide-void-return
--markup-provider=redcarpet
--markup markdown
- CHANGELOG.md
- LICENSE.txt
194 changes: 156 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,46 @@
[![Maintainability](https://api.codeclimate.com/v1/badges/b8c0af10b15a0ffeb1a1/maintainability)](https://codeclimate.com/github/main-branch/create_github_release/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/b8c0af10b15a0ffeb1a1/test_coverage)](https://codeclimate.com/github/main-branch/create_github_release/test_coverage)

A script to manage your gem version and create a GitHub branch, PR, and release
for a new gem version.

Since this script builds a changelog by listing the commits on the default branch,
it works best if you are disciplined about squashing PR commits to the
minimum number of commits necessary (usually one) in order to avoid a noisy changelog.

Tested on Ruby 2.7+

* [The create\_github\_release Gem](#the-create_github_release-gem)
* [Installation](#installation)
* [Usage](#usage)
* [First release using this script when there were NO prior releases](#first-release-using-this-script-when-there-were-no-prior-releases)
* [First release using this script when there were prior releases](#first-release-using-this-script-when-there-were-prior-releases)
* [Subsequent releases using this script](#subsequent-releases-using-this-script)
When run in your gem's git worktree, the `create-github-release` script does the
following:

* bumps the gem's version following SemVer,
* updates the gems's changelog,
* creates a new release branch and release tag,
* commits the version and changelog changes to the release branch,
* pushes these changes to GitHub and creates a PR to merge the release branch to the
default branch

Since this script builds a changelog by listing the commits since the last release, it
works best if you are disciplined about squashing PR commits to the minimum number of
commits necessary (usually one) in order to avoid a noisy changelog.

Tested on Ruby 3.0+

* [Installation](#installation)
* [Usage](#usage)
* [First release using this script when there were NO prior releases](#first-release-using-this-script-when-there-were-no-prior-releases)
* [First release using this script when there were prior releases](#first-release-using-this-script-when-there-were-prior-releases)
* [Subsequent releases using this script](#subsequent-releases-using-this-script)
* [Pre-release versions](#pre-release-versions)
* [Creating the first pre-release version for a release](#creating-the-first-pre-release-version-for-a-release)
* [Creating subsequent pre-releases](#creating-subsequent-pre-releases)
* [Changing the pre-release type](#changing-the-pre-release-type)
* [Creating the release after pre-releases](#creating-the-release-after-pre-releases)
* [After Running create-github-release](#after-running-create-github-release)
* [How the changelog is updated](#how-the-changelog-is-updated)
* [Limitations](#limitations)
* [Development](#development)
* [Contributing](#contributing)
* [License](#license)
* [FAQ](#faq)
* [What if I want to reverse the changes made by this script?](#what-if-i-want-to-reverse-the-changes-made-by-this-script)
* [How is the changelog updated?](#how-is-the-changelog-updated)
* [Development](#development)
* [Contributing](#contributing)
* [License](#license)

## Installation

Add `create_github_release` as a development dependency in your project's gemspec:

```ruby
spec.add_development_dependency 'create_github_release', '~> 0.1'
spec.add_development_dependency 'create_github_release'
```

and then install using `bundle update`.
Expand All @@ -45,16 +57,18 @@ This gem installs the `create-guthub-release` command line tool:
Usage:
create-github-release --help | RELEASE_TYPE [options]
RELEASE_TYPE must be 'major', 'minor', 'patch', or 'first'
RELEASE_TYPE must be 'major', 'minor', 'patch', 'pre', 'release', or 'first'
Options:
--default-branch=BRANCH_NAME Override the default branch
--release-branch=BRANCH_NAME Override the release branch to create
-p, --pre Create a pre-release
-t, --pre-type=TYPE Type of pre-release to create (e.g. alpha, beta, etc.)
--remote=REMOTE_NAME Use this remote name instead of 'origin'
--last-release-version=VERSION
Use this version instead `semverify current`
--next-release-version=VERSION
Use this version instead `semverify RELEASE_TYPE`
Use this version instead `semverify next-RELEASE_TYPE`
--changelog-path=PATH Use this file instead of CHANGELOG.md
-q, --[no-]quiet Do not show output
-v, --[no-]verbose Show extra output
Expand Down Expand Up @@ -195,7 +209,85 @@ The `create-github-release` script will do the following:
See [After running create-github-release](#after-running-create-github-release)
for instructions for completing your release.

## After Running create-github-release
### Pre-release versions

This gem allows creation of a release with a pre-release version as [defined in the
Semver 2.0.0 spec](https://semver.org/#spec-item-9). An example of a pre-release
version is `1.0.0-beta.1`.

Pre-release versions have a lower precedence than their associated normal version.
This means the pre-release version sorts before the associated release version. For
example, `1.0.0-beta.1` comes before `1.0.0`. A pre-release version indicates that
the version is unstable and might not yet satisfy the intended compatibility
requirements as denoted by its associated normal version

This gem limits pre-release versions to the form `MAJOR.MINOR.PATCH-PRERELEASE` where
`PRERELEASE` can ONLY have the following form: `TYPE.DIGITS`. `TYPE` is any text
string allowed in the Semver 2.0.0 spec and is typically 'alpha', 'beta', 'pre',
'rc', etc. `DIGITS` is a numeric identifier that does not include leading zeroes.

#### Creating the first pre-release version for a release

Let's say that:
* The current release version is `1.3.4`
* You want to create the first pre-release for the next MINOR release
* You want the pre-release TYPE to be 'alpha'

You would use the following command:

```shell
create-github-release minor --pre --pre-type=alpha
```

This would create a release whose version is `1.4.0-alpha.1`.

#### Creating subsequent pre-releases

Let's say you would like to create another alpha pre-release for the `1.4.0` release.

You would use the following command:

```shell
create-github-release pre
```

This woould increment the pre-release numeric identifier giving the version is `1.4.0-alpha.2`.

It is only valid to use the `pre` command when the current release is a pre-release
version. For example, it would not be valid to run `create-github-release pre` if the
current version is `1.0.0`.

#### Changing the pre-release type

Continuing with the previous example where the current release version is
`1.4.0-alpha.2`, if you now you want to create a beta pre-release, you would use the
following command:

```shell
create-github-release pre --pre-type=beta
```

This would change the release type and reset the pre-release numeric identifier to
'1' resulting in the verion `1.4.0-beta.1`

Note that the current release type MUST be lexically less than the new release type
specified on the command line. This means that if the current version is
`1.4.0-beta.1`, it would not be valid to change the release type to `alpha` since
'alpha' <= 'beta'.

#### Creating the release after pre-releases

Now let's say that the current version is `1.4.0-beta.1`. To create release whose version
is `1.4.0`, use the command:

```shell
create-github-release release
```

It is only valid to use the `release` command when the current release version is a
pre-release version.

### After Running create-github-release

If you want to make additional updates to the ChangeLog or make changes as
part of the release PR, it is best to do them before running this script. If
Expand All @@ -216,15 +308,47 @@ git push
```

GitHub will automatically close the PR after the `git push` command. These commands
are output by `create-github-release` so you do not have to memorize them ;)
are output by `create-github-release` so you do not have to memorize them.

It is important to use a fast foward marge to ensure that the release tag points
to the right commit after the merge. GitHub does not allow fast forward merges when
merging a PR.
It is important to use a fast foward merge to ensure that the release tag points to
the right commit after the merge. The GitHub UI does not allow fast forward merges
when merging a PR.

Finally, publish your gem to rubygems.org with the `rake release` command.
Finally, publish your gem to rubygems.org with the command:

## How the changelog is updated
```shell
rake release:rubygem_push
```

## FAQ

### What if I want to reverse the changes made by this script?

You will need to delete the Git tag and branch created by this script both remotely and locally.

In your worktree run the following commands:

```shell
DEFAULT_BRANCH=main
RELEASE_VERSION=1.0.1
RELEASE_TAG="v${RELEASE_VERSION}"
RELEASE_BRANCH="release_${RELEASE_TAG}"
REMOTE=origin

# Make sure the release branch is not checked out
git checkout "${DEFAULT_BRANCH}"

# Delete remote branch and tag
# Deleting the remote branch will automatically close the release PR
git push "${REMOTE}" --delete "${RELEASE_BRANCH}"
git push "${REMOTE}" --delete "${RELEASE_TAG}"

# Delete the local branch and tag
git branch -D "${RELEASE_BRANCH}"
git tag -D "${RELEASE_TAG}"
```

### How is the changelog updated?

A release description is generated by listing the commits between the last release
and the next release.
Expand Down Expand Up @@ -266,24 +390,18 @@ The resulting updated changelog file has the following sections:
2. next release description
3. body (including past release descriptions)

## Limitations

* Does not work on Windows
* Has only been tested on MRI Ruby
*

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run
`rake spec` to run the tests. You can also run `bin/console` for an interactive
prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`.
To install this gem onto your current Ruby environment, run `bundle exec rake install`.

## Contributing

Bug reports and pull requests are welcome on
[this project's GitHub issue tracker](https://github.com/main-branch/create_github_release)
[this project's GitHub page](https://github.com/main-branch/create_github_release)

## License

Expand Down
12 changes: 6 additions & 6 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# The default task

desc 'Run the same tasks that the CI build will run'
task default: %w[spec rubocop yard yard:audit yard:coverage solargraph:typecheck bundle:audit build]
task default: %w[spec rubocop yard yard:audit yard:coverage bundle:audit build]

# Bundler Audit

Expand Down Expand Up @@ -75,12 +75,12 @@ Yardstick::Rake::Verify.new(:'yard:coverage') do |verify|
verify.threshold = 100
end

# Solargraph typecheck
# # Solargraph typecheck

desc 'Run the solargraph type checker'
task :'solargraph:typecheck' do
sh 'bundle exec solargraph typecheck --level=typed'
end
# desc 'Run the solargraph type checker'
# task :'solargraph:typecheck' do
# sh 'bundle exec solargraph typecheck --level=typed'
# end

# Additional cleanup

Expand Down
6 changes: 3 additions & 3 deletions create_github_release.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ Gem::Specification.new do |spec|

spec.metadata['homepage_uri'] = spec.homepage
spec.metadata['source_code_uri'] = spec.homepage
spec.metadata['changelog_uri'] = spec.homepage
spec.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}/file/CHANGELOG.md"
spec.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{spec.name}/#{spec.version}"

# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
Expand All @@ -42,10 +43,9 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'redcarpet', '~> 3.5'
spec.add_development_dependency 'rspec', '~> 3.10'
spec.add_development_dependency 'rubocop', '~> 1.36'
spec.add_development_dependency 'ruby-debug-ide', '~> 0.7'
spec.add_development_dependency 'simplecov', '~> 0.21'
spec.add_development_dependency 'simplecov-lcov', '~> 0.8'
spec.add_development_dependency 'solargraph', '~> 0.49'
# spec.add_development_dependency 'solargraph', '~> 0.49'
spec.add_development_dependency 'timecop', '~> 0.9'
spec.add_development_dependency 'yard', '~> 0.9'
spec.add_development_dependency 'yardstick', '~> 0.9'
Expand Down
2 changes: 1 addition & 1 deletion exe/create-github-release
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

require 'create_github_release'

options = CreateGithubRelease::CommandLineParser.new.parse(*ARGV)
options = CreateGithubRelease::CommandLine::Parser.new.parse(*ARGV)
pp options if options.verbose

project = CreateGithubRelease::Project.new(options)
Expand Down
3 changes: 1 addition & 2 deletions lib/create_github_release.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# frozen_string_literal: true

require 'create_github_release/backtick_debug'
require 'create_github_release/command_line_options'
require 'create_github_release/command_line_parser'
require 'create_github_release/command_line'
require 'create_github_release/project'

require 'create_github_release/change'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class BundleIsUpToDate < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::BundleIsUpToDate.new(project)
# begin
Expand Down
2 changes: 1 addition & 1 deletion lib/create_github_release/assertions/gh_authenticated.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GhAuthenticated < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::GhAuthenticated.new(project)
# begin
Expand Down
2 changes: 1 addition & 1 deletion lib/create_github_release/assertions/gh_command_exists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GhCommandExists < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::GhCommandExists.new(project)
# begin
Expand Down
2 changes: 1 addition & 1 deletion lib/create_github_release/assertions/git_command_exists.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GitCommandExists < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::GitCommandExists.new(project)
# begin
Expand Down
2 changes: 1 addition & 1 deletion lib/create_github_release/assertions/in_git_repo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class InGitRepo < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::InGitRepo.new(project)
# begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class InRepoRootDirectory < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::InRepoRootDirectory.new(project)
# begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class LocalAndRemoteOnSameCommit < AssertionBase
# @example
# require 'create_github_release'
#
# options = CreateGithubRelease::CommandLineOptions.new { |o| o.release_type = 'major' }
# options = CreateGithubRelease::CommandLine::Options.new { |o| o.release_type = 'major' }
# project = CreateGithubRelease::Project.new(options)
# assertion = CreateGithubRelease::Assertions::LocalAndRemoteOnSameCommit.new(project)
# begin
Expand Down
Loading

0 comments on commit 80da449

Please sign in to comment.