Keep Last Modified Dates with Capistrano Deploy and SVN/Git
BoxCycle is a Rails application that just switched to Git from SVN for version control and uses Capistrano to help automate deployment.
Problem: Deploy Updates Last Modified Dates on All Files
As shocking as it may seem, when you deploy a new version of your app, there is a good chance that Last Modified dates of all files will be updated to the date of deployment even though most of those files did not change.
Why Are Last Modified Dates Important?
In a word, caching.
Last Modified dates are used for Last-Modified and Etag headers which are used by the server to tell the browser if it can use the file already stored in the cache or needs to download the file again. They are also used by Rails for generating cache-busters – the query parameter it adds to images, javascript, and css. Cache-busters allow you to set Expires headers far in the future for files that don’t change often without worrying that you won’t be able to to update them should they change.
Expires headers are crucial since they allow the browser to use files in the cache without even asking the server if the files are still current (like it does with Last-Modified or ETag headers). Their importance is clear with Rails enabling cache-busters by default even though Expires headers require server configuration and won’t be enabled by many users. Rails cache-busters carry a decent performance hit since they must access the file system to get the modified date, but are still enabled by default since making setting Expires headers easier is deemed worth it.
But many default deployment processes will result in Last Modified dates being updated for unchanged files which means that users’ browser have to reload all static assets after every deploy significantly reducing the benefit of Expires headers as well as Last-Modified and Etag headers
Cause: Commands like cp, checkout, and clone Modify Dates
Odds are that your deployment process copies files or uses git clone
or svn checkout
. If it does, modified dates of all files will be updated.
cp
offers options to retain modified dates. From everything I could find, SVN does not store modified dates in the repository and so there is no simple way of maintaining dates after you commit. Git seems to retain modified dates and this was the reason we switched to it, hoping this would solve this problem. While it may retain the dates, it did not solve the problem, since git clone sets new file dates. There may be a way to configure git clone to not overwrite the modified dates, but I didn’t find it before finding another solution.
Solution: Use :deploy_via, :remote_cache and set :normalize_asset_timestamps, false
In Capistrano we originally used :deploy_via, :checkout
. With :remote_cache
, Capistrano loads the latest version into a shared/cached-copy directory and fetches only the updates which allows the dates of unmodified files to remain on subsequent deploys. :remote_cache
definitely works with Git and will probably work with SVN.
You may still have a problem since Capistrano may set all the dates for you. To make sure this doesn’t happen set :normalize_asset_timestamps, false
in your deploy file.
No Responses to “Keep Last Modified Dates with Capistrano Deploy and SVN/Git”
Trackbacks/Pingbacks
- Months of Frustration or How BoxCycle Got a Speed Boost | BoxCycle Blog - [...] Modified deployment so last modified dates are only updated on changed files [...]