Moving your Rails app from Google App Engine Flex to Standard environment
Tags: rails, ruby, googleappengine, googlecloud
Published: 2019-08-19 04:21:12

**tl;dr** Default GAE config for Standard Environment prevents Rails apps from running. It's because `skip_files` is preventing a key file from being uploaded.

Google App Engine currently has two environments: Standard and Flex. Without going into too much detail, the Flex environment is more flexible and can run anything that runs in a docker container. The Standard environment is more restrictive (restricting you to specific languages), but it has other benefits such as much faster deploy times (~4mins instead of ~15mins), faster scaling, and it can even scale to zero.

Until recently, the standard environment hasn't been available to Rubyists, but in [June 2019](https://cloud.google.com/appengine/docs/standard/ruby/release-notes), Google announced that a Ruby 2.5 runtime is available.

## Why move from Flex to Standard? ##

By moving your Ruby project from Flex to Standard, you can expect the following benefits:
* Likely to be significantly cheaper
* Much faster deployments ~4mins vs ~15mins
* Much faster scaling
* Can scale to zero - i.e. zero cost

NOTE: Look at the [comparison page](https://cloud.google.com/appengine/docs/the-appengine-environments) to know if it's right for you.

## Migrating to Standard ##

To move from Flex to Standard there are a few changes you'll need to make.

### Ruby 2.5 only ###

You may already be using Ruby 2.6 in the Flex environment, or maybe your application is using an older version of Ruby, but the Standard environment only provides Ruby 2.5 and nothing else. You will need to make sure your application can run in a 2.5 environment. This means that if you're using any of the [new features in 2.6](https://www.rubyguides.com/2018/11/ruby-2-6-new-features/) then you'll need to take them back out.

Here's a checklist:

* Delete `.ruby-version`
* If you were using 2.6 in Flex, make sure you you aren't using any features that only appear in 2.6
* Your `Gemfile` may specify a Ruby version with something like `ruby '~> 2.6.2'`. You will need to change that to `ruby '~> 2.5'`

### Update app.yaml ###

The three main requirements are:

* remove `env: flex`
* replace `runtime: ruby` with `runtime: ruby25`
* Provide `skip_files` configuration (see below)

([Full app.yaml documentation](https://cloud.google.com/appengine/docs/standard/ruby/config/appref))

### skip_files ###

In your `app.yaml`, there is a parameter `skip_files` which tells `gcloud app deploy` which files not to upload to GAE. If you do not override `skip_files` (you probably aren't), it uses a default set of exclude patterns and prevents any `dot-files` being uploaded. This is often a useful thing, but it will break any Rails deployments because it prevents the sprockets-manifest file from being uploaded. This causes your application to throw the `The asset "somefile.jpg" is not present in the asset pipeline.` error that probably brought you to this page.

The default `skip_files` configuration looks like this:
```
# BAD
skip_files:
- ^(.*/)?#.*#$
- ^(.*/)?.*~$
- ^(.*/)?.*\.py[co]$
- ^(.*/)?.*/RCS/.*$
- ^(.*/)?\..*$
```

It's that final line that prevents `public/assets/.sprockets-manifest-5y483543959430890.json` from being uploaded, and thus causes Rails to think that assets haven't been precompiled.

You need to override it by adding something like the following to `app.yaml`:
```
# GOOD
skip_files:
- ^(.*/)?#.*#$
- ^(.*/)?.*~$
- ^(.*/)?.*/RCS/.*$
- ^(.*/)?\.git/.*$
```

[Read the documentation](https://cloud.google.com/appengine/docs/standard/python/config/appref#skip_files) for further information on the format of `app.yaml` for the Standard environment. Notice that (as of 2018-08-19) the section on `skip_files` only appears in the Python version of the document, and not in the Ruby, despite it being relevant to both.