Github Actions - publishing and tagging ruby gems

I caught sight of a Github action which publishes and tags Ruby gems. It (hopefully) makes upgrading a little easier/more efficient. It’s one less thing maintainers need to worry about when managing a ruby gem.

We wanted the action to be triggered manually. It should publish to RubyGems.org (or another publishing source), and must also tag the default branch (which is usually master) with the version associated with that Gem.

We manually extracted the ruby version from the relevant file, and then created a tag out of that. You can extract it from a javascript file too, which is probably easier.

Here is the solution which worked for us:

Ruby version extraction solution

name: manual-release

on: 
  workflow_dispatch:    

jobs:
  manual-release:
    runs-on: ubuntu-latest
    steps:
 
      - uses: actions/checkout@v2 # checks out default branch (usually master)
      
      - uses: ruby/setup-ruby@v1
        with:          
          ruby-version: 3.0.0      
      - run: bundle install
      

      - name: publish gem
        run: |
          mkdir -p $HOME/.gem
          touch $HOME/.gem/credentials
          chmod 0600 $HOME/.gem/credentials
          printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
          gem build *.gemspec
          gem push *.gem
        env:
          # Make sure to update the secret name
          # if yours isn't named RUBYGEMS_AUTH_TOKEN
          GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
 
      - name: Get version number
        id: version
        run: |          
          echo "::set-output name=version::$(sed -nr "s/.*VERSION\s*=\s*('|\")([^'\"]+).*$/\2/p" $(echo "$GITHUB_WORKSPACE/lib/pagy.rb"))"
  

      - name: Create tag
        uses: actions/github-script@v3
        with:
          github-token: ${{ github.token }}
          script: |
            github.git.createRef({
              owner: context.repo.owner,
              repo: context.repo.repo,
              ref: `refs/tags/${{steps.version.outputs.version}}`,
              sha: context.sha
            })

There may be better ways of doing this. Google in their release-please-action are somehow accessing the verion number in the relevant ruby file. I have not studied their implementation, but it is likely more efficient than the above approach.

Javascript version extraction solution

Or, if you wanted to extract the version number for a javascript file, here is a solution that could also work for you:



name: publish-gem-and-tag

on: 
  workflow_dispatch:    

jobs:
  publish-gem-and-tag:
    runs-on: ubuntu-latest

    steps:
 
      - uses: actions/checkout@v2  # checks out default branch
      
      - uses: ruby/setup-ruby@v1
        with:          
          ruby-version: 3.0.0      
      - run: bundle install      

      - name: publish gem
        run: |
          mkdir -p $HOME/.gem
          touch $HOME/.gem/credentials
          chmod 0600 $HOME/.gem/credentials
          printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
          gem build *.gemspec
          gem push *.gem
        env:          
          GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"

      - name: Create tag
        uses: actions/github-script@v3
        with:
          github-token: ${{ github.token }}
          script: |
            const fs = require("fs")
            eval(fs.readFileSync("./lib/javascripts/pagy.js").toString())
            
            github.git.createRef({
              owner: context.repo.owner,
              repo: context.repo.repo,
              ref: `refs/tags/${Pagy.version}`,
              sha: context.sha
            })

We needed to get access to the pagy.js. Because we didn’t want to add a default export to the pagy.js file, in order to ensure compatibility with as many browswers as possible, I was forced to eval the entire thing so it would work in a node environment. Your situation may be different. You would almost be variably better off exporting the relevant constant in your file.

Written on August 2, 2021