Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implement Capistrano tasks

  • Loading branch information...
commit 0a2c8b5b5a94be5bbcde0579d39c745b4ecf64c5 1 parent 34dbb49
@lautis lautis authored
View
1  .gitignore
@@ -11,6 +11,7 @@ doc
# bundler
.bundle
+Gemfile.lock
# jeweler generated
pkg
View
21 Gemfile
@@ -1,15 +1,12 @@
-source "http://rubygems.org"
-# Add dependencies required to use your gem here.
-# Example:
-# gem "activesupport", ">= 2.3.5"
+source 'http://rubygems.org'
+
+gem 'term-ansicolor'
+gem 'capistrano', '>= 2.11'
-# Add dependencies to develop your gem here.
-# Include everything needed to run rake, tests, features, etc.
group :development do
- gem "rspec", "~> 2.8.0"
- gem "yard", "~> 0.7"
- gem "rdoc", "~> 3.12"
- gem "bundler", "~> 1.0.0"
- gem "jeweler", "~> 1.8.3"
- gem "rcov", ">= 0"
+ gem 'rspec', '~> 2.8.0'
+ gem 'yard', '~> 0.7'
+ gem 'rdoc', '~> 3.12'
+ gem 'bundler', '~> 1.1'
+ gem 'jeweler', '~> 1.8.3'
end
View
2  LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2012 Ville Lautanala
+Copyright (c) 2012 Flowdock Ltd.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
View
19 README.rdoc
@@ -1,19 +0,0 @@
-= capistrano-node
-
-Description goes here.
-
-== Contributing to capistrano-node
-
-* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
-* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
-* Fork the project.
-* Start a feature/bugfix branch.
-* Commit and push until you are happy with your contribution.
-* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
-* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
-
-== Copyright
-
-Copyright (c) 2012 Ville Lautanala. See LICENSE.txt for
-further details.
-
View
7 Rakefile
@@ -15,7 +15,7 @@ require 'jeweler'
Jeweler::Tasks.new do |gem|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
gem.name = "capistrano-node"
- gem.homepage = "http://github.com/lautis/capistrano-node"
+ gem.homepage = "https://github.com/flowdock/capistrano-node"
gem.license = "MIT"
gem.summary = %Q{Capistrano scripts for Node deployment}
gem.description = %Q{TODO: longer description of your gem}
@@ -31,11 +31,6 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
end
-RSpec::Core::RakeTask.new(:rcov) do |spec|
- spec.pattern = 'spec/**/*_spec.rb'
- spec.rcov = true
-end
-
task :default => :spec
require 'yard'
View
27 Readme.md
@@ -0,0 +1,27 @@
+# capistrano-node
+
+Capistrano tasks for deploying Node projects.
+
+## What does it do?
+
+* Skips migrations
+* Installs NPM packages on deploy
+* Manages multiple node versions
+
+## Usage
+
+In your deploy.rb
+
+```ruby
+
+require 'capistrano/node'
+
+set :multi_node, true # To use multiple node versions
+set :node_dir, '/opt/nodejs/versions' # Node dirs
+set :version_prefix, 'v'
+```
+
+## Copyright
+
+Copyright (c) 2012 Flowdock Ltd. See LICENSE.txt for
+further details.
View
1  VERSION
@@ -0,0 +1 @@
+0.0.0
View
68 capistrano-node.gemspec
@@ -0,0 +1,68 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = "capistrano-node"
+ s.version = "0.0.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Ville Lautanala"]
+ s.date = "2012-03-26"
+ s.description = "TODO: longer description of your gem"
+ s.email = "lautis@gmail.com"
+ s.extra_rdoc_files = [
+ "LICENSE.txt"
+ ]
+ s.files = [
+ ".document",
+ ".rspec",
+ "Gemfile",
+ "LICENSE.txt",
+ "Rakefile",
+ "Readme.md",
+ "VERSION",
+ "capistrano-node.gemspec",
+ "lib/capistrano-node.rb",
+ "lib/capistrano/node.rb",
+ "spec/capistrano-node_spec.rb",
+ "spec/spec_helper.rb"
+ ]
+ s.homepage = "https://github.com/flowdock/capistrano-node"
+ s.licenses = ["MIT"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = "1.8.11"
+ s.summary = "Capistrano scripts for Node deployment"
+
+ if s.respond_to? :specification_version then
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q<term-ansicolor>, [">= 0"])
+ s.add_runtime_dependency(%q<capistrano>, [">= 2.11"])
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
+ s.add_development_dependency(%q<yard>, ["~> 0.7"])
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
+ s.add_development_dependency(%q<bundler>, ["~> 1.1"])
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
+ else
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
+ s.add_dependency(%q<capistrano>, [">= 2.11"])
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
+ s.add_dependency(%q<yard>, ["~> 0.7"])
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
+ s.add_dependency(%q<bundler>, ["~> 1.1"])
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
+ end
+ else
+ s.add_dependency(%q<term-ansicolor>, [">= 0"])
+ s.add_dependency(%q<capistrano>, [">= 2.11"])
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
+ s.add_dependency(%q<yard>, ["~> 0.7"])
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
+ s.add_dependency(%q<bundler>, ["~> 1.1"])
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
+ end
+end
+
View
42 lib/capistrano-node.rb
@@ -0,0 +1,42 @@
+require 'json'
+
+module Capistrano
+ module Node
+ extend self
+ # Internal: Parse node version from string
+ #
+ # string - version string
+ # prefix - prefix used in node versions, e.g. 'v', (default: '')
+ #
+ # Returns Gem::Version object
+ def version(string, prefix = '')
+ Gem::Version.create(string[prefix.length..-1])
+ end
+
+ # Internal: Choose best matching version for given requirement
+ #
+ # requirement - Gem::Requirement object
+ # versions - Array of Gem::Versions
+ #
+ # Returns latest matching version
+ def choose_version(requirement, versions = [])
+ versions.sort.reduce(nil) do |used, candidate|
+ if requirement.satisfied_by? candidate
+ candidate
+ else
+ used
+ end
+ end
+ end
+
+ # Internal: Parse requirement from package.json
+ #
+ # file - package.json file object
+ #
+ # Returns Gem::Requirement
+ def requirement(file)
+ json = JSON.parse(File.open('package.json', 'r:utf-8').read)
+ Gem::Requirement.create(json['engines']['node'])
+ end
+ end
+end
View
82 lib/capistrano/node.rb
@@ -0,0 +1,82 @@
+require 'capistrano-node'
+require 'term/ansicolor'
+include Term::ANSIColor
+
+def local_versions(path, prefix)
+ Dir.entries(path).select do |n|
+ n[0] != '.'
+ end.map do |ver|
+ Capistrano::Node.version ver, prefix
+ end
+end
+
+def remote_versions(path, prefix)
+ capture("ls #{path}").chomp.split("\n").map do |ver|
+ Capistrano::Node.version ver, prefix
+ end
+end
+
+Capistrano::Configuration.instance(:must_exist).load do |configuration|
+ after :'deploy:finalize_update', :'deploy:symlink_node'
+ after :'deploy:update_code', :'deploy:npm'
+
+ set :multi_node, false unless defined? multi_node
+ set :local, false unless defined? local
+ set :node_dir, '/opt/nodejs/versions' unless defined? node_dir
+ set :version_prefix, 'v' unless defined? version_prefix
+ set :available_node_versions do
+ if local
+ local_versions node_dir, version_prefix
+ else
+ remote_versions node_dir, version_prefix
+ end.sort
+ end
+
+ set :node_version do
+ requirement = Capistrano::Node.requirement 'package.json'
+ Capistrano::Node.choose_version requirement, available_node_versions
+ end
+
+ namespace :node do
+ desc 'List available node versions'
+ task :versions do
+ puts available_node_versions
+ end
+
+ desc 'Used Node version'
+ task :used do
+ if node_version
+ puts node_version
+ else
+ puts red('No suitable node version found')
+ end
+ end
+ end
+
+ namespace :deploy do
+ task :migrate do
+ # Skip migrations
+ end
+
+ desc 'Symlink node version'
+ task :symlink_node do
+ return unless multi_node
+
+ unless node_version
+ puts red('No suitable node version found')
+ exit
+ end
+
+ if local
+ run_locally "ln -snf #{node_dir}/#{version_prefix}#{node_version}/bin bin"
+ else
+ run "ln -snf #{node_dir}/#{version_prefix}#{node_version}/bin #{release_path}/bin"
+ end
+ end
+
+ desc 'Build NPM packages'
+ task :npm do
+ run "export PATH=#{release_path}/bin:$PATH && cd #{release_path} && npm install && npm rebuild"
+ end
+ end
+end
View
46 spec/capistrano-node_spec.rb
@@ -1,7 +1,47 @@
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+require 'tempfile'
-describe "CapistranoNode" do
- it "fails" do
- fail "hey buddy, you should probably rename this file and start specing for real"
+describe 'Capistrano::Node' do
+ describe '.version' do
+ it 'parses version' do
+ Capistrano::Node.version('0.6.11').should == Gem::Version.new('0.6.11')
+ end
+
+ it 'ignores prefix' do
+ Capistrano::Node.version('v0.4.3', 'v').should == Gem::Version.new('0.4.3')
+ end
+ end
+
+ describe '.choose_version' do
+ before :each do
+ @versions = [
+ Gem::Version.new('0.6.3'),
+ Gem::Version.new('0.6.4'),
+ Gem::Version.new('0.4.2')
+ ]
+ end
+ it 'chooses the matching version' do
+ requirement = Gem::Requirement.create('0.6.3')
+ Capistrano::Node.choose_version(requirement, @versions).to_s.should == '0.6.3'
+ end
+
+ it 'prefers newest version' do
+ requirement = Gem::Requirement.create('~>0.6.3')
+ Capistrano::Node.choose_version(requirement, @versions).to_s.should == '0.6.4'
+ end
+
+ it 'returns nil if no version matches to requirement' do
+ requirement = Gem::Requirement.create('~>0.4.3')
+ Capistrano::Node.choose_version(requirement, @versions).should be_nil
+ end
+ end
+
+ describe '.requirement' do
+ it 'parses node requirement from package.json file' do
+ Tempfile.new('package.json') do |t|
+ t.write('{"node":{"version":">=0.6.11"}}')
+ Capistano::Node.requirement(t.path).should == Gem::Requirement.create(">=0.6.11")
+ end
+ end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.