Skip to content

Instantly share code, notes, and snippets.

@pat
Last active December 17, 2021 09:45
Show Gist options
  • Select an option

  • Save pat/a1e8c1b3616cd3ef4a27963e164a27fc to your computer and use it in GitHub Desktop.

Select an option

Save pat/a1e8c1b3616cd3ef4a27963e164a27fc to your computer and use it in GitHub Desktop.

Revisions

  1. pat revised this gist Feb 21, 2021. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -25,6 +25,12 @@ $ heroku config:set \
    BUNDLE_BUILD__MYSQL2=--with-mysql-config
    ```

    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build, you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.
    * Update your app to use the `heroku-20` stack if you haven't already:

    If anyone has any questions or thoughts about this,[do let me know](https://twitter.com/pat).
    ```
    $ heroku stack:set heroku-20
    ```

    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build (for example, if you had already changed the stack and deployed other changes), you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.

    If anyone has any questions or thoughts about this, [do let me know](https://twitter.com/pat).
  2. pat revised this gist Feb 21, 2021. 1 changed file with 3 additions and 5 deletions.
    8 changes: 3 additions & 5 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,8 @@
    **Edit 2021-02-14**: I've found a solution that works well on heroku-18, but not (yet) on heroku-20. Still, that's two years further to figure this out, now that I'm not tied to heroku-16 any more.
    **Edit 2021-02-21**: I've confirmed this solution works with both heroku-18 and heroku-20 stacks.

    ---

    What follows is my solution for having `mysql2` gem compiled and working against MySQL v5.7 (rather than v8+) on the `heroku-18` stack. It does not yet work on `heroku-20` (which is built on Ubuntu 20.04), and I'm yet to figure out why. But `heroku-18` should be around for another two years, so that's a good step forward.

    This is how I've managed to make it work:
    What follows is my solution for having `mysql2` gem compiled and working against MySQL v5.7 (rather than v8+) on the `heroku-20` stack. This is how I've managed to make it work:

    * Add the apt buildstack ahead of your standard buildpack (in my case, that's Ruby):

    @@ -29,4 +27,4 @@ $ heroku config:set \

    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build, you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.

    If anyone is able to get this working on `heroku-20` as well (I'm finding it compiles fine, but still can't talk to MySQL 5.7 servers), [let me know](https://twitter.com/pat).
    If anyone has any questions or thoughts about this,[do let me know](https://twitter.com/pat).
  3. pat revised this gist Feb 14, 2021. 1 changed file with 8 additions and 43 deletions.
    51 changes: 8 additions & 43 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    **Edit**: Actually, as it currently stands, this approach is now not working for me. I'm still hunting for a way through (see comments below). Any suggestions welcome!
    **Edit 2021-02-14**: I've found a solution that works well on heroku-18, but not (yet) on heroku-20. Still, that's two years further to figure this out, now that I'm not tied to heroku-16 any more.

    ---

    Heroku's recent heroku-20 stack is built on Ubuntu 20.04, and the MySQL packages in this release default to v8+. However, I have some apps that make use of Sphinx v2.2.11, which only interacts with MySQL <= 5.7 - so, I need the `mysql2` gem compiled against MySQL 5.7.
    What follows is my solution for having `mysql2` gem compiled and working against MySQL v5.7 (rather than v8+) on the `heroku-18` stack. It does not yet work on `heroku-20` (which is built on Ubuntu 20.04), and I'm yet to figure out why. But `heroku-18` should be around for another two years, so that's a good step forward.

    This is how I've managed to make it work:

    @@ -19,49 +19,14 @@ $ heroku buildpacks:add --index 1 heroku-community/apt
    https://cdn.mysql.com/Downloads/MySQL-5.7/libmysqlclient-dev_5.7.32-1ubuntu18.04_amd64.deb
    ```

    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build, you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.

    ---

    However - even with the same Ruby version and identical Aptfile, I found one of my apps would crash when loading rake tasks within the Heroku build process:
    * Ensure that the `mysql2` gem compiles using the Apt-provided library (via `BUNDLE_BUILD__MYSQL2`) and that, when the library loads, it knows how to find libstdc++ (via `LD_PRELOAD`). I've found that `LD_PRELOAD` isn't already set to anything in my apps - but **yours may be different**, so do check before running this command.

    ```
    ! Could not detect rake tasks
    remote: ! ensure you can run `$ bundle exec rake -P` against your app
    remote: ! and using the production group of your Gemfile.
    remote: ! rake aborted!
    remote: ! LoadError: /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.so: undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE - /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.so
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `block in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:299:in `load_dependency'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2.rb:36:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:74:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:74:in `block (2 levels) in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:69:in `each'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:69:in `block in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:58:in `each'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:58:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler.rb:174:in `require'
    remote: ! /tmp/build_9b0ce686/config/application.rb:21:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/Rakefile:7:in `require'
    remote: ! /tmp/build_9b0ce686/Rakefile:7:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/rake_module.rb:29:in `load'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/rake_module.rb:29:in `load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:703:in `raw_load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:104:in `block in load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:103:in `load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:82:in `block in run'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:80:in `run'
    remote: ! /tmp/build_9b0ce686/bin/rake:6:in `<main>'
    $ heroku config:set \
    LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 \
    BUNDLE_BUILD__MYSQL2=--with-mysql-config
    ```

    The gem compilies fine, mind you, it just seems to be an issue loading it within the build process. My workaround is to ensure the gem's not loaded by default by adding a `:require => false` to it in the Gemfile:

    ```
    gem "mysql2", "~> 0.5.3", :require => false
    ```
    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build, you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.

    ... and then, whenever I do need it in my app, I require it manually with `require "mysql2"`. Using the gem at this point is fine and doesn't raise an exception. I haven't yet figured out why (I've burnt too much time on it already) - if anyone does have ideas, [let me know](https://twitter.com/pat).
    If anyone is able to get this working on `heroku-20` as well (I'm finding it compiles fine, but still can't talk to MySQL 5.7 servers), [let me know](https://twitter.com/pat).
  4. pat revised this gist Jan 30, 2021. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    **Edit**: Actually, as it currently stands, this approach is now not working for me. I'm still hunting for a way through (see comments below). Any suggestions welcome!

    ---

    Heroku's recent heroku-20 stack is built on Ubuntu 20.04, and the MySQL packages in this release default to v8+. However, I have some apps that make use of Sphinx v2.2.11, which only interacts with MySQL <= 5.7 - so, I need the `mysql2` gem compiled against MySQL 5.7.

    This is how I've managed to make it work:
  5. pat revised this gist Dec 28, 2020. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -15,9 +15,7 @@ $ heroku buildpacks:add --index 1 heroku-community/apt
    https://cdn.mysql.com/Downloads/MySQL-5.7/libmysqlclient-dev_5.7.32-1ubuntu18.04_amd64.deb
    ```

    * Deploy this Aptfile to your app, and it _should_ work.

    If at any point you need to ensure the `mysql2` gem is recompiled, you'll need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying.
    * Deploy this Aptfile to your app, and it _should_ work. If the gems are cached from a previous build, you will need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying, to ensure the `mysql2` gem is recompiled.

    ---

  6. pat created this gist Dec 28, 2020.
    65 changes: 65 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    Heroku's recent heroku-20 stack is built on Ubuntu 20.04, and the MySQL packages in this release default to v8+. However, I have some apps that make use of Sphinx v2.2.11, which only interacts with MySQL <= 5.7 - so, I need the `mysql2` gem compiled against MySQL 5.7.

    This is how I've managed to make it work:

    * Add the apt buildstack ahead of your standard buildpack (in my case, that's Ruby):

    ```
    $ heroku buildpacks:add --index 1 heroku-community/apt
    ```

    * Create an `Aptfile` in the root of your project, and add the MySQL 5.7 client tools (as a URL for the deb file) to it:

    ```
    # in Aptfile:
    https://cdn.mysql.com/Downloads/MySQL-5.7/libmysqlclient-dev_5.7.32-1ubuntu18.04_amd64.deb
    ```

    * Deploy this Aptfile to your app, and it _should_ work.

    If at any point you need to ensure the `mysql2` gem is recompiled, you'll need to [clear your build cache](https://help.heroku.com/18PI5RSY/how-do-i-clear-the-build-cache) prior to deploying.

    ---

    However - even with the same Ruby version and identical Aptfile, I found one of my apps would crash when loading rake tasks within the Heroku build process:

    ```
    ! Could not detect rake tasks
    remote: ! ensure you can run `$ bundle exec rake -P` against your app
    remote: ! and using the production group of your Gemfile.
    remote: ! rake aborted!
    remote: ! LoadError: /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.so: undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE - /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.so
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `block in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:299:in `load_dependency'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/activesupport-6.1.0/lib/active_support/dependencies.rb:332:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/mysql2-0.5.3/lib/mysql2.rb:36:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:74:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:74:in `block (2 levels) in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:69:in `each'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:69:in `block in require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:58:in `each'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler/runtime.rb:58:in `require'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/bundler-2.1.4/lib/bundler.rb:174:in `require'
    remote: ! /tmp/build_9b0ce686/config/application.rb:21:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/Rakefile:7:in `require'
    remote: ! /tmp/build_9b0ce686/Rakefile:7:in `<top (required)>'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/rake_module.rb:29:in `load'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/rake_module.rb:29:in `load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:703:in `raw_load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:104:in `block in load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:103:in `load_rakefile'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:82:in `block in run'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:186:in `standard_exception_handling'
    remote: ! /tmp/build_9b0ce686/vendor/bundle/ruby/2.7.0/gems/rake-13.0.1/lib/rake/application.rb:80:in `run'
    remote: ! /tmp/build_9b0ce686/bin/rake:6:in `<main>'
    ```

    The gem compilies fine, mind you, it just seems to be an issue loading it within the build process. My workaround is to ensure the gem's not loaded by default by adding a `:require => false` to it in the Gemfile:

    ```
    gem "mysql2", "~> 0.5.3", :require => false
    ```

    ... and then, whenever I do need it in my app, I require it manually with `require "mysql2"`. Using the gem at this point is fine and doesn't raise an exception. I haven't yet figured out why (I've burnt too much time on it already) - if anyone does have ideas, [let me know](https://twitter.com/pat).