Gem development: recommended gem metadata

The gemspec for gems allows to add metadata to your gem, some of which have a special meaning and are helpful for users.
You can provide links to your Github bugtracker or changelog file that are then used on the rubygems page of your gem (in the sidebar, e.g. see gem page of consul).

Here are some keys that should be filled:

Gem::Specification.new do |s|
  s.name = 'my-gem'
  s.homepage = 'https://github.com/makandra/my-gem'

  s.metadata = {
    'source_code_uri' => s.homepage,
    'bug_tracker...

How to get information about a gem (via CLI or at runtime from Ruby)

When you need information about a gem (like version(s) or install path(s)), you can use the gem binary from the command line, or the Gem API inside a ruby process at runtime.

gem binary (in a terminal)

You can get some information about a gem by running gem info <gem name> in your terminal.

Example:

$ gem info irb

*** LOCAL GEMS ***

irb (1.4.1, 1.3.5)
    Author: Keiju ISHITSUKA
    Homepage: https://github.com/ruby/irb
    Licenses: Ruby, BSD-2-Clause
    Installed at (1.4.1): /home/arne/.rbenv/versions/3.0.3/lib/ruby/g...

Integrating ESLint

Introduction

To ensure a consistent code style for JavaScript code, we use ESLint. The workflow is similar to integrating rubocop for Ruby code.

1. Adding the gem to an existing code base

You can add the following lines to your package.json under devDependencies:

  "devDependencies": {
    "eslint": "^8.7.0",
    "eslint-config-standard": "^16.0.3",
    "eslint-plugin-import": "^2.25.4",
    "eslint-plugin-node"...

esbuild: Make your Rails application show build errors

Building application assets with esbuild is the new way to do it, and it's great, especially in combination with Sprockets (or Propshaft on Rails 7).
You might be missing some convenience features, though.

Here we cover one specific issue:
Once you have started your development Rails server and esbuild with the --watch option (if you used jsbundling-rails to set up, you probably use bin/dev), esbuild will recompile your assets upon change, but build errors will only be printed to the terminal. Your application won't complain about them ...

Deployment: Merge consecutive commits without cherry-picking

You want to deploy new features but the latest commits are not ready for production? Then use git merge master~n to skip the n-last commits.

Tip

A big advantage of merging vs. cherry-picking is that cherry-picking will create copies of all picked commits. When you eventually do merge the branch after cherry-picking, you will have duplicate commit messages in your history.

Example

It's time for a production deployment!

git log --pretty=format:"%h - %s" --reverse origin/production..origin/master

0e6ab39f - Feature A
6396...

The TCF 2.0 (Tranparency and Consent Framework) standard, and what you should know about it

The Interactive Advertising Bureau (IAB) is a European marketing association which has introduced a standard how advertising can be served to users in line with the General Data Protection Regulation (GDPR). This standard is called the TCF 2.0 (Transparency and Consent Framework). If you want to integrate any kind of advertising into a website, chances are the advertising network will require your website to implement that standard. This is a very brief overview of what this means:

The basic idea in the TCF 2.0 ...

Git shortcut to rebase onto another branch

Inspired by recent "git shortcut" cards I figured it would be nice to have one of these for rebasing a few commits onto another branch. The usual notation is prone to of-by-one errors as you have to either specify the commit before the ones you want to move or count the number of commits.

You may add this rebase-onto function to your ~/.bashrc:

function rebase-onto {
  commit=$(git log --oneline | fzf --prompt 'Select the first commit y...

Git shortcut to fixup a recent commit

git --fixup is very handy to amend a change to a previous commit. You can then autosquash your commits with git rebase -i --autosquash and git will do the magic for you and bring them in the right order. However, as git --fixup wants a ref to another commit, it is quite annoying to use since you always have to look up the sha of the commit you want to amend first.

Inspired by the [shortcut to checkout recent branches with fzf](https://makandracards.com/makandra/505126-g...

RSpec matcher to compare two HTML fragments

The RSpec matcher tests if two HTML fragments are equivalent. Equivalency means:

  • Whitespace is ignored
  • Types of attribute quotes are irrelevant
  • Attribute order is irrelevant
  • Comments are ignored

You use it like this:

html = ...
expect(html).to match_html(<<~HTML)
  <p>
    Expected content
  </p>  
HTML

You may override options from CompareXML by passing keyword arguments after the HTML string:

html = ...
expect(html).to match_html(<<~HTML, ignore_text_nodes: true)
 ...

Bookmarklet to facilitate generating new git branches for PivotalTracker Stories

This bookmarklet grabs a PivotalTracker story title, transforms it into a valid git branch name and automatically prepends your initials and an optional abbreviation (for better tab completion). It will output the following formats:

If you cancel the first dialog or confirm it without entering text:

git checkout -b kw/178298638-card-320-state-machines

If you enter an abbreviation (e.g. stm in this case):

git checkout -b kw/stm/178298638-card-320-state-machines

How to set it up:

  • in the attached file replace `YOUR_INITI...

GitHub Actions: Manually running a workflow

To start a workflow manually it must have a trigger called workflow_dispatch:

---
name: Tests
on:
  push:
    branches:
    - master
  pull_request:
    branches:
    - master
  workflow_dispatch:
    branches:
    - master  

In the Actions tab of your repo you can now select a workflow and press "Run Workflow".

See GitHub documentation for details.

GitHub Actions: Retrying a failing step

If you have a flaky command you can use the nick-invision/retry to re-try a failing command, optionally with a timeout:

---
...
jobs:
  test:
    ...
    steps:
    - name: Run tests
      uses: nick-invision/retry@v2
      with:
        timeout_seconds: 30
        max_attempts: 3
        command: bundle exec rake spec

How to checkout submodules in Gitlab CI

Accessing other repositories in Gitlab CI is not straight forward, since the access rights of the current pipeline might not be sufficient enough.

One approach is to use project access tokens and clone the repositories via HTTPS.

  • Create a project access token for all submodules you want to have access to with the setting read_repository
  • Add the secrets as environment variable to the main project you want to have access to submodules:
    • Protected false ...

Geordi 6.0.0 released

6.0.0 2021-06-02

Compatible changes

  • geordi commit will continue even if one of the given projects is inaccessible. It will only fail if no stories could be found at all.

Breaking changes

How to: "git log" with renamed files

While renaming a file sometimes feels like "dropping its history", that is not true: Just use git log --follow on renamed files to access their full history.

Given a file "bar" that was previously named "foo":

touch foo
git add foo
git commit -m "Add foo"
mv foo bar
git add bar
git commit -m "Rename foo to bar"

git log bar

commit adc8e6a05b65355359c4e4618d6af0ed8f8b7f14 (HEAD -> git-follow)
Author: Michael Leimstaedtner <makmic@makandra.de>
Date:   Wed May 12 08:49:37 2021 +0200

    Rename foo to bar

git lo...

Carrierwave: How to remove container directories when deleting a record

When deleting a record in your Rails app, Carrierwave automatically takes care of removing all associated files.
However, the file's container directory will not be removed automatically. If you delete records regularly, this may be an annoyance.

Here is a solution which was adapted from the Carrierwave GitHub wiki and cleans up any empty parent directories it can find.

class ExampleUploader < CarrierWave...

Bundler: Packaging gems into the git repository (offline installation)

Installing gems on a server that has no access to the internet (especially rubygems.org) requires to bundle the gems into the repository itself. This requires to adjust the bundle config in the repository.

  1. Execute the following commands to configure bundler:
bundle config set --local path vendor
bundle config set --local disable_shared_gems true

Note

For Bundler < 2 you have to omit the "set": bundle config --local name value.
See here: [https://bundler.io/v1.17/man/bundle-config.1.html](https://bundler.io/v1.17/man...

How to push to Git without running CI on GitLab CI, GitHub Actions, or Travis CI

If a project ist configured to spawn CI runners for tests or deployment when pushing to the Repo, a habit of pushing WIP commits regularly may conflict with that.
Here are two solutions that allow you to keep pushing whenever you feel like it.

Special commit message

To skip a CI run, simply add [ci skip] or [skip ci] to your commit message. Example:

git commit -m "wip authentication [ci skip]"

Git push options (GitLab)

In addition to that, GitLab CI supports Git push options. Instead of changing your commit message, ...

Geordi 5.4.0 released

5.4.0 2021-02-01

Compatible changes

  • Add geordi branch command that checks out a feature branch based on a story from Pivotal Tracker
  • Faster MySQL dumping with --single-transaction and --quick
  • Allow pivotal tracker ids in the global config file
  • Fix missing require for Fileutils in the dump load command (#145)
  • Document PARALLEL_TEST_PROCESSORS

Webmock < 3.12.1 cannot handle IPv6 addresses correctly

We had the issue, that a VCR spec failed, after updating CarrierWave from version 0.11.0 to 1.3.2.
In this version, CarrierWave uses the gem SsrfFilter, which retrieves the IP addresses for the given hostname and replaces the hostname in the requested url with one of them.

It works with IPv4 addresses, but not with IPv6 addresses, because WebMock cannot handle those correctly:

uri = "#{protocol}://...

How to fix: WrongScopeError when using rspec_rails with Rails 6.1

tl;dr: Upgrade the gem to at least 4.0.1

When you use rspec_rails in a version < 4 with Rails 6.1 you may encounter an error like this:

Failure/Error:
  raise WrongScopeError,
    "`#{name}` is not available from within an example (e.g. an " \
    "`it` block) or from constructs that run in the scope of an " \
    "example (e.g. `before`, `let`, etc). It is only available " \
    "on an example group (e.g. a `describe` or `context` block)."
    `name` is not available from within an example (e.g. an `it` block) or from constructs that...