capistrano-calendar 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ .credentials.yml
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.8.7
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'json', '1.6.1'
6
+ gem 'gdata', '1.1.2'
7
+ gem 'daemons', '1.1.4'
8
+
9
+
10
+ gem 'rspec', '2.6.0'
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ capistrano-calendar (0.0.1)
5
+ capistrano (>= 2.5.5)
6
+ gdata (>= 1.1.0)
7
+ json
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ capistrano (2.9.0)
13
+ highline
14
+ net-scp (>= 1.0.0)
15
+ net-sftp (>= 2.0.0)
16
+ net-ssh (>= 2.0.14)
17
+ net-ssh-gateway (>= 1.1.0)
18
+ daemons (1.1.4)
19
+ diff-lcs (1.1.2)
20
+ gdata (1.1.2)
21
+ highline (1.6.2)
22
+ json (1.6.1)
23
+ net-scp (1.0.4)
24
+ net-ssh (>= 1.99.1)
25
+ net-sftp (2.0.5)
26
+ net-ssh (>= 2.0.9)
27
+ net-ssh (2.2.1)
28
+ net-ssh-gateway (1.1.0)
29
+ net-ssh (>= 1.99.1)
30
+ rspec (2.6.0)
31
+ rspec-core (~> 2.6.0)
32
+ rspec-expectations (~> 2.6.0)
33
+ rspec-mocks (~> 2.6.0)
34
+ rspec-core (2.6.4)
35
+ rspec-expectations (2.6.0)
36
+ diff-lcs (~> 1.1.2)
37
+ rspec-mocks (2.6.0)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ capistrano-calendar!
44
+ daemons (= 1.1.4)
45
+ gdata (= 1.1.2)
46
+ json (= 1.6.1)
47
+ rspec (= 2.6.0)
@@ -0,0 +1,91 @@
1
+ # Capistrano Calendar
2
+
3
+ ## Introduction
4
+
5
+ capistrano-calendar is extension for capistrano that allows your create different deployment notification in calendar service. Currently supported services:
6
+
7
+ * google calendar
8
+
9
+ ## Installation
10
+
11
+ gem install capistrano-calendar
12
+
13
+ Add to your Capfile
14
+
15
+ require 'capistrano/calendar/recipes'
16
+
17
+ ## How it works
18
+
19
+ This gem provides:
20
+
21
+ * capistrano recipe *calendar:create_event*
22
+ * ruby binary script *capistrano-calendar*
23
+
24
+ Capistrano recipe should be used in some :after hooks (e.g. after deploy). Recipe reads calendar configurations and run capistrano-calendar binary on some host specified in *capistrano_runner* option. So you **need to install** *capistrano-calendar* gem also on that calendar host. Also please ensure that you properly configured calendar_runner otherwise you may have **duplicated events** in calender.
25
+
26
+ ## Calendar configuration
27
+
28
+ * *:calendar_service* (:google) - calendar service to use e.g. ':google'
29
+ * **:calendar_username** (nil) - calendar service username e.g 'vasya.pupkin@gmail.com'
30
+ * **:calendar_password** (nil) - calendar service password e.g 'qwery123456'
31
+ * *:calendar_name* (default) - calendar name to use for events
32
+ * *:calendar_summary* (nil) - calendar summary for new calendar
33
+ * *:calendar_location* (nil) - calendar location for new calendar
34
+ * *:calendar_timezone* ('UTC') - calendar timezone for new calendar
35
+ * *:calendar_color* ('#A32929') - calendar color for new calendar
36
+ * **:calendar_event_name** (nil) - calendar event name
37
+ * *:calendar_event_summary* (nil) - calendar event summary
38
+ * *:calendar_event_location* (nil) - calendar event location
39
+ * *:calendar_event_time* (Time.now) - calendar event time
40
+ * *:calendar_event_status* ('confirmed') - calendar event status
41
+
42
+ Bold means required options. Value in brackets means default value.
43
+
44
+ ## Calendar runner configuration
45
+
46
+ Calendar event creation will be executed by default on the one of application servers (specified in :app roles)
47
+ You can change this behavior via *calendar_runner* option. Examples:
48
+
49
+ set(:calendar_runner, { :roles => :calendar_notifier, :once => true )
50
+ # or
51
+ set(:calendar_runner, { :hosts => 'notification.example.com' })
52
+
53
+ Be sure to pass `:once => true` option if you use *:roles* !
54
+
55
+ ## Configuration example
56
+
57
+ set :calendar_service, :google
58
+ set :calendar_username, 'vasya.pupkin@my.company.com'
59
+ set :calendar_password, '123456'
60
+
61
+ set :calendar_name { stage }
62
+ set :calendar_summary { "" }
63
+ set :calendar_timezone, 'UTC'
64
+ set :calendar_color, { stage == 'production' ? '#ff000' : '#00ff00' }
65
+
66
+ set :calendar_event_summary { "Bla" }
67
+ set :calendar_event_time { Time.now }
68
+
69
+ after 'deploy' do
70
+ set :calendar_event_title "[Deployed] #{application} #{branch}: #{real_revision}"
71
+ top.calendar.create_event
72
+ end
73
+
74
+ after 'deploy:rollback' do
75
+ set :calendar_event_title "[Rollback] #{application} #{branch}: #{real_revision}"
76
+ top.calendar.create_event
77
+ end
78
+
79
+ #
80
+ # Extra configurations if you are using capistrano-patch:
81
+ #
82
+ after 'patch:apply' do
83
+ set :calendar_event_title "[Pathed] #{application} #{branch}: #{patch_strategy.revision_to}"
84
+ calendar_client.create_event
85
+ end
86
+
87
+ after 'patch:revert' do
88
+ set :calendar_event_title "[Patch rollback] #{application} #{branch}: #{patch_strategy.revision_from}"
89
+ top.calendar.create_event
90
+ end
91
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'capistrano/calendar'
4
+
5
+ Capistrano::Calendar::Runner.new(ARGV).run!
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require "capistrano/calendar/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "capistrano-calendar"
8
+ s.version = Capistrano::Calendar::VERSION
9
+ s.authors = ["Andriy Yanko"]
10
+ s.email = ["andriy.yanko@gmail.com"]
11
+ s.homepage = "https://github.com/railsware/capistrano-calendar/"
12
+ s.summary = %q{Deployment event creation on (google) calendar service}
13
+
14
+ s.rubyforge_project = "capistrano-calendar"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency "capistrano", ">=2.5.5"
22
+ s.add_runtime_dependency "gdata", ">=1.1.0"
23
+ s.add_runtime_dependency "json"
24
+ end
@@ -0,0 +1,7 @@
1
+ module Capistrano
2
+ module Calendar
3
+ autoload :Client, 'capistrano/calendar/client'
4
+ autoload :Configuration, 'capistrano/calendar/configuration'
5
+ autoload :Runner, 'capistrano/calendar/runner'
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ require 'capistrano/errors'
2
+
3
+ module Capistrano
4
+ module Calendar
5
+ module Client
6
+ def self.new(config)
7
+ name = config[:calendar_service] || :google
8
+
9
+ require "capistrano/calendar/client/#{name}"
10
+
11
+ client_const = name.to_s.capitalize.gsub(/_(.)/) { $1.upcase }
12
+
13
+ const_get(client_const).new(config)
14
+
15
+ rescue LoadError
16
+ raise Capistrano::Error, "could not find any client named '#{name}'"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ module Capistrano
2
+ module Calendar
3
+ module Client
4
+ class Base
5
+ def initialize(config)
6
+ @configuration = config
7
+ end
8
+
9
+ attr_reader :configuration
10
+
11
+ def calendar_username
12
+ configuration.fetch(:calendar_username)
13
+ end
14
+
15
+ def calendar_password
16
+ configuration.fetch(:calendar_password)
17
+ end
18
+
19
+ def authenticate
20
+ raise NotImplementedError, "`authenticate' is not implemented by #{self.class.name}"
21
+ end
22
+
23
+ def create_event
24
+ raise NotImplementedError, "`create_event' is not implemented by #{self.class.name}"
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,105 @@
1
+ require 'capistrano/calendar/client/base'
2
+
3
+ require 'gdata'
4
+ require 'json'
5
+ require 'time'
6
+
7
+ module Capistrano
8
+ module Calendar
9
+ module Client
10
+ class Google < Base
11
+
12
+ #
13
+ # http://code.google.com/apis/calendar/data/2.0/developers_guide_protocol.html
14
+ #
15
+
16
+ OWN_CALENDARS_URL = "https://www.google.com/calendar/feeds/default/owncalendars/full"
17
+ CALENDAR_EVENTS_URL = "https://www.google.com/calendar/feeds/default/private/full"
18
+
19
+ def authenticate
20
+ client.clientlogin(calendar_username, calendar_password)
21
+ end
22
+
23
+ def create_event
24
+ response = client.post(events_url, json_event_entity)
25
+ JSON.parse(response.body)['data']
26
+ end
27
+
28
+ def events_url
29
+ if configuration[:calendar_name]
30
+ calendar = find_or_create_calendar(configuration[:calendar_name])
31
+ calendar['eventFeedLink']
32
+ else
33
+ CALENDAR_EVENTS_URL
34
+ end
35
+ end
36
+
37
+ def find_or_create_calendar(calendar_name)
38
+ find_calendar(calendar_name) || create_calendar(calendar_name)
39
+ end
40
+
41
+ def find_calendar(calendar_name)
42
+ response = client.get(OWN_CALENDARS_URL + '?alt=jsonc')
43
+ JSON.parse(response.body)['data']['items'].find { |item|
44
+ item['title'] == calendar_name
45
+ }
46
+ end
47
+
48
+ def create_calendar(calendar_name)
49
+ response = client.post(OWN_CALENDARS_URL, json_calendar_entity)
50
+ JSON.parse(response.body)['data']
51
+ end
52
+
53
+ def delete_calendar(calendar)
54
+ calendar.is_a?(Hash) or calendar = find_calendar(calendar)
55
+ calendar or raise Capistrano::Error, "Calendar #{calendar.inspect} not found"
56
+ client.delete(calendar['selfLink'])
57
+ end
58
+
59
+ protected
60
+
61
+ def client
62
+ @client ||= GData::Client::Calendar.new({
63
+ :headers => { 'Content-Type' => 'application/json' },
64
+ :source => 'capistrano-calendar'
65
+ })
66
+ end
67
+
68
+ def json_calendar_entity
69
+ data = {
70
+ 'title' => configuration.fetch(:calendar_name),
71
+ 'timeZone' => configuration.fetch(:calendar_timezone, 'UTC'),
72
+ 'color' => configuration.fetch(:calendar_color, '#A32929'),
73
+ 'hidden' => false
74
+ }
75
+
76
+ value = configuration[:calendar_summary] and data['details'] = value
77
+ value = configuration[:calendar_location] and data['location'] = value
78
+
79
+ { 'data' => data }.to_json
80
+ end
81
+
82
+ def json_event_entity
83
+ event_time = configuration.fetch(:calendar_event_time, Time.now).utc.xmlschema
84
+
85
+ data = {
86
+ 'title' => configuration.fetch(:calendar_event_name),
87
+ 'status' => configuration.fetch(:calendar_event_status, 'confirmed'),
88
+ 'when' => [
89
+ {
90
+ 'start' => event_time,
91
+ 'stop' => event_time
92
+ }
93
+ ]
94
+ }
95
+
96
+ value = configuration[:calendar_event_summary] and data['details'] = value
97
+ value = configuration[:calendar_event_location] and data['location'] = value
98
+
99
+ { 'data' => data }.to_json
100
+ end
101
+
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,41 @@
1
+ require 'yaml'
2
+ require 'base64'
3
+
4
+ module Capistrano
5
+ module Calendar
6
+ class Configuration
7
+
8
+ def self.collect(hash)
9
+ [
10
+ :calendar_service,
11
+ :calendar_username,
12
+ :calendar_password,
13
+
14
+ :calendar_name,
15
+ :calendar_summary,
16
+ :calendar_location,
17
+ :calendar_timezone,
18
+ :calendar_color,
19
+
20
+ :calendar_event_name,
21
+ :calendar_event_summary,
22
+ :calendar_event_location,
23
+ :calendar_event_time,
24
+ :calendar_event_status
25
+ ].inject({}) { |result, key|
26
+ result[key] = hash[key] if hash.exists?(key)
27
+ result
28
+ }
29
+ end
30
+
31
+ def self.encode(hash)
32
+ Base64.encode64(hash.to_yaml).gsub("\n", '')
33
+ end
34
+
35
+ def self.decode(string)
36
+ YAML.load(Base64.decode64(string))
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ require 'capistrano/calendar'
2
+
3
+ Capistrano::Configuration.instance.load do
4
+
5
+ set(:calendar_runner) do
6
+ {
7
+ :roles => :app,
8
+ :once => true
9
+ }
10
+ end
11
+
12
+ namespace :calendar do
13
+ desc "Create calendar event"
14
+ task :create_event do
15
+ configuration = Capistrano::Calendar::Configuration.collect(self)
16
+ string = Capistrano::Calendar::Configuration.encode(configuration)
17
+
18
+ run("capistrano-calendar create_event #{string}", calendar_runner)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,88 @@
1
+ require 'optparse'
2
+
3
+ module Capistrano
4
+ module Calendar
5
+ class Runner
6
+ def self.run(*args)
7
+ new(*args).run!
8
+ end
9
+
10
+ def initialize(argv)
11
+ @argv = argv
12
+ end
13
+
14
+ attr_reader :client
15
+
16
+ def run!
17
+ parser = OptionParser.new do |o|
18
+ o.banner = "Usage: capistrano-calendar [options] COMMAND [CONFIGURATION_DATA]"
19
+ o.separator ""
20
+ o.separator "Commands:"
21
+ o.separator ""
22
+ o.separator " create_event - create calendar event"
23
+ o.separator ""
24
+ o.separator "CONFIGURATION_DATA is base64 encoded yaml data"
25
+ o.separator ""
26
+ o.separator "Common options:"
27
+ o.on_tail("-h", "--help", "Show this message") { puts o; exit }
28
+ o.on_tail('-v', '--version', "Show version") { puts Capistrano::Calendar::VERSION; exit }
29
+ end
30
+
31
+ parser.parse!(@argv)
32
+
33
+ @command = @argv.shift
34
+ @configuration = @argv.shift
35
+
36
+ case @command
37
+ when 'create_event'
38
+ @configuration or abort(parser.help)
39
+ @configuration = Capistrano::Calendar::Configuration.decode(@configuration)
40
+ @configuration.is_a?(Hash) or abort("Bad configuration given")
41
+
42
+ @client = Capistrano::Calendar::Client.new(@configuration)
43
+
44
+ daemonize { create_event }
45
+ else
46
+ abort parser.help
47
+ end
48
+
49
+ end
50
+
51
+ protected
52
+
53
+ def create_event
54
+ client.authenticate
55
+ client.create_event
56
+ end
57
+
58
+ def daemonize
59
+ Process.fork do
60
+ # Detach the child process from the parent's session.
61
+ Process.setsid
62
+
63
+ # Re-fork. This is recommended for System V-based
64
+ # system as it guarantees that the daemon is not a
65
+ # session leader, which prevents it from aquiring
66
+ # a controlling terminal under the System V rules.
67
+ exit if fork
68
+
69
+ # Rename the process
70
+ $0 = "capistrano-calendar"
71
+
72
+ # Flush all buffers
73
+ $stdout.sync = $stderr.sync = true
74
+
75
+ # Set all standard files to `/dev/null/` in order
76
+ # to be sure that any output from the daemon will
77
+ # not appear in any terminals.
78
+ $stdin.reopen("/dev/null")
79
+ $stdout.reopen("/tmp/capistrano-calendar.stdout")
80
+ $stderr.reopen("/tmp/capistrano-calendar.stderr")
81
+
82
+ yield
83
+ end
84
+ end
85
+
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,5 @@
1
+ module Capistrano
2
+ module Calendar
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capistrano::Calendar::Client, "#create_event for google calendar" do
4
+
5
+ let(:configuration) do
6
+ {
7
+ :calendar_service => :google,
8
+ :calendar_username => Helper.credentials[:google][:username],
9
+ :calendar_password => Helper.credentials[:google][:password],
10
+ :calendar_name => "Capistrano Calendar",
11
+ :calendar_event_name => 'Test Deploy!'
12
+ }
13
+ end
14
+
15
+ let(:client) {
16
+ client = Capistrano::Calendar::Client.new(configuration)
17
+ client.authenticate
18
+ client
19
+ }
20
+
21
+ before(:each) do
22
+ sleep(1)
23
+ configuration[:calendar_name] << " #{Time.now.to_f}"
24
+ end
25
+
26
+ it "should create calendar and event" do
27
+ event = client.create_event
28
+
29
+ event.should be_kind_of(Hash)
30
+ event['title'].should == configuration[:calendar_event_name]
31
+
32
+ calendar = client.find_calendar(configuration[:calendar_name])
33
+ calendar.should be_kind_of(Hash)
34
+ calendar['title'].should == configuration[:calendar_name]
35
+ calendar['timeZone'].should == 'UTC'
36
+ end
37
+
38
+ context "when calendar exists" do
39
+ before(:each) do
40
+ @calendar = client.create_calendar(configuration[:calendar_name])
41
+ end
42
+
43
+ it "should create event and does NOT create another calendar" do
44
+ event = client.create_event
45
+
46
+ event.should be_kind_of(Hash)
47
+ event['title'].should == configuration[:calendar_event_name]
48
+
49
+ calendar = client.find_calendar(configuration[:calendar_name])
50
+ calendar.should be_kind_of(Hash)
51
+ calendar['id'].should == @calendar['id']
52
+ end
53
+ end
54
+
55
+ context "when calendar_name is nil" do
56
+ before(:each) do
57
+ configuration.delete(:calendar_name)
58
+ end
59
+
60
+ it "should create event in default calendar" do
61
+ event = client.create_event
62
+
63
+ event.should be_kind_of(Hash)
64
+ event['title'].should == configuration[:calendar_event_name]
65
+ event['selfLink'].should include(Capistrano::Calendar::Client::Google::CALENDAR_EVENTS_URL)
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,26 @@
1
+ require 'capistrano'
2
+ require 'capistrano/calendar/client'
3
+
4
+ require 'yaml'
5
+
6
+ module Helper
7
+ def self.load_credentials!
8
+ @credentials = YAML.load_file('.credentials.yml')
9
+ rescue Errno::ENOENT => e
10
+ puts "Put your credentials into '.credentials.yml'. Example:"
11
+ puts({
12
+ :google => {
13
+ :username => 'vasya.pukin@gmail.com',
14
+ :password => '123456'
15
+ }
16
+ }.to_yaml)
17
+
18
+ exit(1)
19
+ end
20
+
21
+ def self.credentials
22
+ @credentials
23
+ end
24
+ end
25
+
26
+ Helper.load_credentials!
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-calendar
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Andriy Yanko
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-26 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: capistrano
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 17
29
+ segments:
30
+ - 2
31
+ - 5
32
+ - 5
33
+ version: 2.5.5
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: gdata
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 19
45
+ segments:
46
+ - 1
47
+ - 1
48
+ - 0
49
+ version: 1.1.0
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: json
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ description:
67
+ email:
68
+ - andriy.yanko@gmail.com
69
+ executables:
70
+ - capistrano-calendar
71
+ extensions: []
72
+
73
+ extra_rdoc_files: []
74
+
75
+ files:
76
+ - .gitignore
77
+ - .rvmrc
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - README.md
81
+ - Rakefile
82
+ - bin/capistrano-calendar
83
+ - capistrano-calendar.gemspec
84
+ - lib/capistrano/calendar.rb
85
+ - lib/capistrano/calendar/client.rb
86
+ - lib/capistrano/calendar/client/base.rb
87
+ - lib/capistrano/calendar/client/google.rb
88
+ - lib/capistrano/calendar/configuration.rb
89
+ - lib/capistrano/calendar/recipes.rb
90
+ - lib/capistrano/calendar/runner.rb
91
+ - lib/capistrano/calendar/version.rb
92
+ - spec/google_calendar_spec.rb
93
+ - spec/spec_helper.rb
94
+ homepage: https://github.com/railsware/capistrano-calendar/
95
+ licenses: []
96
+
97
+ post_install_message:
98
+ rdoc_options: []
99
+
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 3
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ requirements: []
121
+
122
+ rubyforge_project: capistrano-calendar
123
+ rubygems_version: 1.8.6
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Deployment event creation on (google) calendar service
127
+ test_files:
128
+ - spec/google_calendar_spec.rb
129
+ - spec/spec_helper.rb