correct • elegant • free

Upgrading a Yesod scaffolded site

I haven't spent any time on this site for a very long time. First thing was to bring the Yesod code up to date. The site was built on yesod-0.10. Things have changed a little bit between then and now (yesod-1.2)!

I have developed an effective modus operandi for handling Yesod upgrades.

For a major upgrade like this, I have the following solution to cabal dependency hell:

for p in $(ghc-pkg --user list | sed 1d); do ghc-pkg unregister --force $p; done

In case it's not obvious, this clears out all my installed packages. That may sound ridiculous, but for my most complicated Yesod site (certainly not this one!) rebuilding all the dependencies takes 17 minutes, with no human intervention. Which would you rather do, have a coffee break or do battle with intertwining dependencies? (I'm aware that cabal now supports sandboxes, which would make this more sensible. I tend to have one user per yesod site, so there's little difference.)

So, with our slate cleaned, the first thing is to install yesod-bin. That sucks in many of the dependencies we'll end up needing for the site itself, of course, but the point is to run yesod init and build a virgin scaffolded site (I usually call mine foo), specifying the same database backend as the site.

The first thing to extract from foo is the list of dependencies for yesod. That can simply be copied and pasted into the site's .cabal file. Normally I won't have bothered version-pinning any extra dependencies that I may have added to the site, since the package is never going to be built anywhere else. This means that all the pinned dependencies are from the original scaffolding, so it's trivial to see what to replace.

Next, cabal install --only-dependencies should run without a hitch.

Finally, it's time to fire up yesod devel and deal with any errors. As far as the Yesod scaffolding is concerned, this will involve stitching in new or modified snippets of code from foo to the site. In many cases, this can be entire files, but Foundation.hs has usually had some local changes and it will be necessary to manually patch them in. I suspect this step could be more automated... in fact...

Wait! What I should be doing is keeping the branch that was the unmodified, freshly inited site on a branch; the site itself on a branch forked from that. Then, when I upgrade Yesod, I simply need to refresh the original branch, and rebase the site branch. Why did I never think of that before? I shall have to adopt this strategy immediately! [ ... time passes.... done! Now I'm just waiting for a change to Yesod scaffolding to see how well it works! ]

Of course, there will likely be other changes arising from library updates. For example, in the upgrade I just performed, getModificationTime has gone from a CalendarTime to a UTCTime (whew!). Such changes must be dealt with on case-by-case basis.

I hope you find this useful. To be honest, I largely wrote it to check that the RSS / Atom feed is still working correctly! But I'm glad I did, because otherwise I would never have hit on the (obvious in hindsight) idea of using rebase to track scaffolding changes automatically.