DEV Community 👩‍💻👨‍💻

Cover image for Release Please for Ruby | GitHub Actions
A.J. Romaniello
A.J. Romaniello

Posted on • Updated on

Release Please for Ruby | GitHub Actions

release-please

release-please is a project maintained by the GoogleApi's team which automatically keeps a coherent changelog of your application as it grows as well as deploying your project with a new version tag.

Why Use release-please

  • Automatically generating CHANGELOGs.
  • Automatically determining a semantic version bump (based on the types of commits landed).
  • Communicating the nature of changes to teammates, the public, and other stakeholders.
  • Triggering build and publish processes.
  • Making it easier for people to contribute to your projects, by allowing them to explore a more structured commit history.

Source: conventionalcommits.org

This project not only keeps your changelog up to date by parsing your git commit history, but ensures that updates follow a common commit message convention.

release-please abides to the Conventional Commit Messages, which allows commits to be read by human and machine in a cohesive fashion.

Conventional Commits

Source: conventionalcommits.org

This aims to create a convention for committing to repositories, some of the most important keywords are:

fix:

A commit of the type fix patches a bug in your codebase (this correlates with PATCH in Semantic Versioning).

$ git commit -m "fix(<category>): my new fix"
Enter fullscreen mode Exit fullscreen mode

feat:

A commit of the type feat introduces a new feature to the codebase (this correlates with MINOR in Semantic Versioning).

$ git commit -m "feat(<category>): my new feature"
Enter fullscreen mode Exit fullscreen mode

BREAKING CHANGE

A commit that has a footer BREAKING CHANGE:, or appends a ! after the type/scope, introduces a breaking API change (correlating with MAJOR in Semantic Versioning). A BREAKING CHANGE can be part of commits of any type.

# Breaking Fix
$ git commit -m "fix!(<category>): my breaking fix"

# Breaking Feat
$ git commit -m "feat!(<category>): my breaking feature"
Enter fullscreen mode Exit fullscreen mode

Extra

Types other than fix: and feat: are allowed, for example (based on the the Angular Convention) recommends:

  • build:
  • chore:
  • ci:
  • docs:
  • style:
  • refactor:
  • perf:
  • test:
  • and more.

GitHub Action Setup

Creating the Workflow

To get started using release-please, we must create a new .yml file in our .github/workflows directory of our repository.

We can call this file release.yml.

After creating our file, we can go ahead and name our new workflow.

# /.github/workflows/release.yml

# The name of the Workflow.
name: release-please
Enter fullscreen mode Exit fullscreen mode

Choosing When to Run the Action

Since this project handles version releases and changelog updates, we only want this to run when pushes are made to our main or 'production' branch.

This ensures that this does not run on subsequent commits/pull requests to our repository.

The setup would look something like:

# /.github/workflows/release.yml

name: release-please

# When to run this action.
on:
  # Run on push to our 'main' branch.
  push:
    branches: [ main ]
Enter fullscreen mode Exit fullscreen mode

Setting Up release-please-action

Now that we have our workflow set up to run on pushes to our main branch, we can configure release-please to our liking.

release-please requires a personal access token to be able to create pull-requests and modify the changelog in your repository.

Once you have generated your personal access token, add it as a repository secret.

The secret can be named whatever you like, although must meet a few criteria.

For this example, lets call this secret: GH_TOKEN.

The default configuration would look something like:

# /.github/workflows/release.yml

name: release-please

on:
  push:
    branches: [ master ]

jobs:
  release-please:
    runs-on: ubuntu-latest
    env:
      # The name of your gem/package.
      GEM_NAME: "GEM NAME HERE"

    steps:
      # Use release-please-action.
      - uses: GoogleCloudPlatform/release-please-action@v2

        # Assign an 'id' to this action
        id: release
        with:
          # Personal Access Token
          token: ${{ secrets.GH_TOKEN }}

          # Use release-please/strategies/ruby.ts Release Type
          release-type: ruby

          # The name of the gem.
          package-name: ${{ env.GEM_NAME }}

          # Location of the version.rb file to bump for new releases
          version-file: "lib/${{ env.GEM_NAME }}/version.rb"
Enter fullscreen mode Exit fullscreen mode

Checkout and Publish

If a release is found, we want to:

  1. Checkout the repository.
  2. Build the ruby gem.
  3. Publish the gem to rubygems.org.

Checkout Repository

To checkout our repository, we can simply use the actions/checkout GitHub action.

# /.github/workflows/release.yml

name: release-please

on:
  push:
    branches: [ master ]

jobs:
  release-please:
    runs-on: ubuntu-latest
    env:
      GEM_NAME: "GEM NAME HERE"
    steps:
      - uses: GoogleCloudPlatform/release-please-action@v2
        id: release
        with:
          token: ${{ secrets.GH_TOKEN }}
          release-type: ruby
          package-name: ${{ env.GEM_NAME }}
          version-file: "lib/${{ env.GEM_NAME }}/version.rb"

      # Checkout the Repository if a release has been created.  
      - uses: actions/checkout@v2
        if: ${{ steps.release.outputs.release_created }}
Enter fullscreen mode Exit fullscreen mode

Setting Up Ruby

To be able to build our ruby gem, we first must install ruby onto our machine. We can achieve this by using the ruby/setup-ruby GitHub Action.

# /.github/workflows/release.yml

name: release-please

on:
  push:
    branches: [ master ]

jobs:
  release-please:
    runs-on: ubuntu-latest
    env:
      GEM_NAME: "GEM NAME HERE"
    steps:
      - uses: GoogleCloudPlatform/release-please-action@v2
        id: release
        with:
          token: ${{ secrets.GH_TOKEN }}
          release-type: ruby
          package-name: ${{ env.GEM_NAME }}
          version-file: "lib/${{ env.GEM_NAME }}/version.rb"
        env:
          GEM_NAME: "GEM NAME HERE"
      - uses: actions/checkout@v2
        if: ${{ steps.release.outputs.release_created }}

      # Set up Ruby if a release can be created.
      - uses: ruby/setup-ruby@v1
        with:
          # Latest ruby version (remove to use .ruby-version).
          ruby-version: 3.0

        if: ${{ steps.release.outputs.release_created }}
Enter fullscreen mode Exit fullscreen mode

Publish Gem

First to be able to push a new version, we must allow access via rubygems.org.

To create a new API key, head to rubygems.org.

Next, create a new repository secret.

This can be named anything, although must be referenced correctly within the workflow file.

For this example, we will call this secret: RUBYGEMS_API_KEY

To publish our gem, we have a couple of tasks to complete.

Since our action will run in a new container every time it is called, we must create a ~/.gem/credentials file containing an API Key from the account we would like to post on for rubygems.org.

Manual installation of Bundler is required. Since we are releasing our gem from the repository it must be built and have packages updated on push. The default 'bundler-cache' will break this.

  1. Install the bundler gem.
  2. Unset the BUNDLE_DEPLOYMENT variable.
  3. Run bundle install
  4. Create ~/.gem/credentials.
  5. Add our RUBYGEMS_API_KEY.
  6. Build our gem from the *.gemspec file.
  7. Push the *.gem to the remote server.

We can simply run these commands from within our workflow:

$ gem install bundler
$ bundle config unset deployment
$ bundle install
$ mkdir -p $HOME/.gem
$ touch $HOME/.gem/credentials
$ chmod 0600 $HOME/.gem/credentials
$ printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
$ gem build *.gemspec
$ gem push *.gem
Enter fullscreen mode Exit fullscreen mode

The end result would look like:

# /.github/workflows/release.yml

name: release-please

on:
  push:
    branches: [ master ]

jobs:
  release-please:
    runs-on: ubuntu-latest
    env:
      GEM_NAME: "GEM NAME HERE"

      # Our Ruby Gems API key
      RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}

    steps:
      - uses: GoogleCloudPlatform/release-please-action@v2
        id: release
        with:
          token: ${{ secrets.GH_TOKEN }}
          release-type: ruby
          package-name: ${{ env.GEM_NAME }}
          version-file: "lib/${{ env.GEM_NAME }}/version.rb"
      - uses: actions/checkout@v2
        if: ${{ steps.release.outputs.release_created }}
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.0
        if: ${{ steps.release.outputs.release_created }}

      # Release the gem to https://rubygems.org if a release has been created.
      - name: Release Gem
        run: |
          gem install bundler
          bundle config unset deployment
          bundle install
          mkdir -p $HOME/.gem
          touch $HOME/.gem/credentials
          chmod 0600 $HOME/.gem/credentials
          printf -- "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}\n" > $HOME/.gem/credentials
          gem build *.gemspec
          gem push *.gem
        if: ${{ steps.release.outputs.release_created }}
Enter fullscreen mode Exit fullscreen mode

Creating Your First Release

release-please will create a new pull-request automatically bumping the version of your project.

This will parse your projects git commit history to group together changes in a comprehensive fashion.

Adding Some Changes

Some keywords like ci: will not be build a new release, as these do not change your application.

Only keywords such as: fix:, feat:, or any <type>!: (Breaking Change), will trigger a new release to be created.

Changes will be grouped together, thus adding multiple commits of fix:, feat:, etc would be grouped into the same version release until the release pull request is merged into the main branch.

To generate a new changelog whenever we can force run our release-please action:

  1. Navigate to your repository on GitHub.
  2. Click on the Actions tab.
  3. Select: All Workflows > release-please > Run workflow.

To generate a new release and changelog, we could:

  • Add a new empty commit with a release tag.
$ git commit --allow-empty -m "chore: release 1.0.0" -m "Release-As: 1.0.0" 
Enter fullscreen mode Exit fullscreen mode

OR

  • Start adding commits using conventional commit messages.
$ git add .
$ git commit -m "feat: my new feature"
$ git push
Enter fullscreen mode Exit fullscreen mode

Every time feat: or fix: is in the commit message, release-please will re-parse your git commit history, create a new pull-request with the bumped version and an up-to-date changelog.

Conclusion

release-please adds convention to GitHub commits to allow changelogs and releases to be created without someone having to manually do so, as well as maintaining a specific committing convention.

Our final release.yml file may look like:

Top comments (0)

DEV

Thank you.

 
Thanks for visiting DEV, we’ve worked really hard to cultivate this great community and would love to have you join us. If you’d like to create an account, you can sign up here.