<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>Future Adapter</title>
	<atom:link href="http://futureadapter.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://futureadapter.com</link>
	<description>Cool Tech</description>
	<pubDate>Mon, 05 Jan 2009 23:57:04 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Working with large (thus slow) assets</title>
		<link>http://futureadapter.com/2009/01/05/working-with-large-thus-slow-assets/</link>
		<comments>http://futureadapter.com/2009/01/05/working-with-large-thus-slow-assets/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 23:57:04 +0000</pubDate>
		<dc:creator>mattenat</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<category><![CDATA[capistrano]]></category>

		<category><![CDATA[deploys]]></category>

		<category><![CDATA[git]]></category>

		<category><![CDATA[images]]></category>

		<category><![CDATA[rails]]></category>

		<category><![CDATA[recipes]]></category>

		<guid isPermaLink="false">http://futureadapter.com/?p=43</guid>
		<description><![CDATA[You have a website with fantastic images that are big, plentiful, and full of color.  Like a fashion website, for example.  Or maybe you&#8217;ve decided that all the text on your website needs to be in a non-web font&#8211;as images&#8211;and now you have hundreds or thousands of image files to be deployed.
What to do so [...]]]></description>
			<content:encoded><![CDATA[<p>You have a website with fantastic images that are big, plentiful, and full of color.  Like a fashion website, for example.  Or maybe you&#8217;ve decided that all the text on your website needs to be in a non-web font&#8211;as images&#8211;and now you have hundreds or thousands of image files to be deployed.</p>
<p>What to do so as to avoid heinous deploy times robbing your project of momentum and preventing following the credo of good development, &#8220;release early, release often?&#8221;</p>
<p>Make a separate repo just for your assets.</p>
<p>To accomplish this, you need the repo, you need a cap recipe and callback-hook for doing these deployments on demand (you wouldn&#8217;t want to do them every time, or you&#8217;re defeating the whole point), and you need a couple symbolic links.</p>
<p><strong>STEP ONE: MAKE A REPO</strong></p>
<p>Just follow <a href="http://github.com/repositories/new" target="_blank">Github&#8217;s directions for starting a new repo</a>.  Once you&#8217;re all done, you&#8217;ll need to put your assets into the directory and make your first push.  Since there&#8217;s lots of these assets (that&#8217;s the whole reason you&#8217;re doing this project), it might take a while.</p>
<p><strong>STEP TWO: CAP RECIPE AND CALLBACK-HOOK</strong></p>
<p>For my project, and probably for yours, its important to keep separate asset repos for each environment, in the same way that you&#8217;d keep separate code repos for each environment.  Are you already using <a href="http://weblog.jamisbuck.org/2007/7/23/capistrano-multistage" target="_blank">capistrano multistage</a>?  I am, so these directions assume that piece.  But you should be able to figure it out if you&#8217;re not. </p>
<p>config/deploy/staging.rb:</p>
<pre>
set <span class="constant">:statics_deploy_to</span>, <span class="type">Proc</span>.new { <span class="string">"#{deploy_to}/statics-staging"</span> }
</pre>
<p>config/deploy/production.rb:</p>
<pre>
set <span class="constant">:statics_deploy_to</span>, <span class="type">Proc</span>.new { <span class="string">"#{deploy_to}/statics-production"</span> }
</pre>
<p>Some thought went into the placement of the directory.  Should it mimic the releases structure of a normal rails deployment?  I decided that for my purposes it made the most sense to have a directory which didn&#8217;t change with releases such that updates could literally be git pulls instead of whole new clones.  Since the file sizes are so large, I do want to avoid doing a complete deployment as much as possible.</p>
<p>And now your special recipe &#8230; of note here, the command variable inspiration was from the update_repository_cache method in capistrano&#8217;s recipes/deploy/strategy/remote_cache.rb and the run block was stolen from scm_run in capistrano&#8217;s recipes/deploy/strategy/remote.rb.  I tried to use a slightly more abstracted API, Strategy, instead of using the Git scm API directly, but couldn&#8217;t get things to work (and since this already did, I didn&#8217;t try too hard).</p>
<p>lib/recipes/statics.rb:</p>
<pre>
set <span class="constant">:statics_symlink_target</span>, <span class="type">Proc</span>.new { <span class="string">"</span><span class="variable-name">#{current_path}</span><span class="string">/public/images"</span> }
set <span class="constant">:statics_repository</span>, <span class="type">Proc</span>.new { <span class="string">"git@github.com:USERNAMEHERE/PROJECTNAMEHERE-statics.git"</span> }
set <span class="constant">:statics_branch</span>, <span class="string">'master'</span>

after <span class="string">'deploy:symlink'</span>, <span class="string">'statics:symlink'</span>

namespace <span class="constant">:statics</span> <span class="keyword">do</span>
  desc <span class="string">"Deploy the statics"</span>
  task <span class="constant">:deploy</span> <span class="keyword">do</span>
    gitter =
      <span class="type">Capistrano</span>::<span class="type">Deploy</span>::<span class="type">SCM</span>::<span class="type">Git</span>.new(<span class="constant">:repository</span> =&gt; statics_repository,
                                       <span class="constant">:branch</span> =&gt; statics_branch)

    <span class="comment-delimiter"># </span><span class="comment">figure out the latest version of the code
</span>    revision =
      gitter.query_revision(statics_branch) { |cmd| run_locally(cmd) }

    <span class="comment-delimiter"># </span><span class="comment">clone or fetch depending on what we're up to
</span>    command = <span class="string">"if [ -d </span><span class="variable-name">#{statics_deploy_to}</span><span class="string"> ]; then "</span> +
      <span class="string">"</span><span class="variable-name">#{gitter.sync(revision, statics_deploy_to)}</span><span class="string">; "</span> +
      <span class="string">"else </span><span class="variable-name">#{gitter.checkout(revision, statics_deploy_to)}</span><span class="string">; fi"</span>

    run(command) <span class="keyword">do</span> |ch,stream,text|
      ch[<span class="constant">:state</span>] ||= { <span class="constant">:channel</span> =&gt; ch }
      output = gitter.handle_data(ch[<span class="constant">:state</span>], stream, text)
      ch.send_data(output) <span class="keyword">if</span> output
    <span class="keyword">end</span>
  <span class="keyword">end</span>

  desc <span class="string">"Dynamically link the statics into place"</span>
  task <span class="constant">:symlink</span> <span class="keyword">do</span>
    run <span class="string">"ln -nfs </span><span class="variable-name">#{statics_deploy_to}</span><span class="string"> </span><span class="variable-name">#{statics_symlink_target}</span><span class="string">"</span>
  <span class="keyword">end</span>
<span class="keyword">end</span>
</pre>
<p><strong>STEP THREE: SYMBOLIC LINKS<br />
</strong></p>
<p>There&#8217;s already a symbolic link that automatically gets made on the server when you deploy to connect your static assets to your code.  But you have to do one locally, too.  I&#8217;ll leave that as an exercise for the reader (hint, its pretty much the exact same ln -nfs line that&#8217;s in the recipe).</p>
<p><strong>AND FINALLY<br />
</strong></p>
<pre>
<span class="string">future-book:~/Sites/clientservice matt$ </span>cap production statics:deploy deploy
</pre>
<p><strong>GOTCHA</strong>: Github only allows one deploy key per-repo and now the same account on your hosting server needs to access two repos.  My approach was to setup the deploy key connected to the account of the repo owner, not the actual repo itself.  <a href="http://github.com/guides/multiple-github-accounts" target="_blank">Multiple Github Accounts</a> is another approach.</p>
]]></content:encoded>
			<wfw:commentRss>http://futureadapter.com/2009/01/05/working-with-large-thus-slow-assets/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
