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.