• Stars
    star
    100
  • Rank 328,536 (Top 7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 15 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Symlink to external dependencies, rather than bloating your repositories with them

Cached Externals¶ ↑

This Capistrano extension provides yet another way to manage your application’s external dependencies.

External dependencies are a necessary evil. If you’re doing Rails development, you’ll automatically be dependent on the Rails framework itself, at the very least, and you probably have a handful or two of plugins that you’re using as well. Traditionally, the solution to these has been to either install those dependencies globally (which breaks down when you have multiple apps that need different versions of Rails or the plugins), or to bundle them into your application directly via freeze:gems or the like (which tends to bloat your repository).

Now, bloating a repository is, in itself, not a big deal. However, when it comes time to deploy your application, more data in the repository means more data to check out, resulting in longer deploy times. Some deployment strategies (like remote_cache) can help, but you’re still going to be copying all of that data every time you deploy your application.

One solution is to use a deployment strategy like FastRemoteCache (github.com/37signals/fast_remote_cache), which employs hard-links instead of copying files. But your deploys will go _even faster_ if you didn’t have to worry about moving or linking all the files in your external dependencies.

That’s where this Cached Externals plugin comes in. It capitalizes on one key concept: your external dependencies are unlikely to change frequently. Because they don’t change frequently, it makes more sense to just check them out once, and simply refer to that checkout via symlinks.

This means your deploys only have to add a single symbolic link for each external dependency, which can mean orders of magnitude less work for a deploy to do.

Dependencies¶ ↑

Assumptions¶ ↑

The Cached Externals plugin assumes that your external dependencies are either a gem, or under version control somewhere, and the gem sources and repositories are accessible both locally and from your deployment targets.

Usage¶ ↑

When using this with Rails applications, all you need to do is install this as a plugin in your application. Make sure your Capfile has a line like the following:

Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) }

It should be just before the line that loads the ‘config/deploy’ file. If that line is not there, add it (or rerun “capify .”).

If you are not using this with a Rails application, you’ll need to explicitly load recipes/cached_externals.rb in your Capfile.

Next, tell Capistrano about your external dependencies. This is done via a YAML file: config/externals.yml. It describes a hash of path names that describe the external repository. For example:

---
vendor/rails:
  :type: git
  :repository: git://github.com/rails/rails.git
  :revision: f2d8d13c6495f2a9b3bbf3b50d869c0e5b25c207
vendor/plugins/exception_notification:
  :type: git
  :repository: git://github.com/rails/exception_notification.git
  :revision: ed0b914ff493f9137abc4f68ee08e3c3cd7a3211
vendor/libs/tzinfo:
  :type: gem
  :version: 0.3.18

Specify as many as you like. Although it is best to specify an exact revision, you can also give any revision identifier that capistrano understands (git branches, HEAD, etc.). If you do, though, Capistrano will have to resolve those pseudo-revision identifiers every time, which can slow things down a little.

Once you’ve got your externals.yml in place, you’ll need to clear away the cruft. For example, if you were going to put vendor/rails as a cached external dependency, you’d need to first remove vendor/rails from your working copy. After clearing away all of the in-repository copies of your external dependencies, you just tell capistrano to load up the cached copies:

cap local externals:setup

That will cause Capistrano to read your externals.yml, checkout your dependencies, and create symlinks to them. When run locally like that, the dependencies will be checked out to ../shared/externals (e.g., up a directory from your project root).

Any time you update your config/externals.yml, you’ll need to rerun that command. If an external hasn’t changed revision, Capistrano will notice that and will not check it out again–only those that have changed will be updated.

When you deploy your application, these externals will be checked out into #{shared_path}/externals, and again, nothing will be checked out if the dependency’s revision matches what has already been cached.

Tips¶ ↑

For the fastest possible deploys, always give an exact revision identifier. This way, Capistrano may not have to query the dependency’s repository at all, if nothing has changed.

Also, if you’re using git, it can be a pain to change branches with this plugin, because different branches may have different dependencies, or (even worse) the same dependency but at different revisions. This plugin provides a Rake task, “git:hooks:install”, that installs a couple of git hook scripts: post-checkout and post-merge. (If you already have scripts defined for those, back them up before running this task, because they’ll get clobbered!) These hooks will then make it so that any time you switch branches, or do a “git pull” or “git merge”, the “cap local externals:setup” task will also get run, keeping your external dependencies in sync.

License¶ ↑

This code is released under the MIT license, and is copyright © 2008 by 37signals, LLC. Please see the accompanying LICENSE file for the full text of the license.

More Repositories

1

trix

A rich text editor for everyday writing
JavaScript
17,847
star
2

kamal

Deploy web apps anywhere.
Ruby
8,744
star
3

handbook

Basecamp Employee Handbook
6,165
star
4

pow

Zero-configuration Rack server for Mac OS X
CoffeeScript
3,423
star
5

policies

37signals policies, terms, and legal. Share them; reuse them; contribute to them.
1,863
star
6

local_time

Rails engine for cache-friendly, client-side local time
CoffeeScript
1,791
star
7

marginalia

Attach comments to ActiveRecord's SQL queries
Ruby
1,676
star
8

mail_view

Visual email testing
Ruby
1,341
star
9

xip-pdns

PowerDNS pipe backend adapter powering xip.io
Shell
1,159
star
10

geared_pagination

Paginate Active Record sets at variable speeds
Ruby
758
star
11

wysihat

A WYSIWYG JavaScript framework
JavaScript
681
star
12

bcx-api

API documentation and wrappers for Basecamp 2
672
star
13

name_of_person

Presenting names of people in full, familiar, abbreviated, and initialized forms (but without titulation etc)
Ruby
647
star
14

console1984

The Rails console you love, 1984 style
Ruby
548
star
15

google_sign_in

Sign in (or up) with Google for Rails applications
Ruby
494
star
16

bc3-api

API documentation for Basecamp 4
472
star
17

intermission

intermission helps you perform zero down time application maintenance
Lua
364
star
18

snapback_cache

A client side page cache for jquery.
JavaScript
316
star
19

audits1984

Auditing tool for Rails console sessions
Ruby
309
star
20

full_request_logger

Make full request logs accessible via web UI
Ruby
305
star
21

mysql_role_swap

(Nearly) Zero interruption mysql maintenance script.
Ruby
282
star
22

mission_control-jobs

Dashboard and Active Job extensions to operate and troubleshoot background jobs
Ruby
270
star
23

concerning

Bite-sized separation of concerns
Ruby
201
star
24

api

API integration and more for Basecamp products (Basecamp, Highrise, Campfire, Backpack)
192
star
25

easymon

Easy Monitoring
Ruby
191
star
26

trashed

Tell StatsD about request time, GC, objects and more. Latest Rails 4 and Ruby 2.1 support, and ancient Rails 2 and Ruby 1.8 support.
Ruby
189
star
27

highrise-api

Official API documentation for Highrise
130
star
28

fast_remote_cache

A faster version of Capistrano's remote_cache deployment strategy
Ruby
125
star
29

mass_encryption

Ruby
104
star
30

platform_agent

Parse user agent to deduce the platform
Ruby
103
star
31

campfire-api

Official API documentation for Campfire
97
star
32

basecamp-classic-api

Official API documentation for Basecamp Classic
87
star
33

lufo

Tracks the most recent options chosen on a `<select>` element and displays them at the top of the list
JavaScript
87
star
34

powprox

Pow .dev sites, meet SSL and HTTP/2
Shell
83
star
35

libmemcached_store

ActiveSupport::Cache wrapper for libmemcached
Ruby
81
star
36

action_profiler

Profile Rails requests on a live app
Ruby
75
star
37

bc3-integrations

Ruby
73
star
38

project_search

Rails plugin that adds a script/find command for searching your project
Ruby
71
star
39

activestorage-office-previewer

Active Storage previewer for Microsoft Office files based on LibreOffice
Ruby
67
star
40

dumpsterfire-2020

Code that runs the dumpster
HTML
47
star
41

turbo-8-morphing-demo

Ruby
43
star
42

cognition

Match text; run commands. Works great for building a chatbot!
Ruby
37
star
43

snapshot

A rails plugin that provides tasks for creating and restoring snapshots of development data.
Ruby
34
star
44

backpack-api

Official API documentation for Backpack
Ruby
20
star
45

ruby-dev

Old Rubies on new Macs
15
star
46

orc

Orc(hestrator) - A really bad pow.cx clone for linux
Shell
10
star
47

cleversafe

Ruby
7
star
48

memcached_bench

Ruby
6
star
49

duo-api

Ruby Gem for communicating with the Duo Api
Ruby
6
star
50

accessibility

Guidelines and tools we use at 37signals to make sure our apps are accessible
5
star
51

Xamarin.iOS.OnePasswordExtension

1Password bindings for Xamarin.iOS
C#
5
star
52

mail

Ruby
4
star
53

composed_of_ipaddr

Compact IPv4 attributes for Active Record. Presents an unsigned int (4 bytes) as an IPAddr.
Ruby
4
star
54

house-style

37signals house style
Ruby
3
star
55

deep_hash_transform

Re-key a nested Hash to all-Symbol or -String keys. Rails 4+ backport.
Ruby
3
star
56

github-issues

Github Issue query CLI
Go
2
star
57

homebrew-dev

Old software to build old stuff on new Macs
Ruby
1
star
58

nsone

A stupid simple API client for NS1
Ruby
1
star