designshell 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +18 -0
  2. data/.idea/.name +1 -0
  3. data/.idea/.rakeTasks +7 -0
  4. data/.idea/codeStyleSettings.xml +13 -0
  5. data/.idea/compiler.xml +25 -0
  6. data/.idea/copyright/profiles_settings.xml +5 -0
  7. data/.idea/encodings.xml +5 -0
  8. data/.idea/misc.xml +11 -0
  9. data/.idea/modules.xml +11 -0
  10. data/.idea/scopes/scope_settings.xml +5 -0
  11. data/.idea/vcs.xml +9 -0
  12. data/Gemfile +2 -0
  13. data/Gemfile.lock +196 -0
  14. data/LICENSE +22 -0
  15. data/README.md +35 -0
  16. data/README.rdoc +6 -0
  17. data/Rakefile +46 -0
  18. data/bin/designshelld.example.sh +5 -0
  19. data/bin/designshelld.example2.sh +3 -0
  20. data/bin/designshellserver +22 -0
  21. data/bin/ds +177 -0
  22. data/designshell.gemspec +40 -0
  23. data/designshell.iml +84 -0
  24. data/designshell.rdoc +5 -0
  25. data/features/designshell.feature +8 -0
  26. data/features/step_definitions/designshell_steps.rb +6 -0
  27. data/features/support/env.rb +15 -0
  28. data/lib/buzzcore_mods.rb +19 -0
  29. data/lib/designshell/context.rb +48 -0
  30. data/lib/designshell/core.rb +78 -0
  31. data/lib/designshell/deploy_plan.rb +40 -0
  32. data/lib/designshell/key_chain.rb +40 -0
  33. data/lib/designshell/repo.rb +112 -0
  34. data/lib/designshell/repo_server.rb +25 -0
  35. data/lib/designshell/site_client.rb +141 -0
  36. data/lib/designshell/utils.rb +18 -0
  37. data/lib/designshell/version.rb +3 -0
  38. data/lib/designshell.rb +19 -0
  39. data/lib/designshellserver/command.rb +180 -0
  40. data/lib/designshellserver/core.rb +41 -0
  41. data/lib/designshellserver.rb +17 -0
  42. data/spec/KeyChain_spec.rb +94 -0
  43. data/spec/RepoServer_spec.rb +54 -0
  44. data/spec/Repo_spec.rb +105 -0
  45. data/spec/build_spec.rb +29 -0
  46. data/spec/client_to_server_spec.rb +111 -0
  47. data/spec/designshell_context_spec.rb +18 -0
  48. data/spec/designshell_core_spec.rb +45 -0
  49. data/spec/rspec_helper.rb +8 -0
  50. data/spec/server/deploy_spec.rb +210 -0
  51. data/spec/server/dummy_spec.rb +52 -0
  52. data/spec/site_client_spec.rb +90 -0
  53. data/test/default_test.rb +14 -0
  54. data/test/test_helper.rb +9 -0
  55. data/testmart.iml +9 -0
  56. metadata +390 -0
@@ -0,0 +1,18 @@
1
+ module DesignShell
2
+ module Utils
3
+ def self.lookupItems(aDeployNode, aKeyChain)
4
+ result = {}
5
+ REXML::XPath.each(aDeployNode,'item') do |n|
6
+ name = n.attribute('name').to_s.to_nil
7
+ key = n.attribute('key').to_s.to_nil || name
8
+ next unless name
9
+ if text = n.text.to_nil # value in node
10
+ result[name] = text
11
+ else # value in @params['deploy_creds']
12
+ result[key] = aKeyChain.get(key.to_sym) if key
13
+ end
14
+ end
15
+ result
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module DesignShell
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,19 @@
1
+ require 'designshell/version'
2
+ require 'osx_keychain'
3
+ require 'gli'
4
+ require 'git'
5
+ require 'buzzcore'
6
+ require 'buzzcore_mods'
7
+ require 'termios'
8
+ require 'highline/import'
9
+ require 'fileutils'
10
+ require 'net/ssh'
11
+ require 'uri'
12
+
13
+ require 'designshell/utils'
14
+ require 'designshell/context'
15
+ require 'designshell/key_chain'
16
+ require 'designshell/repo'
17
+ require 'designshell/repo_server'
18
+ require 'designshell/deploy_plan'
19
+ require 'designshell/core'
@@ -0,0 +1,180 @@
1
+ module DesignShellServer
2
+ class Command
3
+
4
+ attr_accessor :core,:context,:line,:command,:id,:params,:repo
5
+
6
+ def initialize(aCore,aLine,aCommandName=nil)
7
+ @core = aCore
8
+ @context = aCore && aCore.context
9
+ @line = aLine
10
+ tl = aLine.dup
11
+ cmd = tl.extract!(/^[A-Z0-9_]+/)
12
+ @command = aCommandName || cmd
13
+ tl.bite! ' '
14
+ @id = tl.extract!(/^[a-z0-9]+/)
15
+ tl.bite! ' '
16
+ @params = ::JSON.parse(tl) if @params = tl.to_nil
17
+ end
18
+
19
+ def execute
20
+ self.send @command.to_sym
21
+ end
22
+
23
+ def writeline(aString)
24
+ @context.stdout.puts aString
25
+ end
26
+
27
+ # Prepares repo in cache dir for site
28
+ # requires params: repo_url,site
29
+ def prepare_cache # {:url=>'git://github.com/ddssda', :branch=>'master', :commit=>'ad452bcd'}
30
+ url = @params['repo_url']
31
+ site = @params['site']
32
+ wd = @core.working_dir_from_site(site)
33
+
34
+ @repo = DesignShell::Repo.new
35
+ suitable = if File.exists?(wd)
36
+ @repo.open wd
37
+ @repo.origin.url==url
38
+ else
39
+ false
40
+ end
41
+
42
+ if suitable
43
+ @repo.fetch
44
+ else
45
+ if File.exists? wd
46
+ raise RuntimeError.new('almost did bad delete') if !@core.cache_dir || @core.cache_dir.length<3 || !wd.begins_with?(@core.cache_dir)
47
+ FileUtils.rm_rf wd
48
+ end
49
+ @repo.clone(url, wd)
50
+ end
51
+ end
52
+
53
+ # Switches @repo to given branch and/or commit
54
+ # Should call prepare_cache first to create @repo
55
+ # requires params: branch and/or commit
56
+ def checkout_branch_commit
57
+ #url = @params['repo_url']
58
+ #site = @params['site']
59
+ #wd = @core.working_dir_from_site(site)
60
+ branch = @params['branch'] || 'master'
61
+ commit = @params['commit']
62
+ @repo.checkout(commit,branch)
63
+ #perhaps use reset --hard here
64
+ if (commit)
65
+ @repo.merge(commit,['--ff-only'])
66
+ else
67
+ @repo.merge('origin/'+branch,['--ff-only'])
68
+ end
69
+ end
70
+
71
+ # Determines whether to do an incremental or complete deploy and deploys current files in repo working dir to repo_url
72
+ # requires :
73
+ # uses: site_client.deploy_status
74
+ # params: deploy_cred
75
+ def deploy
76
+ deployPlanString = @repo.get_file_content('.deploy_plan.xml',@params['commit']||@params['branch'])
77
+ xmlRoot = XmlUtils.get_xml_root(deployPlanString)
78
+ # select plan
79
+ planNode = XmlUtils.single_node(xmlRoot,'plan')
80
+ # for each deploy
81
+ deployNode = XmlUtils.single_node(planNode,'deploy')
82
+ # create client for kind/method
83
+ @site_client = DesignShell::SiteClient.new({
84
+ :site_url => @params['site_url'],
85
+ :site_username => @params['site_username'],
86
+ :site_password => @params['site_password'],
87
+ })
88
+ ds = @site_client.deploy_status
89
+ site_repo_url = ds && ds['repo_url'].to_nil
90
+ site_branch = ds && ds['branch'].to_nil
91
+ site_commit = ds && ds['commit'].to_nil
92
+ repo_url = @repo.url
93
+ # @todo must limit uploads to build folder
94
+ fromPath = MiscUtils.ensure_slashes(XmlUtils.peek_node_value(deployNode,'fromPath','/'),false,true) # eg. /build/bigcommerce effectively selects a subfolder that should be debased
95
+ toPath = MiscUtils.ensure_slashes(XmlUtils.peek_node_value(deployNode,'toPath','/'),false,true) # eg. / effectively the new base for these files
96
+ if site_repo_url && site_repo_url==repo_url && site_branch && site_commit
97
+ # incremental
98
+ changes = @repo.changesBetweenCommits(site_commit,@repo.head.to_s)
99
+ uploads,deletes = convertChangesToUploadsDeletes(changes)
100
+ uploads.delete_if { |fp| !fp.begins_with?(fromPath) }
101
+ deletes.delete_if { |fp| !fp.begins_with?(fromPath) }
102
+ @site_client.delete_files(deletes,fromPath,toPath)
103
+ @site_client.upload_files(@repo.path,uploads,fromPath,toPath)
104
+ @site_client.deploy_status = {
105
+ :repo_url => @repo.url,
106
+ :branch => @repo.branch,
107
+ :commit => @repo.head.to_s,
108
+ :fromPath => fromPath,
109
+ :toPath => toPath
110
+ }
111
+ else
112
+ # complete
113
+ # for now, just deploy all files in wd, creating folders as necessary
114
+ # later, delete remote files not in wd except for eg. .deploy-status.xml and perhaps upload folders
115
+ uploads = MiscUtils.recursive_file_list(@repo.path,false)
116
+ uploads.delete_if do |fp|
117
+ !fp.begins_with?(fromPath) || fp.begins_with?('.git/')
118
+ end
119
+ @site_client.upload_files(@repo.path,uploads,fromPath,toPath)
120
+ @site_client.deploy_status = {
121
+ :repo_url => @repo.url,
122
+ :branch => @repo.branch,
123
+ :commit => @repo.head.to_s,
124
+ :fromPath => fromPath,
125
+ :toPath => toPath
126
+ }
127
+ end
128
+ end
129
+
130
+ # Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
131
+ def convertChangesToUploadsDeletes(changes)
132
+ uploads = []
133
+ deletes = []
134
+ changes.each do |line|
135
+ continue if line==""
136
+ tabi = line.index("\t")
137
+ status = line[0,tabi]
138
+ path = line[tabi+1..-1]
139
+ if status.index('D')
140
+ deletes << path
141
+ else
142
+ uploads << path
143
+ end
144
+ end
145
+ return uploads,deletes
146
+ end
147
+
148
+ def DUMMY
149
+ id = StringUtils.random_word(8,8)
150
+ writeline "RECEIVED "+id
151
+ sleep 1
152
+ detail = ::JSON.generate({:this=>5, :that=>'ABC'}) #JSON.parse(document) or JSON.generate(data)
153
+ writeline ['PROGRESS',id,detail].join(' ')
154
+ sleep 1
155
+ detail = ::JSON.generate({:result=>123}) #JSON.parse(document) or JSON.generate(data)
156
+ writeline ['COMPLETE',id,detail].join(' ')
157
+ end
158
+
159
+ def QUICK
160
+ id = StringUtils.random_word(8,8)
161
+ writeline "RECEIVED "+id
162
+ writeline "COMPLETE "+id
163
+ end
164
+
165
+ def DEPLOY # {}
166
+ id = StringUtils.random_word(8,8)
167
+ writeline "RECEIVED "+id
168
+ detail =
169
+ writeline ['PROGRESS',id,::JSON.generate({:message => 'preparing cache'})].join(' ')
170
+ prepare_cache
171
+ writeline ['PROGRESS',id,::JSON.generate({:message => 'checkout'})].join(' ')
172
+ checkout_branch_commit
173
+ writeline ['PROGRESS',id,::JSON.generate({:message => 'deploying'})].join(' ')
174
+ deploy
175
+ writeline "COMPLETE "+id
176
+ end
177
+
178
+
179
+ end
180
+ end
@@ -0,0 +1,41 @@
1
+ module DesignShellServer
2
+ class Core
3
+
4
+ attr_reader :context
5
+
6
+ def initialize(aContext)
7
+ @context = aContext
8
+ end
9
+
10
+ def make_command(aLine)
11
+ command_name = aLine.scan(/^[A-Z0-9_]+/).pop.to_nil
12
+ return nil unless command_name && DesignShellServer::Command.instance_methods.include?(command_name)
13
+ return DesignShellServer::Command.new(self,aLine,command_name)
14
+ end
15
+
16
+ def run
17
+ if line = ENV['SSH_ORIGINAL_COMMAND']
18
+ command = make_command(line)
19
+ command.execute
20
+ else
21
+ @context.stdout.print "\n>"
22
+ @context.stdin.each_line do |line| line.chomp! "\n"
23
+ command = make_command(line)
24
+ command.execute
25
+ @context.stdout.print "\n>"
26
+ end
27
+ end
28
+ end
29
+
30
+ def cache_dir
31
+ @cache_dir ||= MiscUtils.append_slash(@context.credentials[:cache_dir] || MiscUtils.make_temp_dir('DesignShellServer'))
32
+ end
33
+
34
+ def working_dir_from_site(aSite)
35
+ return nil unless aSite
36
+ aSite.gsub!(/[^a-zA-Z0-9.\-_]/,'_')
37
+ File.join(cache_dir,aSite)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ require 'git'
2
+ require 'buzzcore'
3
+ require 'buzzcore_mods'
4
+ require 'net/dav'
5
+ require 'json'
6
+ require 'fileutils'
7
+ require 'uri'
8
+
9
+ #require 'termios'
10
+ #require 'highline/import'
11
+
12
+ require 'designshell/context'
13
+ require 'designshell/site_client'
14
+ require 'designshell/deploy_plan'
15
+ require 'designshell/repo'
16
+ require 'designshellserver/core'
17
+ require 'designshellserver/command'
@@ -0,0 +1,94 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+
4
+ describe "KeyChain" do
5
+
6
+ keyChain = nil
7
+
8
+ before do
9
+ keyChain = DesignShell::KeyChain.new('DesignShellTest')
10
+ end
11
+
12
+ it "should write,read,check value" do
13
+ value = StringUtils.random_word(8,8)
14
+ keyChain.set('testKey',value)
15
+ readValue = keyChain.get('testKey')
16
+ readValue.should == value
17
+ end
18
+
19
+ it "should support get and set with a prefix" do
20
+ value1 = StringUtils.random_word(8,8)
21
+ value2 = StringUtils.random_word(8,8)
22
+ keyChain.set('testKey',value1)
23
+ keyChain.set('testKey',value2,'blah')
24
+ keyChain.get('testKey').should==value1
25
+ keyChain.get('testKey','blah').should==value2
26
+ end
27
+
28
+ it "should support multiple get" do
29
+ value1 = StringUtils.random_word(8,8)
30
+ value2 = StringUtils.random_word(8,8)
31
+ keyChain.set('testKey1',value1)
32
+ keyChain.set('testKey2',value2)
33
+ keyChain.get('testKey1').should==value1
34
+ keyChain.get('testKey2').should==value2
35
+ keyChain.get(['testKey1']).should=={'testKey1' => value1}
36
+ keyChain.get(['testKey2']).should=={'testKey2' => value2}
37
+ keyChain.get(['testKey1','testKey2']).should=={'testKey1' => value1,'testKey2' => value2}
38
+ keyChain.get(%w(testKey1 testKey2)).should=={'testKey1' => value1,'testKey2' => value2}
39
+ end
40
+
41
+ it "should support multiple get with a prefix" do
42
+ value1 = StringUtils.random_word(8,8)
43
+ value2 = StringUtils.random_word(8,8)
44
+ keyChain.set('testKey1','')
45
+ keyChain.set('testKey2','')
46
+ keyChain.set('testKey1',value1,'prefix1.')
47
+ keyChain.set('testKey2',value2,'prefix1.')
48
+ keyChain.get(%w(testKey1 testKey2)).should == {'testKey1' => '', 'testKey2' => ''}
49
+ keyChain.get(%w(testKey1 testKey2),'prefix1.').should == {'testKey1' => value1, 'testKey2' => value2}
50
+ keyChain.get(%w(testKey1 testKey2),'prefix1.',true).should == {'prefix1.testKey1' => value1, 'prefix1.testKey2' => value2}
51
+ end
52
+
53
+ it "should support multiple set" do
54
+ value1 = StringUtils.random_word(8,8)
55
+ value2 = StringUtils.random_word(8,8)
56
+ keyChain.set({
57
+ 'testKey1' => value1,
58
+ 'testKey2' => value2
59
+ })
60
+ keyChain.get('testKey1').should==value1
61
+ keyChain.get('testKey2').should==value2
62
+ end
63
+
64
+ DEPLOY_XML = <<EOS
65
+ <deploy>
66
+ <kind>BigCommerce</kind>
67
+ <method>WebDav</method>
68
+ <fromPath>/build/bigcommerce</fromPath>
69
+ <toPath>/</toPath>
70
+ <item name="itemX">some item x</item>
71
+ <item name="itemY" key="itemYYY">YYY</item>
72
+ <item name="itemZ"></item>
73
+ <item name="itemZZ"/>
74
+ </deploy>
75
+ EOS
76
+
77
+ it "should support DesignShell::Utils.lookupItems" do
78
+ values = {
79
+ 'itemX' => 'never read this',
80
+ 'itemY' => 'never read this',
81
+ 'itemYYY' => 'YYYYY',
82
+ 'itemZ' => 'ZZZ',
83
+ 'itemZZ' => 'ZZZZZ',
84
+ }
85
+ keyChain.set(values)
86
+ deployXml = XmlUtils.get_xml_root(DEPLOY_XML)
87
+ result = DesignShell::Utils.lookupItems(deployXml,keyChain)
88
+ result['itemX'].should=='some item x'
89
+ result['itemY'].should=='YYY' # text value overrides keychain
90
+ result['itemZ'].should==values['itemZ']
91
+ result['itemZZ'].should==values['itemZZ']
92
+ end
93
+
94
+ end
@@ -0,0 +1,54 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+ require "fileutils"
4
+
5
+ describe "RepoServer" do
6
+
7
+ testFolder = nil
8
+ before do
9
+ testFolder = Dir.mktmpdir('Repo_spec-')
10
+
11
+ cred = Credentials.new(:designshell)
12
+
13
+ end
14
+
15
+ after do
16
+ FileUtils.rm_rf testFolder if testFolder
17
+ end
18
+
19
+ it "should list repos" do
20
+ keyChain = DesignShell::KeyChain.new('DesignShell')
21
+ #keyChain.set({
22
+ # :oauth_token => 'OAuth consumer Key',
23
+ # :oauth_secret => 'OAuth consumer Secret',
24
+ # :login => 'username, not email address',
25
+ # :password => 'user password'
26
+ #},'RepoServer.')
27
+ repoServer = DesignShell::RepoServer.new
28
+ # should move values to credentials that looks up keyChain
29
+ values = keyChain.get([:oauth_token,:oauth_secret,:login,:password],'RepoServer.').symbolize_keys
30
+ repoServer.setup(values)
31
+
32
+ result = repoServer.repos #"[#<Hashie::Mash is_private=true name="test1" owner="buzzware" scm="git" slug="test1">]"
33
+ result.class.should==Array
34
+ result.length.should > 0
35
+ result.first.scm.should=='git'
36
+ end
37
+
38
+ it "should clone the first repo" do
39
+ keyChain = DesignShell::KeyChain.new('DesignShell')
40
+ repoServer = DesignShell::RepoServer.new
41
+ values = keyChain.get([:oauth_token,:oauth_secret,:login,:password],'RepoServer.').symbolize_keys
42
+ repoServer.setup(values)
43
+ repos = repoServer.repos
44
+ repos.length.should > 0
45
+ repo = repos && repos.first
46
+
47
+ url = "git@bitbucket.org:#{repo.owner}/#{repo.slug}.git"
48
+ repo = DesignShell::Repo.new
49
+ result = repo.clone(url, testFolder)
50
+ repo.path.should == testFolder
51
+ repo.branches.class.should == Git::Branches
52
+ end
53
+
54
+ end
data/spec/Repo_spec.rb ADDED
@@ -0,0 +1,105 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+ require "fileutils"
4
+
5
+ describe "Repo" do
6
+
7
+ testFolder = nil
8
+ before do
9
+ testFolder = MiscUtils.real_path(Dir.mktmpdir('Repo_spec-'))
10
+ end
11
+
12
+ after do
13
+ FileUtils.rm_rf testFolder if testFolder
14
+ end
15
+
16
+
17
+ COMMIT_RESULT1 = "[master (root-commit) 6bdd9e1] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file1.txt"
18
+
19
+ it "commit should create commit object or string message" do
20
+ repo = DesignShell::Repo.new
21
+ repo.init testFolder
22
+
23
+ file1 = File.join(testFolder,'file1.txt')
24
+ content11 = '11111'
25
+ MiscUtils.string_to_file(content11,file1)
26
+ repo.add 'file1.txt'
27
+ commit1 = repo.commit_all('first commit')
28
+ commit1.class.should == Git::Object::Commit
29
+
30
+ commit2 = repo.commit_all('second commit without changes')
31
+ commit2.should == nil
32
+ end
33
+
34
+ it "create a repo, add file, commit, change, commit, reset, check" do
35
+ repo = DesignShell::Repo.new
36
+ repo.init testFolder
37
+ repo.path.should == MiscUtils.real_path(testFolder)
38
+
39
+ file1 = File.join(testFolder,'file1.txt')
40
+ content11 = '11111'
41
+ MiscUtils.string_to_file(content11,file1)
42
+ repo.git.add 'file1.txt'
43
+ commit1 = repo.commit_all('first commit')
44
+
45
+ content12 = '11111-some more text'
46
+ MiscUtils.string_to_file(content12,file1)
47
+ commit2 = repo.commit_all('second commit')
48
+
49
+ read_content = MiscUtils.string_from_file(file1)
50
+ read_content.should == content12
51
+
52
+ repo.reset_hard(commit1)
53
+
54
+ read_content = MiscUtils.string_from_file(file1)
55
+ read_content.should == content11
56
+ end
57
+
58
+ it "should download a remote repo and check log, then re-open it and check log again" do
59
+ repo = DesignShell::Repo.new
60
+ url = "git@github.com:buzzware/underscore_plus.git"
61
+ repo.clone(url, testFolder)
62
+ repo.path.should == testFolder
63
+ repo.log.first.class.should == Git::Object::Commit
64
+
65
+ repo = DesignShell::Repo.new
66
+ repo.open testFolder
67
+ repo.path.should == testFolder
68
+ repo.log.first.class.should == Git::Object::Commit
69
+ repo.origin.url==url
70
+ end
71
+
72
+ it "should download a remote repo and get diffs between commits" do
73
+ repo = DesignShell::Repo.new
74
+ url = "git@github.com:buzzware/underscore_plus.git"
75
+ repo.clone(url, testFolder)
76
+
77
+ commit1 = "4b133ff8825bbd488ba61fa3e3b82a5fa746ac6a"
78
+ commit2 = "d1b8440dc730ceb4471fbe7c42ccfac94ea12799"
79
+ changes = repo.changesBetweenCommits(commit1,commit2)
80
+ changes.should==["A\tunderscore_plus.js"]
81
+ changes = repo.changesBetweenCommits(commit2,commit1)
82
+ changes.should==["D\tunderscore_plus.js"]
83
+ end
84
+
85
+ it "should get contents of a given file from a given commit" do
86
+ repo = DesignShell::Repo.new
87
+ url = "git@github.com:buzzware/underscore_plus.git"
88
+ repo.clone(url, testFolder)
89
+
90
+ commit1 = "4b133ff8825bbd488ba61fa3e3b82a5fa746ac6a"
91
+ commit2 = "d1b8440dc730ceb4471fbe7c42ccfac94ea12799"
92
+ file1 = "README.md"
93
+ file2 = "underscore_plus.js"
94
+
95
+ readme = repo.get_file_content(file1,commit1)
96
+ readme.is_a?(String).should==true
97
+ readme.size.should > 0
98
+ code = repo.get_file_content(file2,commit1)
99
+ code.should==nil
100
+ code = repo.get_file_content(file2,commit2)
101
+ code.is_a?(String).should==true
102
+ code.size.should > 0
103
+ end
104
+
105
+ end
@@ -0,0 +1,29 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+
4
+ describe "build" do
5
+
6
+ testFolder = nil
7
+ before do
8
+ testFolder = Dir.mktmpdir('Repo_spec-')
9
+ end
10
+
11
+ after do
12
+ FileUtils.rm_rf testFolder if testFolder
13
+ end
14
+
15
+ #it "should build source folder into build folder" do
16
+ # context = DesignShell::Context.new()
17
+ # ds = DesignShell::Core.new(:context => context)
18
+ # ds.build
19
+ #end
20
+
21
+ #it "should commit the repository" do
22
+ # context = DesignShell::Context.new()
23
+ # repo = DesignShell::Repo.new
24
+ # repo.configure()
25
+ # repo.clone("git@github.com:buzzware/underscore_plus.git", testFolder)
26
+ # ds = DesignShell::Core.new(:context => context, :repo => repo)
27
+ # ds.ensure_repo_open.commit_all(context)
28
+ #end
29
+ end
@@ -0,0 +1,111 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+
4
+ describe "client to server interaction" do
5
+
6
+ before do
7
+ @key_chain = DesignShell::KeyChain.new('DesignShellTest')
8
+ @credentials = Credentials.new('designshell')
9
+ Dir.chdir @credentials[:deploy_repo_path]
10
+ @context = DesignShell::Context.new(
11
+ :argv=>[],
12
+ :env=>{},
13
+ :stdout=>$stdout,
14
+ :stdin=>$stdin,
15
+ :stderr=>$stderr,
16
+ :key_chain=>@key_chain,
17
+ :credentials=>@credentials
18
+ )
19
+ end
20
+
21
+ it "should call QUICK and get results" do
22
+ dash = DesignShell::Core.new(
23
+ :context => @context
24
+ )
25
+ result = dash.call_server_command('QUICK')
26
+ puts result
27
+ result.begins_with?('RECEIVED').should == true
28
+ result.index('COMPLETE').should >= 0
29
+ end
30
+
31
+ it "should call deploy" do
32
+ dash = DesignShell::Core.new(
33
+ :context => @context
34
+ )
35
+ result = dash.deploy
36
+ puts result
37
+ result.begins_with?('RECEIVED').should == true
38
+ result.index('COMPLETE').should >= 0
39
+ end
40
+
41
+
42
+
43
+ #it "should connect to SSH server" do
44
+ # Net::SSH.start( @context.credentials[:deploy_host],nil) do |ssh|
45
+ #
46
+ # #result = ssh.exec!("ls")
47
+ # #puts result
48
+ #
49
+ #
50
+ # #ssh.open_channel{|channel| #get root privelages
51
+ # ##configure behavior of channel
52
+ # #channel.on_data{|channel, data|
53
+ # # puts "#{data}"
54
+ # # if data =~ /^Password:/
55
+ # # channel.send_data("#{PASSWORD}\n")
56
+ # # elsif data =~ /root@/
57
+ # # channel.exec("tail /some/log/file.txt")
58
+ # # channel.on_data{"STOP LOOPING, DAMN YOU!"}
59
+ # # end
60
+ # #channel.on_close... (etc.)
61
+ # #
62
+ # #channel.request_pty do |ch,success|
63
+ # # if success
64
+ # # puts "pty successfully obtained"
65
+ # # else
66
+ # # puts "could not obtain pty"
67
+ # # end end
68
+ # #
69
+ # #channel.exec("sudoshell"){|channel, win| #custom sudo script.
70
+ # # if win
71
+ # # puts "ss command sent"
72
+ # # else puts "ss command FAIL"
73
+ # # end
74
+ # #}
75
+ # #
76
+ #
77
+ # ssh.open_channel do |channel|
78
+ # channel.on_data do |ch, data|
79
+ # puts "got stdout: #{data}"
80
+ # #channel.send_data "something for stdin\n"
81
+ # end
82
+ #
83
+ # channel.on_extended_data do |ch, type, data|
84
+ # puts "got stderr: #{data}"
85
+ # end
86
+ #
87
+ # channel.on_close do |ch|
88
+ # puts "channel is closing!"
89
+ # end
90
+ #
91
+ # channel.request_pty do |ch,success|
92
+ # if success
93
+ # puts "pty successfully obtained"
94
+ # else
95
+ # puts "could not obtain pty"
96
+ # end
97
+ # end
98
+ # #sleep 1
99
+ # result = channel.exec("DEPLOY") do |ch, success|
100
+ # abort "could not execute command" unless success
101
+ # end
102
+ # channel.wait
103
+ # puts result
104
+ # end
105
+ #
106
+ # ssh.loop
107
+ #
108
+ # end
109
+ #end
110
+
111
+ end
@@ -0,0 +1,18 @@
1
+ require "rspec"
2
+ require "rspec_helper"
3
+
4
+ describe "DesignShell::Context" do
5
+
6
+ it "should find repo path upward" do
7
+ tempdir = MiscUtils.real_path(MiscUtils.make_temp_dir('designshell_context_spec'))
8
+ Dir.mkdir(git_dir = File.join(tempdir,'.git'))
9
+ Dir.mkdir(File.join(tempdir,'one'))
10
+ orange = File.join(tempdir,'one/apple/orange')
11
+ FileUtils.mkpath(orange)
12
+ Dir.mkdir(File.join(tempdir,'two'))
13
+ Dir.chdir(orange)
14
+ context = DesignShell::Context.new({})
15
+ context.pwd.should==orange
16
+ context.find_git_root.should==tempdir
17
+ end
18
+ end