Bash alias to switch between recent branches

If you have fzf installed, you may add an alias such as this to your ~/.bashrc:

alias recent-branch="git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads/ |  fzf | sed 's/\* //g' | xargs -I '{}' git checkout {}"
alias rb=recent-branch

Now whenever you want to switch back and forth between your most recent branches, type recent-branch, select one and press enter.

Upgrading Rails 2 from 2.3.8 through 2.3.18 to Rails LTS

This card shows how to upgrade a Rails 2 application from Rails 2.3.8 through every single patch level up to 2.3.18, and then, hopefully, Rails LTS.

2.3.8 to 2.3.9

This release has many minor changes and fixes to prepare your application for Rails 3.

Step-by-step upgrade instructions:

  1. Upgrade rails gem
  2. Change your environment.rb so it says RAILS_GEM_VERSION = '2.3.9'
  3. Change your ...

Updating a gem created with Bundler

Since May 2011 we are cutting new gems using Bundler, which is less painful than cutting gems using Jeweler. You know a gem was cut using Bundler if you see the word Bundler in a gem project's Rakefile.

This is how to update a gem that was cut using Bundler:

  • Say git pull or check out a repository from Github like git clone git@github.com:makandra/geordi.git
  • Update the gem version in `lib/project...

Rails: How to restore a postgres dump from the past

It sometimes happen that a database dump, that would want to insert into your development database, does not match the current schema of the database. This often happens when you have an old dump, but your current setup is up to date with the the master.

Hint: In most cases it is sufficient to delete and recreate the local database in order to import the dump. If any problems occur, proceed as follows:

1. Figure out the original migration status of the dumpfile

  • Convert your dump to plaintext: `pg_restore -f some.dump > some.dump....

Bundler 2.3 honors the version specified in `BUNDLED_WITH`

Bundler so far ignored the version specified under BUNDLED_WITH in the Gemfile.lock. This had two annoying consequences:

  • If the bundler version on your system was lower than in the Gemfile.lock, you got an error message and had to manually install the correct version.
  • If the bundler version on your system was higher than in the Gemfile.lock, bundler silently updated the version in the Gemfile.lock to your system's bundler version. To avoid this, you had to always specify, which version you want to use for each bundler c...

Fix for mysql2 error "Incorrect MySQL client library version! This gem was compiled for x.x.x but the client library is y.y.y."

This should be fixed in the latest LTS-branches of our mysql2 fork, 0.2.x-lts and 0.3.x-lts.

Use

gem 'mysql2', git: 'https://github.com/makandra/mysql2', branch: '0.2.x-lts' # for Rails 2.x
gem 'mysql2', git: 'https://github.com/makandra/mysql2', branch: '0.3.x-lts' # for Rails 3.x

in your Gemfile, and do a

bundle update mysql2

Background

mysql2 used to check that the client library used at runtime actually matches the one it was compiled against. However, at least on Ubunt...

Run all RSpec tests edited or added in the current branch

With this command you can run all the spec files which have been edited or added in the current branch since master:

git diff --name-only master -- ./spec | xargs -I{} rspec {} 
  • If you have several spec folders add them for path parameter after ./spec accordingly.
  • The option -I{} creates a placeholder to be replaced.
  • You can also compare edited/added specs between commits with <commit>..<commit>

Manage your AWS credentials for multiple accounts

Create a directory mkdir ~/.aws

Initialise git repository cd ~/.aws && git init

Create a git branch with a name you want (e.g. development for the aws development account credentials).

Add AWS credential file .aws_credentials:

AWSAccessKeyId=ABCDEFG1234
AWSSecretKey=4321GFEDCBA

Also add your EC2 cert and private key file.
You can add other AWS account depending files like .fog or .guignol.yml too.

Create symlinks for some config files like .aws_credentials and .fog:

ln -s ~/.aws/.aws_credentials ~/.aws_cred...

Force GitHub Pull Requests to update the diff against its target branch

When you have a Pull Request on GitHub that includes commits from another Pull Request, you will still see them after the "child" PR has been merged. Unfortunately, GitHub won't automatically update the diff (or commit list).

Here is what worked for me:

  1. Check out the target branch
    1. git checkout my-target-branch
    2. Make sure you are up to date against origin (e.g. git fetch and git status). You should be 0 commits ahead or behind.
  2. Add and commit a file
    1. touch .please-update
    2. git add .please-update
    3. `gi...

Installing old versions of mysql2 on Ubuntu 20.04+

On some of our older projects, we use the mysql2 gem. Unfortunately, versions 0.2.x (required for Rails 2.3) and versions 0.3.x (required for Rails 3.2) can no longer be installed on Ubuntu 20.04. Trying this either leads to errors when compiling the native extension, or a segfaults when using it.

For Rails 4.2, mysql2 version 0.4.10 seems to work okay. If you still have issues, upgrade to 0.5.x, which should be compatible.

To install it, you have to switch the mysql2 gem to our fork. In your Gemfile, ...

Prefer using Dir.mktmpdir when dealing with temporary directories in Ruby

Ruby's standard library includes a class for creating temporary directories. Similar to Tempfile it creates a unique directory name.

Note:

  • You need to use a block or take care of the cleanup manually
  • You can create a prefix and suffix e.g. Dir.mktmpdir(['foo', 'bar']) => /tmp/foo20220912-14561-3g93n1bar
  • You can choose a different base directory than Dir.tmpdir e.g. `Dir.mktmpdir('foo', Rails.root.join('tmp')) => /home/user/rails_example/tmp/foo20220912-14...

Local deployment after pipeline succeeds

If you have a fully functional CI pipeline but no CD, you might find yourself frequently waiting for CI (with "merge after pipeline succeeds") just to perform the deployment.

The following command waits for the next commit that lands on the current branch (should be main or similar) and proceeds to deploy staging afterwards:

alias await-deployment='watch -g git pull && bundle exec cap staging deploy'

Note

Use at your own risk.
You could be deploying code from someone else that was pushed to the same branch in the meantime.

Speed up Capistrano deployments using a remote cached copy of repository

You can seriously speed up deployments with Capistrano when using a local git repository on the server you are deploying to.

Simply add

set :deploy_via, :remote_cache
set :copy_exclude, [ '.git' ]

to your config/deploy.rb and Capistrano will create a clone in shared/cached-copy. This will be updated using git pull when deploying which transfers less bytes and is usually much faster. If deploy_via is set to use default settings (being "export"), Capistrano will do a full clone of the repository from your git host otherwi...

Automatically build sprites with Lemonade

How it works

See the lemonade descriptions.

Unfortunately, the gem has a few problems:

  • it does not work with Sass2
  • it always generates all sprites when the sass file changes, which is too slow for big projects
  • it expects a folder structure quite different to our usual

All these problems are solved for us, in our own lemonade fork. This fork has since been merged to the original gem, maybe we can use t...

rbenv: How to update list of available Ruby versions on Linux

When you tell rbenv to install a Ruby it does not know about, you will get an error message.

$ rbenv install 2.1.2
ruby-build: definition not found: 2.1.2

You can list all available versions with `rbenv install --list'.

If the version you're looking for is not present, first try upgrading
ruby-build. If it's still missing, open a request on the ruby-build
issue tracker: https://github.com/sstephenson/ruby-build/issues

(Fun fact: Recent versions of ruby-build will give you a more helpful error message which...

Protip: Clone large projects multiple times

Large projects usually have large test suites that can run for a long time.
This can be annoying as running tests blocks you from picking up the next story -- but it doesn't have to be that way!

Simply clone your project's repo twice (or even more often).

When your work on a feature branch is done, simply push that branch and check it out on your 2nd copy to run tests there.
You can pick up a new story and work on that on your "main" project directory.

If you do it right, you will even be able to run tests in both your 2nd copy and your m...

Upgrading from Capistrano 2 to 3

Capistrano 3 is a major rework of the framework and requires several adjustments to your deploy configuration files. The biggest change is that they moved away from their custom DSL and use Rake instead. For connecting with and operating on the servers, they bring a new gem SSHKit which does the heavy lifting. It's SSHKit's DSL that is used anywhere inside the Rake tasks. See #Resources at the bottom for examples.

Step 1: Upgrade guide

For migration from 2 to 3, follow this tutorial: [Capistrano 3 Upgrade Guide](https://semaphorec...

How to revert features for deployment, merge back, and how to stay sane

Removing features and merging those changes back can be painful. Here is how it worked for me.\
tl;dr: Before merging back: reinstate reverted features in a temporary branch, then merge that branch.

Scenario

Consider your team has been working on several features in a branch, made many changes over time and thus several commits for each feature.\
Now your client wants you to deploy while there are still stories that were rejected previously and can't be deployed.
...

Capistrano + Rails: Tagging production deploys

Just like Ruby Gems tag their version releases to the corresponding Git commit, it can be helpful to track production deploys within the commit history. This task does the tagging for you.

Capistrano 3

# lib/capistrano/tasks/deploy.rb
namespace :deploy do
  ...

  desc 'Tag the deployed revision'
  task :tag_revision do
    date = Date.today.to_s

    puts `git tag deploy-#{date} #{fetch :current_revision}`
    puts `git push --tags origin`
  end

end
# config/deploy/production.rb
after 'deploy:finished', 'deploy:tag_revi...

Fix: esbuild assets are missing after capistrano deploy

Issue: You have an app using jsbundling-rails and esbuild. After deploy, the assets built by esbuild are missing in public/assets.

Solution: Add app/builds to your git repo (by adding a app/builds/.keep file).

Something in sprockets is caching paths and refuses to accept files in "unknown" locations.

Migrate gem tests from Travis CI to Github Actions with gemika

We currently test most of our gems on Travis CI, but want to migrate those tests to Github Actions. This is a step-by-step guide on how to do this.

Note that this guide requires the gem to use gemika.

  1. Go to a new "ci" branch:
    git checkout -b ci
    
  2. Update gemika to version >= 0.5.0 in all your Gemfiles.
  3. Have gemika generate a Github Actions workflow definition by running
    mkdir -p .github/workflows; bundle exec rake gemika:generate_github_actions_workflow > .github/workf...
    

Bash script to list commits by Pivotal Tracker ID

The main benefit of our convention to prefix commits by their corresponding Pivotal Tracker ID is that we can easily detect commits that belong to the same story. You can either do that manually or use the bash script below by copying it somewhere to your .bashrc.

# Usage: ptcommits 123456
function ptcommits {
  if test "$1"
  then
    local PTID=$(echo "$1" | grep "[0-9]*" -o) # Allow URLs
    git log --onel...

Hack of the day: One-liner to run all changed Cucumber features

Similar to our snippet that runs all Cucumber features matching a given string, the following will run all modified or new Cucumber features by looking at your git status:

git status --short | grep -v '^ D ' | grep '.feature' | sed 's/.. //' | tr '\n' ' ' | xargs geordi cucumber

If you want to know what each of the above commands does, see [explainshell](http://explainshell.com/explain?cmd=git+status+--short+%7C+grep+-v+%27%5E+D+%27+%7C+grep+%27.feature%27+%7C+sed+%27s%2F..+%2F%2F%27+%7C+tr+%27%5Cn%27+%27+%27+%7C...

MongoMapper for Rails 2 on Ruby 1.9

MongoMapper is a MongoDB adapter for Ruby. We've forked it so it works for Rails 2.3.x applications running on Ruby 1.9. [1]

makandra/mongomapper is based on the "official" rails2 branch [2] which contains commits that were added after 0.8.6 was released. Tests are fully passing on our fork for Ruby 1.8.7, REE, and Ruby 1.9.3.

To use it, add this to your Gemfile:

gem 'mongo_mapper', :git => 'git://github.com/makandra/mongomapper.git', :branch => 'rails2'

...