Repository: railwayapp/nixpacks
Pull request #310 (2022-07-13 23:53:46)

no-cache option also does not use the docker cache
When not building with a cache (`--no-cache` or `NIXPACKS_NO_CACHE=1`), do not use the buildkit cache mount **as well as the regular docker cache**.



Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..345b8a7
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,52 @@
+name: 🐛 Bug Report
+description: Create a bug report to help us improve Nixpacks
+title: "Nixpacks Bug Report"
+labels: ["bug"]
+body:
+  - type: checkboxes
+    id: issue-already-exists
+    attributes:
+      label: Is there an existing issue for this?
+      description: |
+        Please search to see if an issue already exists for the bug you encountered.
+        Please see [Searching Issues and Pull Requests](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests) for how to use the GitHub search bar and filters.
+      options:
+      - label: I have searched the existing issues
+        required: true
+  - type: textarea
+    id: describe-the-bugs
+    validations:
+      required: true
+    attributes:
+      label: Describe the bug
+      description: Please provide a clear and concise description about the problem you ran into.
+      placeholder: This happened when I...
+  - type: textarea
+    id: to-reproduce
+    validations:
+      required: false
+    attributes:
+      label: To reproduce
+      description: |
+        Please provide a code sample or a code snippet to reproduce the said problem. If you have code snippets, error messages or a stack trace please provide them here.
+      placeholder: |
+        Steps to reproduce the bug:
+
+          1. Provide '...'
+          2. Run '...'
+          3. See error
+  - type: textarea
+    id: expected-behavior
+    validations:
+      required: false
+    attributes:
+      label: Expected behavior
+      description: "A clear and concise description of what you would expect to happen."
+  - type: textarea
+    id: environment-info
+    attributes:
+      label: Environment
+      description: |
+        Please share your environment with us. (ie, OS, OS version and Nixpacks version)
+    validations:
+      required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..effec84
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,13 @@
+blank_issues_enabled: true
+version: 2.1
+contact_links:
+  - name: 📖 Nixpacks Documentation
+    url: https://nixpacks.com/
+    about: Documentation about Nixpacks
+  - name: 🚅 Railway
+    url: https://railway.app/
+    about: Railway homepage
+  - name: 💬 Railway Discord
+    url: https://discord.gg/railway
+    about: Contact the Railway team for support via Discord
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..ce7dd0c
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,32 @@
+name: 🚀 Feature Request
+description: Submit a proposal/request for new Nixpacks feature
+title: "Nixpacks Feature Request"
+body:
+- type: textarea
+  id: feature-request
+  validations:
+    required: true
+  attributes:
+    label: Feature request
+    description: |
+      A clear and concise description of the feature request.
+    placeholder: |
+      This could be implemented by...
+- type: textarea
+  id: motivation
+  validations:
+    required: false
+  attributes:
+    label: Motivation
+    description: |
+      Please outline the motivation for this feature request. Is your feature request related to a problem? e.g., I'm always frustrated when [...].
+      If this is related to another issue, please link here too.
+      If you have a current workaround, please also provide it here.
+    placeholder: |
+      This feature would solve ...
+- type: textarea
+  id: contribution
+  attributes:
+    label: Contribution
+    description: |
+      Is there any way that you could help, e.g. by submitting a PR? Please make sure to read the [contributing guidelines](https://github.com/railwayapp/nixpacks/blob/main/CONTRIBUTING.md).
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..038be79
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,16 @@
+## What does this PR address?
+<!-- Thanks for sending a pull request! -->
+
+<!-- Remove if not applicable -->
+Fixes # (issue)
+
+## Before submitting:
+<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
+<!--- If you're unsure about any of these, don't hesitate to ask -->
+<!--- If you plan to update documentation or tests in follow-up, please note -->
+
+- [ ] Make sure to follow [GitHub's guide](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) on creating PR.
+- [ ] Did you read through [contribution guidelines](https://github.com/railwayapp/nixpacks/blob/main/CONTRIBUTING.md)?
+- [ ] Did your changes require updates to the documentation? Have you updated those accordingly?
+- [ ] Did you write tests to cover your changes? Did it pass locally when running `cargo test`?
+- [ ] Have you run `cargo fmt`, `cargo check` and `cargo clippy` locally to ensure that CI passes?
diff --git a/Cargo.lock b/Cargo.lock
index 44064e2..cd96827 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -299,7 +299,7 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "nixpacks"
-version = "0.2.3"
+version = "0.2.5"
 dependencies = [
  "anyhow",
  "base64",
diff --git a/Cargo.toml b/Cargo.toml
index b3a294c..4bb3887 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "nixpacks"
-version = "0.2.3"
+version = "0.2.5"
 edition = "2021"
 license = "MIT"
 authors = ["Railway <contact@railway.app>"]
diff --git a/base/debian/Dockerfile b/base/debian/Dockerfile
index ba7140c..04a0d07 100644
--- a/base/debian/Dockerfile
+++ b/base/debian/Dockerfile
@@ -3,7 +3,7 @@ FROM debian:bullseye-20220622-slim
 ARG DEBIAN_FRONTEND=noninteractive
 
 RUN apt-get update && apt-get -y upgrade \
-  && apt-get install --no-install-recommends -y sudo locales curl xz-utils ca-certificates openssl make git \
+  && apt-get install --no-install-recommends -y sudo locales curl xz-utils ca-certificates openssl make git pkg-config \
   && apt-get clean && rm -rf /var/lib/apt/lists/* \
   && mkdir -m 0755 /nix && mkdir -m 0755 /etc/nix && groupadd -r nixbld && chown root /nix \
   && printf 'sandbox = false \nfilter-syscalls = false' > /etc/nix/nix.conf \
diff --git a/docs/components/TopNav.tsx b/docs/components/TopNav.tsx
index 7f15d49..87cd1fb 100644
--- a/docs/components/TopNav.tsx
+++ b/docs/components/TopNav.tsx
@@ -38,7 +38,7 @@ export const TopNav: React.FC<{
       <nav
         className={`flex items-center justify-between px-8 py-5 w-full max-w-[90rem] mx-auto`}
       >
-        <Link href="/" className="flex">
+        <Link href="/docs" className="flex">
           📦 Nixpacks
         </Link>
 
diff --git a/docs/next.config.js b/docs/next.config.js
index f3043b7..2fdadf1 100644
--- a/docs/next.config.js
+++ b/docs/next.config.js
@@ -7,6 +7,12 @@ module.exports =
     async redirects() {
       return [
         { source: "/", destination: "/docs/getting-started", permanent: false },
+        {
+          source: "/install.sh",
+          destination:
+            "https://raw.githubusercontent.com/railwayapp/nixpacks/main/install.sh",
+          permanent: true,
+        },
       ];
     },
   });
diff --git a/docs/pages/docs/install.md b/docs/pages/docs/install.md
index a2def71..c41d98f 100644
--- a/docs/pages/docs/install.md
+++ b/docs/pages/docs/install.md
@@ -17,7 +17,7 @@ brew install railwayapp/tap/nixpacks
 Download Nixpacks from GH releases and install automatically
 
 ```sh
-curl -fsSL https://raw.githubusercontent.com/railwayapp/nixpacks/master/install.sh | bash
+curl -sSL https://nixpacks.com/install.sh | bash
 ```
 
 ## Scoop
diff --git a/docs/pages/docs/providers/ruby.md b/docs/pages/docs/providers/ruby.md
index 2c7caf2..5c90b62 100644
--- a/docs/pages/docs/providers/ruby.md
+++ b/docs/pages/docs/providers/ruby.md
@@ -8,7 +8,7 @@ Ruby is detected if a `Gemfile` file is found.
 
 ## Setup
 
-The Ruby version is installed using [RVM](https://rvm.io/). The versions found in the `Gemfile` is installed.
+The Ruby version is installed using [RVM](https://rvm.io/). You can specify the version in a `.ruby-version` file or the versions found in the `Gemfile` is installed. You can also
 
 ## Install
 
diff --git a/examples/python-numpy/main.py b/examples/python-numpy/main.py
new file mode 100644
index 0000000..91cf460
--- /dev/null
+++ b/examples/python-numpy/main.py
@@ -0,0 +1,10 @@
+import numpy as np
+import pandas as pd
+
+print(np)
+print(pd)
+
+arr = np.random.rand(2, 3)
+print(arr)
+
+print("Hello from Python numpy and pandas")
diff --git a/examples/python-numpy/requirements.txt b/examples/python-numpy/requirements.txt
new file mode 100644
index 0000000..1341486
--- /dev/null
+++ b/examples/python-numpy/requirements.txt
@@ -0,0 +1,2 @@
+numpy==1.23.1
+pandas==1.4.3
diff --git a/examples/ruby-gemfile-lock/Gemfile.lock b/examples/ruby-gemfile-lock/Gemfile.lock
deleted file mode 100644
index 972ca7d..0000000
--- a/examples/ruby-gemfile-lock/Gemfile.lock
+++ /dev/null
@@ -1,28 +0,0 @@
-GEM
-  remote: https://rubygems.org/
-  specs:
-    mustermann (1.1.1)
-      ruby2_keywords (~> 0.0.1)
-    rack (2.2.3)
-    rack-protection (2.2.0)
-      rack
-    ruby2_keywords (0.0.5)
-    sinatra (2.2.0)
-      mustermann (~> 1.0)
-      rack (~> 2.2)
-      rack-protection (= 2.2.0)
-      tilt (~> 2.0)
-    tilt (2.0.10)
-
-PLATFORMS
-  x86_64-darwin-20
-  x86_64-linux
-
-DEPENDENCIES
-  sinatra
-
-RUBY VERSION
-   ruby 2.7.2p137
-
-BUNDLED WITH
-   2.2.8
diff --git a/examples/ruby-gemfile-lock/app.rb b/examples/ruby-gemfile-lock/app.rb
deleted file mode 100644
index c3a60ec..0000000
--- a/examples/ruby-gemfile-lock/app.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'sinatra'
-puts "Hello from Sinatra"
-get '/' do
-  'Choo Choo! Welcome to your Sinatra server 🚅'
-end
\ No newline at end of file
diff --git a/examples/ruby-gemfile-lock/config.ru b/examples/ruby-gemfile-lock/config.ru
deleted file mode 100644
index 0d7426a..0000000
--- a/examples/ruby-gemfile-lock/config.ru
+++ /dev/null
@@ -1,3 +0,0 @@
-
-require './app'
-run Sinatra::Application
\ No newline at end of file
diff --git a/examples/ruby-gemfile/Gemfile b/examples/ruby-gemfile/Gemfile
deleted file mode 100644
index 0011017..0000000
--- a/examples/ruby-gemfile/Gemfile
+++ /dev/null
@@ -1,6 +0,0 @@
-
-source 'https://rubygems.org'
-
-ruby "2.7.2"
-
-gem 'sinatra'
\ No newline at end of file
diff --git a/examples/ruby-gemfile/Procfile b/examples/ruby-gemfile/Procfile
deleted file mode 100644
index 82cb606..0000000
--- a/examples/ruby-gemfile/Procfile
+++ /dev/null
@@ -1,1 +0,0 @@
-web: ruby app.rb
\ No newline at end of file
diff --git a/examples/ruby-gemfile/app.rb b/examples/ruby-gemfile/app.rb
deleted file mode 100644
index c3a60ec..0000000
--- a/examples/ruby-gemfile/app.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'sinatra'
-puts "Hello from Sinatra"
-get '/' do
-  'Choo Choo! Welcome to your Sinatra server 🚅'
-end
\ No newline at end of file
diff --git a/examples/ruby-gemfile/config.ru b/examples/ruby-gemfile/config.ru
deleted file mode 100644
index 0d7426a..0000000
--- a/examples/ruby-gemfile/config.ru
+++ /dev/null
@@ -1,3 +0,0 @@
-
-require './app'
-run Sinatra::Application
\ No newline at end of file
diff --git a/examples/ruby-rails-postgres/.gitattributes b/examples/ruby-rails-postgres/.gitattributes
new file mode 100644
index 0000000..31eeee0
--- /dev/null
+++ b/examples/ruby-rails-postgres/.gitattributes
@@ -0,0 +1,7 @@
+# See https://git-scm.com/docs/gitattributes for more about git attribute files.
+
+# Mark the database schema as having been generated.
+db/schema.rb linguist-generated
+
+# Mark any vendored files as having been vendored.
+vendor/* linguist-vendored
diff --git a/examples/ruby-rails-postgres/.gitignore b/examples/ruby-rails-postgres/.gitignore
new file mode 100644
index 0000000..e16dc71
--- /dev/null
+++ b/examples/ruby-rails-postgres/.gitignore
@@ -0,0 +1,31 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+#   git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+# Ignore pidfiles, but keep the directory.
+/tmp/pids/*
+!/tmp/pids/
+!/tmp/pids/.keep
+
+# Ignore uploaded files in development.
+/storage/*
+!/storage/.keep
+/tmp/storage/*
+!/tmp/storage/
+!/tmp/storage/.keep
+
+/public/assets
+
+# Ignore master key for decrypting credentials and more.
+/config/master.key
diff --git a/examples/ruby-rails-postgres/.ruby-version b/examples/ruby-rails-postgres/.ruby-version
new file mode 100644
index 0000000..ef538c2
--- /dev/null
+++ b/examples/ruby-rails-postgres/.ruby-version
@@ -0,0 +1,1 @@
+3.1.2
diff --git a/examples/ruby-rails/Gemfile b/examples/ruby-rails-postgres/Gemfile
similarity index 93%
rename from examples/ruby-rails/Gemfile
rename to examples/ruby-rails-postgres/Gemfile
index 7096e07..2c54c88 100644
--- a/examples/ruby-rails/Gemfile
+++ b/examples/ruby-rails-postgres/Gemfile
@@ -1,16 +1,16 @@
 source "https://rubygems.org"
 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
 
-ruby "3.0.3"
+ruby "3.1.2"
 
 # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
-gem "rails", "~> 7.0.3"
+gem "rails", "~> 7.0.3", ">= 7.0.3.1"
 
 # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
 gem "sprockets-rails"
 
-# Use sqlite3 as the database for Active Record
-gem "sqlite3", "~> 1.4"
+# Use postgresql as the database for Active Record
+gem "pg", "~> 1.1"
 
 # Use the Puma web server [https://github.com/puma/puma]
 gem "puma", "~> 5.0"
@@ -28,7 +28,7 @@ gem "stimulus-rails"
 gem "jbuilder"
 
 # Use Redis adapter to run Action Cable in production
-# gem "redis", "~> 4.0"
+gem "redis", "~> 4.0"
 
 # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
 # gem "kredis"
diff --git a/examples/ruby-rails/Gemfile.lock b/examples/ruby-rails-postgres/Gemfile.lock
similarity index 65%
rename from examples/ruby-rails/Gemfile.lock
rename to examples/ruby-rails-postgres/Gemfile.lock
index 6023e7e..8316509 100644
--- a/examples/ruby-rails/Gemfile.lock
+++ b/examples/ruby-rails-postgres/Gemfile.lock
@@ -1,67 +1,67 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    actioncable (7.0.3)
-      actionpack (= 7.0.3)
-      activesupport (= 7.0.3)
+    actioncable (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       nio4r (~> 2.0)
       websocket-driver (>= 0.6.1)
-    actionmailbox (7.0.3)
-      actionpack (= 7.0.3)
-      activejob (= 7.0.3)
-      activerecord (= 7.0.3)
-      activestorage (= 7.0.3)
-      activesupport (= 7.0.3)
+    actionmailbox (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      activejob (= 7.0.3.1)
+      activerecord (= 7.0.3.1)
+      activestorage (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       mail (>= 2.7.1)
       net-imap
       net-pop
       net-smtp
-    actionmailer (7.0.3)
-      actionpack (= 7.0.3)
-      actionview (= 7.0.3)
-      activejob (= 7.0.3)
-      activesupport (= 7.0.3)
+    actionmailer (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      actionview (= 7.0.3.1)
+      activejob (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       mail (~> 2.5, >= 2.5.4)
       net-imap
       net-pop
       net-smtp
       rails-dom-testing (~> 2.0)
-    actionpack (7.0.3)
-      actionview (= 7.0.3)
-      activesupport (= 7.0.3)
+    actionpack (7.0.3.1)
+      actionview (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       rack (~> 2.0, >= 2.2.0)
       rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.0, >= 1.2.0)
-    actiontext (7.0.3)
-      actionpack (= 7.0.3)
-      activerecord (= 7.0.3)
-      activestorage (= 7.0.3)
-      activesupport (= 7.0.3)
+    actiontext (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      activerecord (= 7.0.3.1)
+      activestorage (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       globalid (>= 0.6.0)
       nokogiri (>= 1.8.5)
-    actionview (7.0.3)
-      activesupport (= 7.0.3)
+    actionview (7.0.3.1)
+      activesupport (= 7.0.3.1)
       builder (~> 3.1)
       erubi (~> 1.4)
       rails-dom-testing (~> 2.0)
       rails-html-sanitizer (~> 1.1, >= 1.2.0)
-    activejob (7.0.3)
-      activesupport (= 7.0.3)
+    activejob (7.0.3.1)
+      activesupport (= 7.0.3.1)
       globalid (>= 0.3.6)
-    activemodel (7.0.3)
-      activesupport (= 7.0.3)
-    activerecord (7.0.3)
-      activemodel (= 7.0.3)
-      activesupport (= 7.0.3)
-    activestorage (7.0.3)
-      actionpack (= 7.0.3)
-      activejob (= 7.0.3)
-      activerecord (= 7.0.3)
-      activesupport (= 7.0.3)
+    activemodel (7.0.3.1)
+      activesupport (= 7.0.3.1)
+    activerecord (7.0.3.1)
+      activemodel (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
+    activestorage (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      activejob (= 7.0.3.1)
+      activerecord (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       marcel (~> 1.0)
       mini_mime (>= 1.1.0)
-    activesupport (7.0.3)
+    activesupport (7.0.3.1)
       concurrent-ruby (~> 1.0, >= 1.0.2)
       i18n (>= 1.6, < 2)
       minitest (>= 5.1)
@@ -84,16 +84,16 @@ GEM
     childprocess (4.1.0)
     concurrent-ruby (1.1.10)
     crass (1.0.6)
-    debug (1.5.0)
+    debug (1.6.1)
       irb (>= 1.3.6)
-      reline (>= 0.2.7)
+      reline (>= 0.3.1)
     digest (3.1.0)
     erubi (1.10.0)
     globalid (1.0.0)
       activesupport (>= 5.0)
-    i18n (1.10.0)
+    i18n (1.12.0)
       concurrent-ruby (~> 1.0)
-    importmap-rails (1.1.0)
+    importmap-rails (1.1.3)
       actionpack (>= 6.0.0)
       railties (>= 6.0.0)
     io-console (0.5.11)
@@ -111,8 +111,8 @@ GEM
     matrix (0.4.2)
     method_source (1.0.0)
     mini_mime (1.1.2)
-    minitest (5.16.0)
-    msgpack (1.5.2)
+    minitest (5.16.2)
+    msgpack (1.5.3)
     net-imap (0.2.3)
       digest
       net-protocol
@@ -128,60 +128,61 @@ GEM
       net-protocol
       timeout
     nio4r (2.5.8)
-    nokogiri (1.13.6-x86_64-linux)
+    nokogiri (1.13.7-arm64-darwin)
       racc (~> 1.4)
+    pg (1.4.1)
     public_suffix (4.0.7)
     puma (5.6.4)
       nio4r (~> 2.0)
     racc (1.6.0)
-    rack (2.2.3.1)
-    rack-test (1.1.0)
-      rack (>= 1.0, < 3)
-    rails (7.0.3)
-      actioncable (= 7.0.3)
-      actionmailbox (= 7.0.3)
-      actionmailer (= 7.0.3)
-      actionpack (= 7.0.3)
-      actiontext (= 7.0.3)
-      actionview (= 7.0.3)
-      activejob (= 7.0.3)
-      activemodel (= 7.0.3)
-      activerecord (= 7.0.3)
-      activestorage (= 7.0.3)
-      activesupport (= 7.0.3)
+    rack (2.2.4)
+    rack-test (2.0.2)
+      rack (>= 1.3)
+    rails (7.0.3.1)
+      actioncable (= 7.0.3.1)
+      actionmailbox (= 7.0.3.1)
+      actionmailer (= 7.0.3.1)
+      actionpack (= 7.0.3.1)
+      actiontext (= 7.0.3.1)
+      actionview (= 7.0.3.1)
+      activejob (= 7.0.3.1)
+      activemodel (= 7.0.3.1)
+      activerecord (= 7.0.3.1)
+      activestorage (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       bundler (>= 1.15.0)
-      railties (= 7.0.3)
+      railties (= 7.0.3.1)
     rails-dom-testing (2.0.3)
       activesupport (>= 4.2.0)
       nokogiri (>= 1.6)
     rails-html-sanitizer (1.4.3)
       loofah (~> 2.3)
-    railties (7.0.3)
-      actionpack (= 7.0.3)
-      activesupport (= 7.0.3)
+    railties (7.0.3.1)
+      actionpack (= 7.0.3.1)
+      activesupport (= 7.0.3.1)
       method_source
       rake (>= 12.2)
       thor (~> 1.0)
       zeitwerk (~> 2.5)
     rake (13.0.6)
+    redis (4.7.1)
     regexp_parser (2.5.0)
     reline (0.3.1)
       io-console (~> 0.5)
     rexml (3.2.5)
     rubyzip (2.3.2)
-    selenium-webdriver (4.2.1)
+    selenium-webdriver (4.3.0)
       childprocess (>= 0.5, < 5.0)
       rexml (~> 3.2, >= 3.2.5)
       rubyzip (>= 1.2.2, < 3.0)
       websocket (~> 1.0)
-    sprockets (4.0.3)
+    sprockets (4.1.1)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
     sprockets-rails (3.4.2)
       actionpack (>= 5.2)
       activesupport (>= 5.2)
       sprockets (>= 3.0.0)
-    sqlite3 (1.4.4)
     stimulus-rails (1.0.4)
       railties (>= 6.0.0)
     strscan (3.0.3)
@@ -211,7 +212,7 @@ GEM
     zeitwerk (2.6.0)
 
 PLATFORMS
-  x86_64-linux
+  arm64-darwin-21
 
 DEPENDENCIES
   bootsnap
@@ -219,11 +220,12 @@ DEPENDENCIES
   debug
   importmap-rails
   jbuilder
+  pg (~> 1.1)
   puma (~> 5.0)
-  rails (~> 7.0.3)
+  rails (~> 7.0.3, >= 7.0.3.1)
+  redis (~> 4.0)
   selenium-webdriver
   sprockets-rails
-  sqlite3 (~> 1.4)
   stimulus-rails
   turbo-rails
   tzinfo-data
@@ -231,7 +233,7 @@ DEPENDENCIES
   webdrivers
 
 RUBY VERSION
-   ruby 3.0.3p157
+   ruby 3.1.2p20
 
 BUNDLED WITH
-   2.3.12
+   2.3.7
diff --git a/examples/ruby-rails-postgres/Procfile b/examples/ruby-rails-postgres/Procfile
new file mode 100644
index 0000000..a3abf51
--- /dev/null
+++ b/examples/ruby-rails-postgres/Procfile
@@ -0,0 +1,1 @@
+web: rake db:migrate && bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000}
diff --git a/examples/ruby-rails-postgres/README.md b/examples/ruby-rails-postgres/README.md
new file mode 100644
index 0000000..f6bf1b7
--- /dev/null
+++ b/examples/ruby-rails-postgres/README.md
@@ -0,0 +1,34 @@
+---
+title: Rails Starter
+description: A Rails starter app using a PostgreSQL database
+tags:
+  - ruby
+  - rails
+  - postgresql
+---
+
+# Rails Starter Example
+
+This is a [Ruby on Rails](https://rubyonrails.org/) starter app that connects to a Railway Postgres database and supports [Action Cable](https://guides.rubyonrails.org/action_cable_overview.html).
+
+[![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template/sibk1f)
+
+## ✨ Features
+
+- Ruby
+- Rails
+- Postgres
+- Redis
+
+## 💁‍♀️ How to use
+
+- [Create a Railway project with the Postgres plugin](https://railway.app/project?plugins=postgresql)
+- Connect to your Railway project with `railway link`
+- Install Ruby requirements `bundle install`
+- Migrate the database `railway run rake db:migrate`
+- Run Rails `railway run bin/rails server`
+
+## 📝 Notes
+
+This app was generated with the `rails new` command. Read more about Rails on
+their [official website](https://rubyonrails.org/)
diff --git a/examples/ruby-rails/Rakefile b/examples/ruby-rails-postgres/Rakefile
similarity index 100%
rename from examples/ruby-rails/Rakefile
rename to examples/ruby-rails-postgres/Rakefile
diff --git a/examples/ruby-rails/app/assets/config/manifest.js b/examples/ruby-rails-postgres/app/assets/config/manifest.js
similarity index 100%
rename from examples/ruby-rails/app/assets/config/manifest.js
rename to examples/ruby-rails-postgres/app/assets/config/manifest.js
diff --git a/examples/ruby-rails/app/assets/images/.keep b/examples/ruby-rails-postgres/app/assets/images/.keep
similarity index 100%
rename from examples/ruby-rails/app/assets/images/.keep
rename to examples/ruby-rails-postgres/app/assets/images/.keep
diff --git a/examples/ruby-rails/app/assets/stylesheets/application.css b/examples/ruby-rails-postgres/app/assets/stylesheets/application.css
similarity index 100%
rename from examples/ruby-rails/app/assets/stylesheets/application.css
rename to examples/ruby-rails-postgres/app/assets/stylesheets/application.css
diff --git a/examples/ruby-rails/app/channels/application_cable/channel.rb b/examples/ruby-rails-postgres/app/channels/application_cable/channel.rb
similarity index 100%
rename from examples/ruby-rails/app/channels/application_cable/channel.rb
rename to examples/ruby-rails-postgres/app/channels/application_cable/channel.rb
diff --git a/examples/ruby-rails/app/channels/application_cable/connection.rb b/examples/ruby-rails-postgres/app/channels/application_cable/connection.rb
similarity index 100%
rename from examples/ruby-rails/app/channels/application_cable/connection.rb
rename to examples/ruby-rails-postgres/app/channels/application_cable/connection.rb
diff --git a/examples/ruby-rails/app/controllers/application_controller.rb b/examples/ruby-rails-postgres/app/controllers/application_controller.rb
similarity index 100%
rename from examples/ruby-rails/app/controllers/application_controller.rb
rename to examples/ruby-rails-postgres/app/controllers/application_controller.rb
diff --git a/examples/ruby-rails/app/controllers/concerns/.keep b/examples/ruby-rails-postgres/app/controllers/concerns/.keep
similarity index 100%
rename from examples/ruby-rails/app/controllers/concerns/.keep
rename to examples/ruby-rails-postgres/app/controllers/concerns/.keep
diff --git a/examples/ruby-rails/app/helpers/application_helper.rb b/examples/ruby-rails-postgres/app/helpers/application_helper.rb
similarity index 100%
rename from examples/ruby-rails/app/helpers/application_helper.rb
rename to examples/ruby-rails-postgres/app/helpers/application_helper.rb
diff --git a/examples/ruby-rails/app/javascript/application.js b/examples/ruby-rails-postgres/app/javascript/application.js
similarity index 86%
rename from examples/ruby-rails/app/javascript/application.js
rename to examples/ruby-rails-postgres/app/javascript/application.js
index 0d7b494..e524d16 100644
--- a/examples/ruby-rails/app/javascript/application.js
+++ b/examples/ruby-rails-postgres/app/javascript/application.js
@@ -1,3 +1,2 @@
 // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
 import "@hotwired/turbo-rails"
-import "controllers"
diff --git a/examples/ruby-rails/app/jobs/application_job.rb b/examples/ruby-rails-postgres/app/jobs/application_job.rb
similarity index 100%
rename from examples/ruby-rails/app/jobs/application_job.rb
rename to examples/ruby-rails-postgres/app/jobs/application_job.rb
diff --git a/examples/ruby-rails/app/mailers/application_mailer.rb b/examples/ruby-rails-postgres/app/mailers/application_mailer.rb
similarity index 100%
rename from examples/ruby-rails/app/mailers/application_mailer.rb
rename to examples/ruby-rails-postgres/app/mailers/application_mailer.rb
diff --git a/examples/ruby-rails/app/models/application_record.rb b/examples/ruby-rails-postgres/app/models/application_record.rb
similarity index 100%
rename from examples/ruby-rails/app/models/application_record.rb
rename to examples/ruby-rails-postgres/app/models/application_record.rb
diff --git a/examples/ruby-rails/app/models/concerns/.keep b/examples/ruby-rails-postgres/app/models/concerns/.keep
similarity index 100%
rename from examples/ruby-rails/app/models/concerns/.keep
rename to examples/ruby-rails-postgres/app/models/concerns/.keep
diff --git a/examples/ruby-rails/app/views/layouts/application.html.erb b/examples/ruby-rails-postgres/app/views/layouts/application.html.erb
similarity index 89%
rename from examples/ruby-rails/app/views/layouts/application.html.erb
rename to examples/ruby-rails-postgres/app/views/layouts/application.html.erb
index ba30da1..439477f 100644
--- a/examples/ruby-rails/app/views/layouts/application.html.erb
+++ b/examples/ruby-rails-postgres/app/views/layouts/application.html.erb
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
   <head>
-    <title>RubyRails</title>
+    <title>RubyRailsPostgres</title>
     <meta name="viewport" content="width=device-width,initial-scale=1">
     <%= csrf_meta_tags %>
     <%= csp_meta_tag %>
diff --git a/examples/ruby-rails/app/views/layouts/mailer.html.erb b/examples/ruby-rails-postgres/app/views/layouts/mailer.html.erb
similarity index 100%
rename from examples/ruby-rails/app/views/layouts/mailer.html.erb
rename to examples/ruby-rails-postgres/app/views/layouts/mailer.html.erb
diff --git a/examples/ruby-rails/app/views/layouts/mailer.text.erb b/examples/ruby-rails-postgres/app/views/layouts/mailer.text.erb
similarity index 100%
rename from examples/ruby-rails/app/views/layouts/mailer.text.erb
rename to examples/ruby-rails-postgres/app/views/layouts/mailer.text.erb
diff --git a/examples/ruby-rails/bin/bundle b/examples/ruby-rails-postgres/bin/bundle
similarity index 98%
rename from examples/ruby-rails/bin/bundle
rename to examples/ruby-rails-postgres/bin/bundle
index 981e650..5b593cb 100755
--- a/examples/ruby-rails/bin/bundle
+++ b/examples/ruby-rails-postgres/bin/bundle
@@ -41,7 +41,7 @@ m = Module.new do
     gemfile = ENV["BUNDLE_GEMFILE"]
     return gemfile if gemfile && !gemfile.empty?
 
-    File.expand_path("../Gemfile", __dir__)
+    File.expand_path("../../Gemfile", __FILE__)
   end
 
   def lockfile
diff --git a/examples/ruby-rails/bin/importmap b/examples/ruby-rails-postgres/bin/importmap
similarity index 100%
rename from examples/ruby-rails/bin/importmap
rename to examples/ruby-rails-postgres/bin/importmap
diff --git a/examples/ruby-rails/bin/rails b/examples/ruby-rails-postgres/bin/rails
similarity index 100%
rename from examples/ruby-rails/bin/rails
rename to examples/ruby-rails-postgres/bin/rails
diff --git a/examples/ruby-rails/bin/rake b/examples/ruby-rails-postgres/bin/rake
similarity index 100%
rename from examples/ruby-rails/bin/rake
rename to examples/ruby-rails-postgres/bin/rake
diff --git a/examples/ruby-rails/bin/setup b/examples/ruby-rails-postgres/bin/setup
similarity index 100%
rename from examples/ruby-rails/bin/setup
rename to examples/ruby-rails-postgres/bin/setup
diff --git a/examples/ruby-rails/config.ru b/examples/ruby-rails-postgres/config.ru
similarity index 100%
rename from examples/ruby-rails/config.ru
rename to examples/ruby-rails-postgres/config.ru
diff --git a/examples/ruby-rails/config/application.rb b/examples/ruby-rails-postgres/config/application.rb
similarity index 96%
rename from examples/ruby-rails/config/application.rb
rename to examples/ruby-rails-postgres/config/application.rb
index 94ff4a4..bdafd27 100644
--- a/examples/ruby-rails/config/application.rb
+++ b/examples/ruby-rails-postgres/config/application.rb
@@ -6,7 +6,7 @@ require "rails/all"
 # you've limited to :test, :development, or :production.
 Bundler.require(*Rails.groups)
 
-module RubyRails
+module RubyRailsPostgres
   class Application < Rails::Application
     # Initialize configuration defaults for originally generated Rails version.
     config.load_defaults 7.0
diff --git a/examples/ruby-rails/config/boot.rb b/examples/ruby-rails-postgres/config/boot.rb
similarity index 100%
rename from examples/ruby-rails/config/boot.rb
rename to examples/ruby-rails-postgres/config/boot.rb
diff --git a/examples/ruby-rails/config/cable.yml b/examples/ruby-rails-postgres/config/cable.yml
similarity index 57%
rename from examples/ruby-rails/config/cable.yml
rename to examples/ruby-rails-postgres/config/cable.yml
index e16f8f6..65b3ba1 100644
--- a/examples/ruby-rails/config/cable.yml
+++ b/examples/ruby-rails-postgres/config/cable.yml
@@ -1,5 +1,6 @@
 development:
-  adapter: async
+  adapter: redis
+  url: redis://localhost:6379/1
 
 test:
   adapter: test
@@ -7,4 +8,4 @@ test:
 production:
   adapter: redis
   url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
-  channel_prefix: ruby_rails_production
+  channel_prefix: ruby_rails_postgres_production
diff --git a/examples/ruby-rails-postgres/config/credentials.yml.enc b/examples/ruby-rails-postgres/config/credentials.yml.enc
new file mode 100644
index 0000000..d64f86e
--- /dev/null
+++ b/examples/ruby-rails-postgres/config/credentials.yml.enc
@@ -0,0 +1,1 @@
+EQPmg2/qhhG1Cv4TEdE6zKWtd7qnwtlNnl14E1UnXkRB1Wj9t6tajmpQfUAEIRzQrhDwds5/zjeDki87tQ2ZabEBfu9Ec2tPwQcHAHUBS88nifVXNVCwmQ/Tdu7rUmrUTmeP5ouAGcO6uzsZYvnrLmjZZ+TXE9pz4ZXKBX5f6zIAyR8WV0YEDdy0O/FwiFY+AbfL3huBfVayt7UxTggkaySxaoJrkX39VsiWrv79CUHvvUeryYuXrCTKWTEzlNRAT4u80wSAyFSfb4Su8MuDWT68zAhAf9jRDKGmpmhX0qtsEbMBxZjFAl5HJdAYPgRTcwxbJgXCLB7ZL5ut63eQm05Io0FFS8jarUbLKBE8Xr6zhv6B4njW8/nLHfLYbke4/RWUPC+gC1FZk62kbxF4aIQH2OUOZQZkO7MC--HcHJ/V3Jq93Ex4Pl--dP8YSje+cTSADUyhiry8FA==
\ No newline at end of file
diff --git a/examples/ruby-rails-postgres/config/database.yml b/examples/ruby-rails-postgres/config/database.yml
new file mode 100644
index 0000000..f54258b
--- /dev/null
+++ b/examples/ruby-rails-postgres/config/database.yml
@@ -0,0 +1,84 @@
+# PostgreSQL. Versions 9.3 and up are supported.
+#
+# Install the pg driver:
+#   gem install pg
+# On macOS with Homebrew:
+#   gem install pg -- --with-pg-config=/usr/local/bin/pg_config
+# On macOS with MacPorts:
+#   gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
+# On Windows:
+#   gem install pg
+#       Choose the win32 build.
+#       Install PostgreSQL and put its /bin directory on your path.
+#
+# Configure Using Gemfile
+# gem "pg"
+#
+default: &default
+  adapter: postgresql
+  encoding: unicode
+  # For details on connection pooling, see Rails configuration guide
+  # https://guides.rubyonrails.org/configuring.html#database-pooling
+  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+
+development:
+  <<: *default
+  url: <%= ENV["DATABASE_URL"] %>
+
+  # The specified database role being used to connect to postgres.
+  # To create additional roles in postgres see `$ createuser --help`.
+  # When left blank, postgres will use the default role. This is
+  # the same name as the operating system user running Rails.
+  #username: ruby_rails_postgres
+
+  # The password associated with the postgres role (username).
+  #password:
+
+  # Connect on a TCP socket. Omitted by default since the client uses a
+  # domain socket that doesn't need configuration. Windows does not have
+  # domain sockets, so uncomment these lines.
+  #host: localhost
+
+  # The TCP port the server listens on. Defaults to 5432.
+  # If your server runs on a different port number, change accordingly.
+  #port: 5432
+
+  # Schema search path. The server defaults to $user,public
+  #schema_search_path: myapp,sharedapp,public
+
+  # Minimum log levels, in increasing order:
+  #   debug5, debug4, debug3, debug2, debug1,
+  #   log, notice, warning, error, fatal, and panic
+  # Defaults to warning.
+  #min_messages: notice
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+  <<: *default
+  url: <%= ENV["DATABASE_URL"] %>
+
+# As with config/credentials.yml, you never want to store sensitive information,
+# like your database password, in your source code. If your source code is
+# ever seen by anyone, they now have access to your database.
+#
+# Instead, provide the password or a full connection URL as an environment
+# variable when you boot the app. For example:
+#
+#   DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
+#
+# If the connection URL is provided in the special DATABASE_URL environment
+# variable, Rails will automatically merge its configuration values on top of
+# the values provided in this file. Alternatively, you can specify a connection
+# URL environment variable explicitly:
+#
+#   production:
+#     url: <%= ENV["MY_APP_DATABASE_URL"] %>
+#
+# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
+# for a full overview on how database connection configuration can be specified.
+#
+production:
+  <<: *default
+  url: <%= ENV["DATABASE_URL"] %>
diff --git a/examples/ruby-rails/config/environment.rb b/examples/ruby-rails-postgres/config/environment.rb
similarity index 100%
rename from examples/ruby-rails/config/environment.rb
rename to examples/ruby-rails-postgres/config/environment.rb
diff --git a/examples/ruby-rails/config/environments/development.rb b/examples/ruby-rails-postgres/config/environments/development.rb
similarity index 100%
rename from examples/ruby-rails/config/environments/development.rb
rename to examples/ruby-rails-postgres/config/environments/development.rb
diff --git a/examples/ruby-rails/config/environments/production.rb b/examples/ruby-rails-postgres/config/environments/production.rb
similarity index 98%
rename from examples/ruby-rails/config/environments/production.rb
rename to examples/ruby-rails-postgres/config/environments/production.rb
index a7253ff..6f14a88 100644
--- a/examples/ruby-rails/config/environments/production.rb
+++ b/examples/ruby-rails-postgres/config/environments/production.rb
@@ -60,7 +60,7 @@ Rails.application.configure do
 
   # Use a real queuing backend for Active Job (and separate queues per environment).
   # config.active_job.queue_adapter     = :resque
-  # config.active_job.queue_name_prefix = "ruby_rails_production"
+  # config.active_job.queue_name_prefix = "ruby_rails_postgres_production"
 
   config.action_mailer.perform_caching = false
 
diff --git a/examples/ruby-rails/config/environments/test.rb b/examples/ruby-rails-postgres/config/environments/test.rb
similarity index 100%
rename from examples/ruby-rails/config/environments/test.rb
rename to examples/ruby-rails-postgres/config/environments/test.rb
diff --git a/examples/ruby-rails-postgres/config/importmap.rb b/examples/ruby-rails-postgres/config/importmap.rb
new file mode 100644
index 0000000..26c5560
--- /dev/null
+++ b/examples/ruby-rails-postgres/config/importmap.rb
@@ -0,0 +1,4 @@
+# Pin npm packages by running ./bin/importmap
+
+pin "application", preload: true
+pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
diff --git a/examples/ruby-rails/config/initializers/assets.rb b/examples/ruby-rails-postgres/config/initializers/assets.rb
similarity index 100%
rename from examples/ruby-rails/config/initializers/assets.rb
rename to examples/ruby-rails-postgres/config/initializers/assets.rb
diff --git a/examples/ruby-rails/config/initializers/content_security_policy.rb b/examples/ruby-rails-postgres/config/initializers/content_security_policy.rb
similarity index 100%
rename from examples/ruby-rails/config/initializers/content_security_policy.rb
rename to examples/ruby-rails-postgres/config/initializers/content_security_policy.rb
diff --git a/examples/ruby-rails/config/initializers/filter_parameter_logging.rb b/examples/ruby-rails-postgres/config/initializers/filter_parameter_logging.rb
similarity index 100%
rename from examples/ruby-rails/config/initializers/filter_parameter_logging.rb
rename to examples/ruby-rails-postgres/config/initializers/filter_parameter_logging.rb
diff --git a/examples/ruby-rails/config/initializers/inflections.rb b/examples/ruby-rails-postgres/config/initializers/inflections.rb
similarity index 100%
rename from examples/ruby-rails/config/initializers/inflections.rb
rename to examples/ruby-rails-postgres/config/initializers/inflections.rb
diff --git a/examples/ruby-rails/config/initializers/permissions_policy.rb b/examples/ruby-rails-postgres/config/initializers/permissions_policy.rb
similarity index 100%
rename from examples/ruby-rails/config/initializers/permissions_policy.rb
rename to examples/ruby-rails-postgres/config/initializers/permissions_policy.rb
diff --git a/examples/ruby-rails/config/locales/en.yml b/examples/ruby-rails-postgres/config/locales/en.yml
similarity index 100%
rename from examples/ruby-rails/config/locales/en.yml
rename to examples/ruby-rails-postgres/config/locales/en.yml
diff --git a/examples/ruby-rails/config/puma.rb b/examples/ruby-rails-postgres/config/puma.rb
similarity index 100%
rename from examples/ruby-rails/config/puma.rb
rename to examples/ruby-rails-postgres/config/puma.rb
diff --git a/examples/ruby-rails/config/routes.rb b/examples/ruby-rails-postgres/config/routes.rb
similarity index 100%
rename from examples/ruby-rails/config/routes.rb
rename to examples/ruby-rails-postgres/config/routes.rb
diff --git a/examples/ruby-rails/config/storage.yml b/examples/ruby-rails-postgres/config/storage.yml
similarity index 100%
rename from examples/ruby-rails/config/storage.yml
rename to examples/ruby-rails-postgres/config/storage.yml
diff --git a/examples/ruby-rails-postgres/db/schema.rb b/examples/ruby-rails-postgres/db/schema.rb
new file mode 100644
index 0000000..4c6bb01
--- /dev/null
+++ b/examples/ruby-rails-postgres/db/schema.rb
@@ -0,0 +1,18 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# This file is the source Rails uses to define your schema when running `bin/rails
+# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
+# be faster and is potentially less error prone than running all of your
+# migrations from scratch. Old migrations may fail to apply correctly if those
+# migrations use external dependencies or application code.
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema[7.0].define(version: 0) do
+  # These are extensions that must be enabled in order to support this database
+  enable_extension "plpgsql"
+  enable_extension "timescaledb"
+
+end
diff --git a/examples/ruby-rails/db/seeds.rb b/examples/ruby-rails-postgres/db/seeds.rb
similarity index 100%
rename from examples/ruby-rails/db/seeds.rb
rename to examples/ruby-rails-postgres/db/seeds.rb
diff --git a/examples/ruby-rails/lib/assets/.keep b/examples/ruby-rails-postgres/lib/assets/.keep
similarity index 100%
rename from examples/ruby-rails/lib/assets/.keep
rename to examples/ruby-rails-postgres/lib/assets/.keep
diff --git a/examples/ruby-rails/lib/tasks/.keep b/examples/ruby-rails-postgres/lib/tasks/.keep
similarity index 100%
rename from examples/ruby-rails/lib/tasks/.keep
rename to examples/ruby-rails-postgres/lib/tasks/.keep
diff --git a/examples/ruby-rails/log/.keep b/examples/ruby-rails-postgres/log/.keep
similarity index 100%
rename from examples/ruby-rails/log/.keep
rename to examples/ruby-rails-postgres/log/.keep
diff --git a/examples/ruby-rails/public/404.html b/examples/ruby-rails-postgres/public/404.html
similarity index 100%
rename from examples/ruby-rails/public/404.html
rename to examples/ruby-rails-postgres/public/404.html
diff --git a/examples/ruby-rails/public/422.html b/examples/ruby-rails-postgres/public/422.html
similarity index 100%
rename from examples/ruby-rails/public/422.html
rename to examples/ruby-rails-postgres/public/422.html
diff --git a/examples/ruby-rails/public/500.html b/examples/ruby-rails-postgres/public/500.html
similarity index 100%
rename from examples/ruby-rails/public/500.html
rename to examples/ruby-rails-postgres/public/500.html
diff --git a/examples/ruby-rails/public/apple-touch-icon-precomposed.png b/examples/ruby-rails-postgres/public/apple-touch-icon-precomposed.png
similarity index 100%
rename from examples/ruby-rails/public/apple-touch-icon-precomposed.png
rename to examples/ruby-rails-postgres/public/apple-touch-icon-precomposed.png
diff --git a/examples/ruby-rails/public/apple-touch-icon.png b/examples/ruby-rails-postgres/public/apple-touch-icon.png
similarity index 100%
rename from examples/ruby-rails/public/apple-touch-icon.png
rename to examples/ruby-rails-postgres/public/apple-touch-icon.png
diff --git a/examples/ruby-rails/public/favicon.ico b/examples/ruby-rails-postgres/public/favicon.ico
similarity index 100%
rename from examples/ruby-rails/public/favicon.ico
rename to examples/ruby-rails-postgres/public/favicon.ico
diff --git a/examples/ruby-rails/public/robots.txt b/examples/ruby-rails-postgres/public/robots.txt
similarity index 100%
rename from examples/ruby-rails/public/robots.txt
rename to examples/ruby-rails-postgres/public/robots.txt
diff --git a/examples/ruby-rails/storage/.keep b/examples/ruby-rails-postgres/storage/.keep
similarity index 100%
rename from examples/ruby-rails/storage/.keep
rename to examples/ruby-rails-postgres/storage/.keep
diff --git a/examples/ruby-rails/vendor/.keep b/examples/ruby-rails-postgres/vendor/.keep
similarity index 100%
rename from examples/ruby-rails/vendor/.keep
rename to examples/ruby-rails-postgres/vendor/.keep
diff --git a/examples/ruby-rails/vendor/javascript/.keep b/examples/ruby-rails-postgres/vendor/javascript/.keep
similarity index 100%
rename from examples/ruby-rails/vendor/javascript/.keep
rename to examples/ruby-rails-postgres/vendor/javascript/.keep
diff --git a/examples/ruby-rails/.ruby-version b/examples/ruby-rails/.ruby-version
deleted file mode 100644
index e76033b..0000000
--- a/examples/ruby-rails/.ruby-version
+++ /dev/null
@@ -1,1 +0,0 @@
-ruby-3.0.3
diff --git a/examples/ruby-rails/README.md b/examples/ruby-rails/README.md
deleted file mode 100644
index 7db80e4..0000000
--- a/examples/ruby-rails/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# README
-
-This README would normally document whatever steps are necessary to get the
-application up and running.
-
-Things you may want to cover:
-
-* Ruby version
-
-* System dependencies
-
-* Configuration
-
-* Database creation
-
-* Database initialization
-
-* How to run the test suite
-
-* Services (job queues, cache servers, search engines, etc.)
-
-* Deployment instructions
-
-* ...
diff --git a/examples/ruby-rails/app/javascript/controllers/application.js b/examples/ruby-rails/app/javascript/controllers/application.js
deleted file mode 100644
index 1213e85..0000000
--- a/examples/ruby-rails/app/javascript/controllers/application.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Application } from "@hotwired/stimulus"
-
-const application = Application.start()
-
-// Configure Stimulus development experience
-application.debug = false
-window.Stimulus   = application
-
-export { application }
diff --git a/examples/ruby-rails/app/javascript/controllers/hello_controller.js b/examples/ruby-rails/app/javascript/controllers/hello_controller.js
deleted file mode 100644
index 5975c07..0000000
--- a/examples/ruby-rails/app/javascript/controllers/hello_controller.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import { Controller } from "@hotwired/stimulus"
-
-export default class extends Controller {
-  connect() {
-    this.element.textContent = "Hello World!"
-  }
-}
diff --git a/examples/ruby-rails/app/javascript/controllers/index.js b/examples/ruby-rails/app/javascript/controllers/index.js
deleted file mode 100644
index 54ad4ca..0000000
--- a/examples/ruby-rails/app/javascript/controllers/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Import and register all your controllers from the importmap under controllers/*
-
-import { application } from "controllers/application"
-
-// Eager load all controllers defined in the import map under controllers/**/*_controller
-import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
-eagerLoadControllersFrom("controllers", application)
-
-// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
-// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
-// lazyLoadControllersFrom("controllers", application)
diff --git a/examples/ruby-rails/config/credentials.yml.enc b/examples/ruby-rails/config/credentials.yml.enc
deleted file mode 100644
index 3170f45..0000000
--- a/examples/ruby-rails/config/credentials.yml.enc
+++ /dev/null
@@ -1,1 +0,0 @@
-4cfZyLSzvnqDGqXqSU6QmtCK7TTNBPP4R9HROIlzh0P3iJ/GM+QBqgiy63JFhCizWobt2n8BkC5kdEytXc77jobqRotCLHyJsq9/vSC2Kn9kKZ9HdPeqWbZoLNuUO+4RlTvd4VBqK26qvarY30k0fyqefQ52vNaS78KImczOhcLKhLuMBSv8dZydeO3KACeSGm/3xk71/oIdZG3d0oc/6zAL5txgncs7h57Q1XqQawRkt9lz14sI4nexUpIBuxtw0tkdaXnF3UDZk7XaigUY6F6yp3VPfW+A3J5K+la87b9QIiajR1Vpwefe8MEgPhyViN+ce0EyvZO6SYeCl0mNIndI+tMzqlBtlGNb1a5eU0Zll4y6WUtD8iSP9ZM+1bPTyUKBkKRyuSguqfVXfAftClHEHmHOt+yeReQg--YQzD6ziIlayHClyM--+lxZ1wrfZPfaTQoHBeX8nA==
\ No newline at end of file
diff --git a/examples/ruby-rails/config/database.yml b/examples/ruby-rails/config/database.yml
deleted file mode 100644
index fcba57f..0000000
--- a/examples/ruby-rails/config/database.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-# SQLite. Versions 3.8.0 and up are supported.
-#   gem install sqlite3
-#
-#   Ensure the SQLite 3 gem is defined in your Gemfile
-#   gem "sqlite3"
-#
-default: &default
-  adapter: sqlite3
-  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
-  timeout: 5000
-
-development:
-  <<: *default
-  database: db/development.sqlite3
-
-# Warning: The database defined as "test" will be erased and
-# re-generated from your development database when you run "rake".
-# Do not set this db to the same as development or production.
-test:
-  <<: *default
-  database: db/test.sqlite3
-
-production:
-  <<: *default
-  database: db/production.sqlite3
diff --git a/examples/ruby-rails/config/importmap.rb b/examples/ruby-rails/config/importmap.rb
deleted file mode 100644
index 8dce42d..0000000
--- a/examples/ruby-rails/config/importmap.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# Pin npm packages by running ./bin/importmap
-
-pin "application", preload: true
-pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
-pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
-pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
-pin_all_from "app/javascript/controllers", under: "controllers"
diff --git a/examples/ruby-rails/config/master.key b/examples/ruby-rails/config/master.key
deleted file mode 100644
index 2ae8816..0000000
--- a/examples/ruby-rails/config/master.key
+++ /dev/null
@@ -1,1 +0,0 @@
-2a8819448744b77022f18c3d6750e537
\ No newline at end of file
diff --git a/examples/ruby-rails/log/development.log b/examples/ruby-rails/log/development.log
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/ruby-sinatra/.gitignore b/examples/ruby-sinatra/.gitignore
new file mode 100644
index 0000000..f22dd34
--- /dev/null
+++ b/examples/ruby-sinatra/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+#   git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+# Ignore pidfiles, but keep the directory.
+/tmp/pids/*
+!/tmp/pids/
+!/tmp/pids/.keep
+
+# Ignore uploaded files in development.
+/storage/*
+!/storage/.keep
+
+/public/assets
+.byebug_history
+
+# Ignore master key for decrypting credentials and more.
+/config/master.key
+
+/public/packs
+/public/packs-test
+/node_modules
+/yarn-error.log
+yarn-debug.log*
+.yarn-integrity
diff --git a/examples/ruby-sinatra/.ruby-version b/examples/ruby-sinatra/.ruby-version
deleted file mode 100644
index 2eb2fe9..0000000
--- a/examples/ruby-sinatra/.ruby-version
+++ /dev/null
@@ -1,1 +0,0 @@
-ruby-2.7.2
diff --git a/examples/ruby-sinatra/Gemfile b/examples/ruby-sinatra/Gemfile
index aca42db..8e7ec1e 100644
--- a/examples/ruby-sinatra/Gemfile
+++ b/examples/ruby-sinatra/Gemfile
@@ -1,4 +1,7 @@
-
 source 'https://rubygems.org'
+git_source(:github) { |repo| "https://github.com/#{repo}.git" }
+
+ruby '3.1.2'
 
-gem 'sinatra'
\ No newline at end of file
+gem 'sinatra', '~> 2.2.0'
+gem 'puma', '~> 5.6.4'
diff --git a/examples/ruby-sinatra/Gemfile.lock b/examples/ruby-sinatra/Gemfile.lock
index 972ca7d..ca0547f 100644
--- a/examples/ruby-sinatra/Gemfile.lock
+++ b/examples/ruby-sinatra/Gemfile.lock
@@ -3,7 +3,10 @@ GEM
   specs:
     mustermann (1.1.1)
       ruby2_keywords (~> 0.0.1)
-    rack (2.2.3)
+    nio4r (2.5.8)
+    puma (5.6.4)
+      nio4r (~> 2.0)
+    rack (2.2.4)
     rack-protection (2.2.0)
       rack
     ruby2_keywords (0.0.5)
@@ -15,14 +18,14 @@ GEM
     tilt (2.0.10)
 
 PLATFORMS
-  x86_64-darwin-20
-  x86_64-linux
+  arm64-darwin-21
 
 DEPENDENCIES
-  sinatra
+  puma (~> 5.6.4)
+  sinatra (~> 2.2.0)
 
 RUBY VERSION
-   ruby 2.7.2p137
+   ruby 3.1.2p20
 
 BUNDLED WITH
-   2.2.8
+   2.3.7
diff --git a/examples/ruby-sinatra/Procfile b/examples/ruby-sinatra/Procfile
index 82cb606..050cfac 100644
--- a/examples/ruby-sinatra/Procfile
+++ b/examples/ruby-sinatra/Procfile
@@ -1,1 +1,1 @@
-web: ruby app.rb
\ No newline at end of file
+web: RACK_ENV=production bundle exec puma
diff --git a/examples/ruby-sinatra/app.rb b/examples/ruby-sinatra/app.rb
index c3a60ec..06a605a 100644
--- a/examples/ruby-sinatra/app.rb
+++ b/examples/ruby-sinatra/app.rb
@@ -1,5 +1,7 @@
 require 'sinatra'
+
 puts "Hello from Sinatra"
+
 get '/' do
   'Choo Choo! Welcome to your Sinatra server 🚅'
-end
\ No newline at end of file
+end
diff --git a/examples/ruby-sinatra/config.ru b/examples/ruby-sinatra/config.ru
index 0d7426a..76a6edf 100644
--- a/examples/ruby-sinatra/config.ru
+++ b/examples/ruby-sinatra/config.ru
@@ -1,3 +1,2 @@
-
 require './app'
-run Sinatra::Application
\ No newline at end of file
+run Sinatra::Application
diff --git a/examples/ruby-sinatra/config/puma.rb b/examples/ruby-sinatra/config/puma.rb
new file mode 100644
index 0000000..d7d7455
--- /dev/null
+++ b/examples/ruby-sinatra/config/puma.rb
@@ -0,0 +1,1 @@
+port ENV['PORT'] || 4567
diff --git a/examples/ruby-gemfile-lock/Gemfile b/examples/ruby/Gemfile
similarity index 68%
rename from examples/ruby-gemfile-lock/Gemfile
rename to examples/ruby/Gemfile
index aca42db..e5fe2ae 100644
--- a/examples/ruby-gemfile-lock/Gemfile
+++ b/examples/ruby/Gemfile
@@ -1,4 +1,2 @@
 
 source 'https://rubygems.org'
-
-gem 'sinatra'
\ No newline at end of file
diff --git a/examples/ruby/Gemfile.lock b/examples/ruby/Gemfile.lock
new file mode 100644
index 0000000..463f43c
--- /dev/null
+++ b/examples/ruby/Gemfile.lock
@@ -0,0 +1,14 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+
+PLATFORMS
+  arm64-darwin-21
+
+DEPENDENCIES
+
+RUBY VERSION
+   ruby 3.1.2p20
+
+BUNDLED WITH
+   2.3.7
diff --git a/examples/ruby-gemfile-lock/Procfile b/examples/ruby/Procfile
similarity index 100%
rename from examples/ruby-gemfile-lock/Procfile
rename to examples/ruby/Procfile
diff --git a/examples/ruby/app.rb b/examples/ruby/app.rb
new file mode 100644
index 0000000..0bbb7fd
--- /dev/null
+++ b/examples/ruby/app.rb
@@ -0,0 +1,1 @@
+puts "Hello from Ruby"
diff --git a/install.sh b/install.sh
index 7710487..b3ec980 100755
--- a/install.sh
+++ b/install.sh
@@ -2,30 +2,32 @@
 
 # Adapted from https://github.com/starship/starship/blob/master/install/install.sh
 
-help_text="# Options
-#
-#   -V, --verbose
-#     Enable verbose output for the installer
-#
-#   -f, -y, --force, --yes
-#     Skip the confirmation prompt during installation
-#
-#   -p, --platform
-#     Override the platform identified by the installer
-#
-#   -b, --bin-dir
-#     Override the bin installation directory
-#
-#   -a, --arch
-#     Override the architecture identified by the installer
-#
-#   -B, --base-url
-#     Override the base URL used for downloading releases
-#   -r, --remove
-#     Uninstall nixpacks
-#   -h, --help
-#     Get some help
-#
+help_text="Options
+
+   -V, --verbose
+   Enable verbose output for the installer
+
+   -f, -y, --force, --yes
+   Skip the confirmation prompt during installation
+
+   -p, --platform
+   Override the platform identified by the installer
+
+   -b, --bin-dir
+   Override the bin installation directory
+
+   -a, --arch
+   Override the architecture identified by the installer
+
+   -B, --base-url
+   Override the base URL used for downloading releases
+
+   -r, --remove
+   Uninstall nixpacks
+
+   -h, --help
+   Get some help
+
 "
 
 set -eu
@@ -52,6 +54,12 @@ info() {
   printf '%s\n' "${BOLD}${GREY}>${NO_COLOR} $*"
 }
 
+debug() {
+  if [[ -n "${VERBOSE}" ]]; then
+    printf '%s\n' "${BOLD}${GREY}>${NO_COLOR} $*"
+  fi
+}
+
 warn() {
   printf '%s\n' "${YELLOW}! $*${NO_COLOR}"
 }
@@ -97,7 +105,6 @@ download() {
   file="$1"
   url="$2"
   touch "$file"
-  printf "%s" "$file"
 
   if has curl; then
     cmd="curl --fail --silent --location --output $file $url"
@@ -128,12 +135,12 @@ unpack() {
 
   case "$archive" in
     *.tar.gz)
-      flags=$(test -n "${VERBOSE-}" && echo "-v" || echo "")
+      flags=$(test -n)
       ${sudo} tar "${flags}" -xzf "${archive}" -C "${bin_dir}"
       return 0
       ;;
     *.zip)
-      flags=$(test -z "${VERBOSE-}" && echo "-qq" || echo "")
+      flags=$(test -z)
       UNZIP="${flags}" ${sudo} unzip "${archive}" -d "${bin_dir}"
       return 0
       ;;
@@ -187,7 +194,7 @@ install() {
 
   # remove tempfile
 
-  rm "${archive}"
+  # rm "${archive}"
 }
 
 # Currently supporting:
@@ -412,6 +419,14 @@ while [ "$#" -gt 0 ]; do
     ;;
   esac
 done
+
+# non-empty VERBOSE enables verbose untarring
+if [ -n "${VERBOSE-}" ]; then
+  VERBOSE=v
+else
+  VERBOSE=
+fi
+
 if [ $UNINSTALL == 1 ]; then
   confirm "Are you sure you want to uninstall nixpacks?"
 
@@ -446,21 +461,20 @@ TARGET="$(detect_target "${ARCH}" "${PLATFORM}")"
 
 is_build_available "${ARCH}" "${PLATFORM}" "${TARGET}"
 
-printf "  %s\n" "${UNDERLINE}Configuration${NO_COLOR}"
-info "${BOLD}Bin directory${NO_COLOR}: ${GREEN}${BIN_DIR}${NO_COLOR}"
-info "${BOLD}Platform${NO_COLOR}:      ${GREEN}${PLATFORM}${NO_COLOR}"
-info "${BOLD}Arch${NO_COLOR}:          ${GREEN}${ARCH}${NO_COLOR}"
-info "${BOLD}Version${NO_COLOR}:       ${GREEN}${VERSION[0]}${NO_COLOR}"
 
-# non-empty VERBOSE enables verbose untarring
-if [ -n "${VERBOSE-}" ]; then
-  VERBOSE=v
-  info "${BOLD}Verbose${NO_COLOR}: yes"
-else
-  VERBOSE=
-fi
+print_configuration () {
+  if [[ -n "${VERBOSE}" ]]; then
+    printf "  %s\n" "${UNDERLINE}Configuration${NO_COLOR}"
+    debug "${BOLD}Bin directory${NO_COLOR}: ${GREEN}${BIN_DIR}${NO_COLOR}"
+    debug "${BOLD}Platform${NO_COLOR}:      ${GREEN}${PLATFORM}${NO_COLOR}"
+    debug "${BOLD}Arch${NO_COLOR}:          ${GREEN}${ARCH}${NO_COLOR}"
+    debug "${BOLD}Version${NO_COLOR}:       ${GREEN}${VERSION[0]}${NO_COLOR}"
+    printf '\n'
+  fi
+}
+
+print_configuration
 
-printf '\n'
 
 EXT=tar.gz
 if [ "${PLATFORM}" = "pc-windows-msvc" ]; then
@@ -468,7 +482,7 @@ if [ "${PLATFORM}" = "pc-windows-msvc" ]; then
 fi
 
 URL="${BASE_URL}/latest/download/nixpacks-v${VERSION[0]}-${TARGET}.${EXT}"
-info "Tarball URL: ${UNDERLINE}${BLUE}${URL}${NO_COLOR}"
+debug "Tarball URL: ${UNDERLINE}${BLUE}${URL}${NO_COLOR}"
 confirm "Install nixpacks ${GREEN}${VERSION[0]}${NO_COLOR} to ${BOLD}${GREEN}${BIN_DIR}${NO_COLOR}?"
 check_bin_dir "${BIN_DIR}"
 
@@ -476,6 +490,7 @@ install "${EXT}"
 
 printf "$GREEN"
   cat <<'EOF'
+
       +--------------+
      /|             /|
     / |            / |
@@ -487,5 +502,6 @@ printf "$GREEN"
    | /            | /
    |/             |/
    *--------------*
+
 EOF
 printf "$NO_COLOR"
diff --git a/src/main.rs b/src/main.rs
index 273d8dc..7047741 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -267,15 +267,3 @@ fn get_default_cache_key(path: &str) -> Result<Option<String>> {
         Ok(None)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_get_default_cache_key() {
-        let path = "./examples/node";
-        let cache_key = get_default_cache_key(path).unwrap();
-        assert_eq!(cache_key, Some("2UWr73QvCk".to_string()));
-    }
-}
diff --git a/src/nixpacks/builder/docker.rs b/src/nixpacks/builder/docker.rs
index cf447f0..7319fc2 100644
--- a/src/nixpacks/builder/docker.rs
+++ b/src/nixpacks/builder/docker.rs
@@ -110,6 +110,10 @@ impl DockerBuilder {
             docker_build_cmd.arg("--quiet");
         }
 
+        if self.options.no_cache {
+            docker_build_cmd.arg("--no-cache");
+        }
+
         // Add build environment variables
         for (name, value) in plan.variables.clone().unwrap_or_default().iter() {
             docker_build_cmd
diff --git a/src/nixpacks/images.rs b/src/nixpacks/images.rs
index efd0664..cb525f7 100644
--- a/src/nixpacks/images.rs
+++ b/src/nixpacks/images.rs
@@ -1,3 +1,3 @@
-pub static DEFAULT_BASE_IMAGE: &str = "ghcr.io/railwayapp/nixpacks:debian-1657555817";
+pub static DEFAULT_BASE_IMAGE: &str = "ghcr.io/railwayapp/nixpacks:debian-1657820962";
 
 pub static DEBIAN_SLIM_IMAGE: &str = "debian:bullseye-slim";
diff --git a/src/nixpacks/plan/generator.rs b/src/nixpacks/plan/generator.rs
index 81749b8..ed839b8 100644
--- a/src/nixpacks/plan/generator.rs
+++ b/src/nixpacks/plan/generator.rs
@@ -14,9 +14,9 @@ use crate::{
 use anyhow::{bail, Context, Ok, Result};
 
 // This line is automatically updated.
-// Last Modified: 2022-07-13 08:25:28 UTC+0000
-// https://github.com/NixOS/nixpkgs/commit/09066922296d9ef06bfadb937b2560524dd10785
-static NIXPKGS_ARCHIVE: &str = "09066922296d9ef06bfadb937b2560524dd10785";
+// Last Modified: 2022-07-18 17:26:19 UTC+0000
+// https://github.com/NixOS/nixpkgs/commit/9eb60f25aff0d2218c848dd4574a0ab5e296cabe
+static NIXPKGS_ARCHIVE: &str = "9eb60f25aff0d2218c848dd4574a0ab5e296cabe";
 
 #[derive(Clone, Default, Debug)]
 pub struct GeneratePlanOptions {
@@ -113,13 +113,7 @@ impl<'a> NixpacksBuildPlanGenerator<'a> {
 
         let env_var_pkgs = environment
             .get_config_variable("PKGS")
-            .map(|pkg_string| {
-                pkg_string
-                    .replace('-', ".")
-                    .split(' ')
-                    .map(Pkg::new)
-                    .collect::<Vec<_>>()
-            })
+            .map(|pkg_string| pkg_string.split(' ').map(Pkg::new).collect::<Vec<_>>())
             .unwrap_or_default();
 
         // Add custom user packages
diff --git a/src/providers/go.rs b/src/providers/go.rs
index e852a25..c6f8bfc 100644
--- a/src/providers/go.rs
+++ b/src/providers/go.rs
@@ -94,7 +94,7 @@ impl GolangProvider {
             let go_version_line = lines.find(|line| line.trim().starts_with("go"));
 
             if let Some(go_version_line) = go_version_line {
-                let go_version = go_version_line.split_whitespace().nth(1).unwrap();
+                let go_version = go_version_line.trim().split_whitespace().nth(1).unwrap();
 
                 if let Some(nix_pkg) = version_number_to_pkg(go_version)? {
                     return Ok(nix_pkg);
diff --git a/src/providers/haskell.rs b/src/providers/haskell.rs
index 23c518a..b0e4a45 100644
--- a/src/providers/haskell.rs
+++ b/src/providers/haskell.rs
@@ -31,6 +31,7 @@ impl Provider for HaskellStackProvider {
             "gcc".to_string(),
             "binutils".to_string(),
             "make".to_string(),
+            "zlib1g-dev".to_string(),
         ]);
         if ARCH == "aarch64" {
             setup_phase.add_apt_pkgs(vec![
diff --git a/src/providers/python.rs b/src/providers/python.rs
index 0e21636..279d3ea 100644
--- a/src/providers/python.rs
+++ b/src/providers/python.rs
@@ -47,7 +47,15 @@ impl Provider for PythonProvider {
             pkgs.append(&mut vec![Pkg::new("postgresql"), Pkg::new("gcc")]);
         }
 
-        Ok(Some(SetupPhase::new(pkgs)))
+        let mut setup_phase = SetupPhase::new(pkgs);
+
+        // Numpy needs some C headers to be available
+        // stdenv.cc.cc.lib -> https://discourse.nixos.org/t/nixos-with-poetry-installed-pandas-libstdc-so-6-cannot-open-shared-object-file/8442/3
+        if PythonProvider::uses_numpy(app)? {
+            setup_phase.add_libraries(vec!["zlib".to_string(), "stdenv.cc.cc.lib".to_string()]);
+        }
+
+        Ok(Some(setup_phase))
     }
 
     fn install(&self, app: &App, _env: &Environment) -> Result<Option<InstallPhase>> {
@@ -305,6 +313,22 @@ impl PythonProvider {
                 .ok_or_else(|| anyhow::anyhow!("failed to load pyproject.toml"))?),
         ))
     }
+
+    fn uses_numpy(app: &App) -> Result<bool> {
+        let requirements_numpy = app.includes_file("requirements.txt")
+            && app
+                .read_file("requirements.txt")?
+                .to_lowercase()
+                .contains("numpy");
+
+        let project_numpy = app.includes_file("pyproject.toml")
+            && app
+                .read_file("pyproject.toml")?
+                .to_lowercase()
+                .contains("numpy");
+
+        Ok(requirements_numpy || project_numpy)
+    }
 }
 
 #[cfg(test)]
@@ -354,4 +378,17 @@ mod test {
 
         Ok(())
     }
+
+    #[test]
+    fn test_numpy_detection() -> Result<()> {
+        assert_eq!(
+            PythonProvider::uses_numpy(&App::new("./examples/python")?)?,
+            false
+        );
+        assert_eq!(
+            PythonProvider::uses_numpy(&App::new("./examples/python-numpy")?)?,
+            true
+        );
+        Ok(())
+    }
 }
diff --git a/src/providers/ruby.rs b/src/providers/ruby.rs
index ba09b17..e8cf480 100644
--- a/src/providers/ruby.rs
+++ b/src/providers/ruby.rs
@@ -9,6 +9,8 @@ use regex::Regex;
 
 pub struct RubyProvider {}
 
+const BUNDLE_CACHE_DIR: &'static &str = &"/root/.bundle/cache";
+
 impl Provider for RubyProvider {
     fn name(&self) -> &str {
         "Ruby"
@@ -25,17 +27,30 @@ impl Provider for RubyProvider {
         }
         let mut setup_phase = SetupPhase::new(pkgs);
         setup_phase.add_apt_pkgs(vec!["procps".to_string()]);
+
+        if self.uses_postgres(app)? {
+            setup_phase.add_apt_pkgs(vec!["libpq-dev".to_string()]);
+        }
+
         setup_phase.add_cmd(
             "curl -sSL https://get.rvm.io | bash -s stable && . /etc/profile.d/rvm.sh".to_string(),
         );
-        setup_phase.add_cmd("rvm install ".to_string() + &self.get_ruby_version(app).unwrap());
-        setup_phase.add_cmd("gem install ".to_string() + &self.get_bundler_version(app));
+
+        setup_phase.add_cmd(format!("rvm install {}", self.get_ruby_version(app)?));
+        setup_phase.add_cmd(format!("gem install {}", self.get_bundler_version(app)));
+        setup_phase
+            .add_cmd("echo 'source /usr/local/rvm/scripts/rvm' >> /root/.profile".to_string());
+
         Ok(Some(setup_phase))
     }
 
     fn install(&self, app: &App, _env: &Environment) -> Result<Option<InstallPhase>> {
-        let mut install_phase = InstallPhase::new("bundle install".to_string());
+        let mut install_phase = InstallPhase::default();
         install_phase.add_file_dependency("Gemfile*".to_string());
+        install_phase.add_cache_directory(BUNDLE_CACHE_DIR.to_string());
+
+        install_phase.add_cmd("bundle install".to_string());
+
         if app.includes_file("package.json") {
             install_phase.add_file_dependency("package.json".to_string());
             install_phase
@@ -54,24 +69,34 @@ impl Provider for RubyProvider {
     }
 
     fn start(&self, app: &App, _env: &Environment) -> Result<Option<StartPhase>> {
-        Ok(Some(StartPhase::new(self.get_start_command(app))))
+        if let Some(start_cmd) = self.get_start_command(app) {
+            let start_phase = StartPhase::new(start_cmd);
+            Ok(Some(start_phase))
+        } else {
+            Ok(None)
+        }
     }
 }
 
 impl RubyProvider {
-    fn get_start_command(&self, app: &App) -> String {
+    fn get_start_command(&self, app: &App) -> Option<String> {
         if self.is_rails_app(app) {
             if app.includes_file("rails") {
-                "bundle exec rails server -b 0.0.0.0 -p ${PORT:-3000}".to_string()
+                Some("bundle exec rails server -b 0.0.0.0 -p ${PORT:-3000}".to_string())
             } else {
-                "bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000} -e $RAILS_ENV".to_string()
+                Some(
+                    "bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000} -e $RAILS_ENV"
+                        .to_string(),
+                )
             }
         } else if app.includes_file("config/environment.rb") && app.includes_directory("script") {
-            "bundle exec ruby script/server -p ${PORT:-3000}".to_string()
+            Some("bundle exec ruby script/server -p ${PORT:-3000}".to_string())
         } else if app.includes_file("config.ru") {
-            "bundle exec rackup config.ru -p ${PORT:-3000}".to_string()
+            Some("bundle exec rackup config.ru -p ${PORT:-3000}".to_string())
+        } else if app.includes_file("Rakefile") {
+            Some("bundle exec rake".to_string())
         } else {
-            "bundle exec rake".to_string()
+            None
         }
     }
 
@@ -116,33 +141,25 @@ impl RubyProvider {
                 .unwrap_or_default()
                 .contains("Rails::Application")
     }
+
+    fn uses_postgres(&self, app: &App) -> Result<bool> {
+        if app.includes_file("Gemfile") {
+            let gemfile = app.read_file("Gemfile").unwrap_or_default();
+            return Ok(gemfile.contains("pg"));
+        }
+        Ok(false)
+    }
 }
 
 #[cfg(test)]
 mod test {
     use super::*;
 
-    #[test]
-    fn test_gemfile_version() -> Result<()> {
-        assert_eq!(
-            RubyProvider::get_ruby_version(
-                &RubyProvider {},
-                &App::new("./examples/ruby-gemfile")?
-            )?,
-            "ruby-2.7.2"
-        );
-
-        Ok(())
-    }
-
     #[test]
     fn test_gemfile_lock_version() -> Result<()> {
         assert_eq!(
-            RubyProvider::get_ruby_version(
-                &RubyProvider {},
-                &App::new("./examples/ruby-gemfile-lock")?
-            )?,
-            "ruby-2.7.2"
+            RubyProvider::get_ruby_version(&RubyProvider {}, &App::new("./examples/ruby")?)?,
+            "ruby-3.1.2"
         );
 
         Ok(())
@@ -157,4 +174,17 @@ mod test {
         .is_err());
         Ok(())
     }
+
+    #[test]
+    fn test_version_file() -> Result<()> {
+        assert_eq!(
+            RubyProvider::get_ruby_version(
+                &RubyProvider {},
+                &App::new("./examples/ruby-rails-postgres")?
+            )?,
+            "3.1.2"
+        );
+
+        Ok(())
+    }
 }
diff --git a/src/providers/staticfile.rs b/src/providers/staticfile.rs
index cdc7be6..c9a8931 100644
--- a/src/providers/staticfile.rs
+++ b/src/providers/staticfile.rs
@@ -9,7 +9,6 @@ use anyhow::Result;
 use indoc::formatdoc;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
-use std::fmt::Write as _;
 
 #[derive(Serialize, Deserialize, Default, Debug)]
 pub struct Staticfile {
@@ -68,7 +67,7 @@ impl Provider for StaticfileProvider {
         let status_code = staticfile.status_code.unwrap_or_default();
         let mut error_page = "".to_string();
         for (key, value) in status_code {
-            writeln!(error_page, "\terror_page {} {};", key, value)?;
+            error_page += &format!("\terror_page {} {};\n", key, value);
         }
 
         let nginx_conf = formatdoc! {"


Test patch:
diff --git a/tests/docker_run_tests.rs b/tests/docker_run_tests.rs
index 81c99a8..a205fd3 100644
--- a/tests/docker_run_tests.rs
+++ b/tests/docker_run_tests.rs
@@ -358,6 +358,13 @@ fn test_python_poetry() {
     assert!(output.contains("Hello from Python-Poetry"));
 }
 
+#[test]
+fn test_python_numpy() {
+    let name = simple_build("./examples/python-numpy");
+    let output = run_image(name, None);
+    assert!(output.contains("Hello from Python numpy and pandas"));
+}
+
 #[test]
 fn test_rust_custom_version() {
     let name = Uuid::new_v4().to_string();
@@ -506,7 +513,32 @@ fn test_ruby_sinatra() {
 
 #[test]
 fn test_ruby_rails() {
-    let name = simple_build("./examples/ruby-rails/");
-    let output = run_image(name, None);
-    assert!(output.contains("Rails"));
+    // Create the network
+    let n = create_network();
+    let network_name = n.name.clone();
+
+    // Create the postgres instance
+    let c = run_postgres();
+    let container_name = c.name.clone();
+
+    // Attach the postgres instance to the network
+    attach_container_to_network(n.name, container_name.clone());
+
+    // Build the Django example
+    let name = simple_build("./examples/ruby-rails-postgres");
+
+    // Run the Rails example on the attached network
+    let output = run_image(
+        name,
+        Some(Config {
+            environment_variables: c.config.unwrap().environment_variables,
+            network: Some(network_name.clone()),
+        }),
+    );
+
+    // Cleanup containers and networks
+    stop_and_remove_container(container_name);
+    remove_network(network_name);
+
+    assert!(output.contains("Rails 7"));
 }
diff --git a/tests/generate_plan_tests.rs b/tests/generate_plan_tests.rs
index f4b0618..481e262 100644
--- a/tests/generate_plan_tests.rs
+++ b/tests/generate_plan_tests.rs
@@ -904,14 +904,21 @@ fn test_zig_gyro() -> Result<()> {
 
 #[test]
 fn test_ruby_rails() -> Result<()> {
-    let plan = simple_gen_plan("./examples/ruby-rails");
+    let plan = simple_gen_plan("./examples/ruby-rails-postgres");
+    assert_eq!(
+        plan.setup.unwrap().apt_pkgs,
+        Some(vec!["procps".to_string(), "libpq-dev".to_string()])
+    );
     assert_eq!(
         plan.install.unwrap().cmds,
         Some(vec!["bundle install".to_string()])
     );
     assert_eq!(
         plan.start.unwrap().cmd,
-        Some("bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000} -e $RAILS_ENV".to_string())
+        Some(
+            "rake db:migrate && bundle exec bin/rails server -b 0.0.0.0 -p ${PORT:-3000}"
+                .to_string()
+        )
     );
     Ok(())
 }
@@ -923,6 +930,9 @@ fn test_ruby_sinatra() -> Result<()> {
         plan.install.unwrap().cmds,
         Some(vec!["bundle install".to_string()])
     );
-    assert_eq!(plan.start.unwrap().cmd, Some("ruby app.rb".to_string()));
+    assert_eq!(
+        plan.start.unwrap().cmd,
+        Some("RACK_ENV=production bundle exec puma".to_string())
+    );
     Ok(())
 }