Using pg_partman with Rails and HerokuCI Using pg_partman with Rails and HerokuCI heroku heroku

Using pg_partman with Rails and HerokuCI


I worked around this by installing pg_partman as part of the db:structure:load_if_sql task when it detects its on HerokuCI with In-Dyno Postgres.

Rake::Task["db:structure:load_if_sql"].enhance [:install_pg_partman]private def heroku_ci?  ENV["CI"]endprivate def in_dyno_postgres?  File.exist?("/app/.indyno/vendor/postgresql")endprivate def install_pg_partman  system './bin/install-pg-partman'endtask :install_pg_partman do  # Heroku In-Dyno Postgres does not have pg_partman.  if heroku_ci? && in_dyno_postgres?    puts 'installing pg_partman'    install_pg_partman  endend

And bin/install-pg-partman.

#!/bin/bashREPO_URL=${REPO_URL='https://github.com/pgpartman/pg_partman.git'}BUILD_DIR=${BUILD_DIR=tmp}PG_CONFIG=${PG_CONFIG='/app/.indyno/vendor/postgresql/bin/pg_config'}if [ ! -f "$PG_CONFIG" ]; then  echo "Cannot find ${PG_CONFIG}"  exit 1;ficd tmprm -rf pg_partmangit clone ${REPO_URL}cd pg_partmanmake install PG_CONFIG=${PG_CONFIG} NO_BGW=1

With tests.

require 'rails_helper'RSpec.describe 'rake install_pg_partman' do  let(:task) { Rake::Task['install_pg_partman'] }  before do    # Otherwise if you call the same task twice it will think    # it's already been done and skip it or re-raise the same exception.    task.reenable  end  shared_context "with CI", temp_env: true do    before { ENV["CI"] = "true" }  end  shared_context "with in-dyno postgres" do    before {      allow(File).to receive(:exist?)        .with("/app/.indyno/vendor/postgresql")        .and_return(true)    }  end  shared_examples "it does not install" do    it 'does not install' do      expect(task).not_to receive(:install_pg_partman)      task.invoke    end  end  it 'is a prerequisite of db:structure:load_if_sql' do    expect(      Rake::Task["db:structure:load_if_sql"].prerequisite_tasks    ).to include(task)  end  context 'no CI, no in-dyno postgres' do    it_behaves_like 'it does not install'  end  context 'when in CI, but no in-dyno postgres' do    include_context "with CI"    it_behaves_like 'it does not install'  end  context 'with in-dyno postgres, but not in CI' do    include_context "with in-dyno postgres"    it_behaves_like 'it does not install'  end  context 'when in CI and with in-dyno postgres', temp_env: true do    include_context "with CI"    include_context "with in-dyno postgres"    let(:pg_config_path) { "/does/not/exist/pg_config" }    before {      ENV["PG_CONFIG"] = pg_config_path    }    it 'tries to install' do      expect(task.send(:heroku_ci?)).to be_truthy      expect(task.send(:in_dyno_postgres?)).to be_truthy      expect {        task.invoke      }.to output(/Cannot find #{pg_config_path}/).to_stdout_from_any_process    end  endend