slicecraft 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # SliceCraft
2
+
3
+ SliceCraft commands for generating, previewing and delivering a project.
4
+
5
+ Download the latest gemfile in the [downloads](https://github.com/80beans/slicecraft/downloads) section, then run `gem install /.[gemfile name]` in your console to install the gem.
6
+
7
+ ## Commands
8
+
9
+ ````
10
+ slicecraft new [projectname]
11
+ ````
12
+
13
+ Creates a new project folder with middleman template in your current folder.
14
+
15
+ ````
16
+ slicecraft preview
17
+ ````
18
+
19
+ Run this in your project folder to create a preview and upload it to the server.
20
+
21
+ ````
22
+ slicecraft deliver
23
+ ````
24
+
25
+ Run this in your project folder to deliver the project, a zip of the build and source is uploaded to the server.
data/bin/slicecraft ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/slicecraft')
6
+
7
+ program :version, '0.0.1'
8
+ program :description, "The 80beans SliceCraft gem. Run 'slicecraft new [projectname]' to create a new SliceCraft project."
9
+
10
+ command :new do |c|
11
+ c.syntax = 'slicecraft new [projectname]'
12
+ c.summary = 'Initialize a new project.'
13
+ c.description = 'Enter a project name to create a folder with that name and generate the 80beans middleman template.'
14
+ c.action do |args, options|
15
+ if args.first
16
+ c.when_called Slicecraft::Project.create(:directory => args.first)
17
+ say "Project '#{args.first}' successfully created, have fun slicing!"
18
+ else
19
+ say "Error: Enter a projectname (slicecraft new [projectname])"
20
+ end
21
+ end
22
+ end
23
+
24
+ command :preview do |c|
25
+ c.syntax = 'slicecraft preview'
26
+ c.summary = 'Ships the project to the preview server'
27
+ c.description = 'When in a folder containing a middleman project run this to sync a preview to the server.'
28
+ c.option '--url', String, 'Instead of building the preview this only shows the preview url'
29
+ c.action do |args, options|
30
+ if options.url
31
+ say "Preview url: #{Slicecraft::Preview.new(:directory => Dir.pwd).result_url}"
32
+ else
33
+ c.when_called Slicecraft::Project.build
34
+ preview = Slicecraft::Preview.new(:directory => Dir.pwd)
35
+ preview.process
36
+ say "Shipped to: #{preview.result_url}"
37
+ say "Pages:"
38
+ preview.result_urls.each{ |r| say r }
39
+ end
40
+ end
41
+ end
42
+
43
+ command :deliver do |c|
44
+ c.syntax = 'slicecraft deliver'
45
+ c.summary = 'Delivers a project zip'
46
+ c.description = 'When in a folder containing a middleman project run this to deliver a project zip containing the build and source to the server.'
47
+ c.option '--url', String, 'Instead of delivering the zip this only shows the zip url'
48
+ c.action do |args, options|
49
+ if options.url
50
+ say "Zip url: #{Slicecraft::Delivery.new(:directory => Dir.pwd).result_url}"
51
+ else
52
+ c.when_called Slicecraft::Project.build
53
+ delivery = Slicecraft::Delivery.new(:directory => Dir.pwd)
54
+ delivery.process
55
+ say "Zipped to: #{delivery.result_url}"
56
+ end
57
+ end
58
+ end
data/config.yml ADDED
@@ -0,0 +1,7 @@
1
+ server:
2
+ url: slicecraft.nl
3
+ user: slicecraft
4
+ preview_path: /home/slicecraft/previews/
5
+ result_url: http://preview.slicecraft.nl
6
+
7
+ template_repo: git@github.com:80beans/slicecraft_template.git
data/lib/slicecraft.rb ADDED
@@ -0,0 +1,117 @@
1
+ require 'net/scp'
2
+ require 'yaml'
3
+ require 'zip/zip'
4
+
5
+ module Slicecraft
6
+
7
+ class Project
8
+
9
+ def self.create(options)
10
+ @location = options[:directory]
11
+
12
+ system "git clone #{self.template_repo} #{@location}"
13
+ FileUtils.rm_rf "#{@location}/.git"
14
+ end
15
+
16
+ def self.build
17
+ result = system "middleman build"
18
+ raise 'Middleman could not build' unless result
19
+ end
20
+
21
+ def self.template_repo
22
+ YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '../config.yml')))['template_repo']
23
+ end
24
+
25
+ end
26
+
27
+ class Syncer
28
+ attr_accessor :path
29
+ attr_accessor :settings
30
+
31
+ def initialize(options)
32
+ @path = options[:directory]
33
+ end
34
+
35
+ def hashed_path
36
+ "#{project_name}_#{Digest::SHA1.hexdigest('12RThh' + project_name)}"
37
+ end
38
+
39
+ def result_url
40
+ "#{settings['result_url']}/#{hashed_path}"
41
+ end
42
+
43
+ def project_name
44
+ @path.split('/').last
45
+ end
46
+
47
+ def build_path
48
+ "#{@path}/build/"
49
+ end
50
+
51
+ def settings
52
+ @settings ||= YAML.load_file(File.expand_path(File.join(File.dirname(__FILE__), '../config.yml')))['server']
53
+ end
54
+
55
+ end
56
+
57
+
58
+ class Preview < Syncer
59
+
60
+ def result_urls
61
+ results = Dir.entries(build_path).select{ |file| file.end_with?('.html') }.map{ |r| "#{result_url}/#{r}" }
62
+ FileUtils.rm_rf build_path if File.exists? build_path
63
+ results
64
+ end
65
+
66
+ def process
67
+ system "rsync -ave ssh #{build_path} #{settings['user']}@#{settings['url']}:#{"#{settings['preview_path']}#{hashed_path}"}"
68
+ end
69
+
70
+ end
71
+
72
+ class Delivery < Syncer
73
+
74
+ def process
75
+ zip
76
+ sync
77
+ end
78
+
79
+ def zip
80
+ if File.exists?('zip/source.zip')
81
+ File.delete('zip/source.zip')
82
+ else
83
+ FileUtils.mkdir('zip') unless File.exists?('zip')
84
+ end
85
+ Zip::ZipFile.open(File.join(zip_path, 'source.zip'), Zip::ZipFile::CREATE) do |zipfile|
86
+ add_folder_to_zipfile(zipfile, 'source')
87
+ add_folder_to_zipfile(zipfile, 'build')
88
+ end
89
+ end
90
+
91
+ def add_folder_to_zipfile(zipfile, folder)
92
+ Dir["#{path}/#{folder}/**/**"].each do |file|
93
+ zipfile.add(file.sub(path+'/',''),file)
94
+ end
95
+ end
96
+
97
+ def zip_path
98
+ "#{@path}/zip/"
99
+ end
100
+
101
+ def result_url
102
+ super + '/source.zip'
103
+ end
104
+
105
+ def hashed_path
106
+ super + '/zip'
107
+ end
108
+
109
+ def sync
110
+ system "rsync -ave ssh #{zip_path} #{settings['user']}@#{settings['url']}:#{"#{settings['preview_path']}#{hashed_path}"}"
111
+ FileUtils.rm_rf zip_path if File.exists? zip_path
112
+ FileUtils.rm_rf build_path if File.exists? build_path
113
+ end
114
+
115
+ end
116
+
117
+ end
@@ -0,0 +1,161 @@
1
+ require 'rspec'
2
+ require File.expand_path(File.dirname(__FILE__) + '/../../lib/slicecraft')
3
+
4
+ describe Slicecraft::Project do
5
+
6
+ context ".create" do
7
+
8
+ it "should create a project" do
9
+ Slicecraft::Project.should_receive(:system).with("git clone git@github.com:80beans/slicecraft_template.git /slice_this")
10
+ FileUtils.should_receive(:rm_rf).with("/slice_this/.git")
11
+
12
+ Slicecraft::Project.create(:directory => "/slice_this")
13
+ end
14
+
15
+ end
16
+
17
+ context ".build" do
18
+
19
+ it "should build a project" do
20
+ Slicecraft::Project.should_receive(:system).with("middleman build").and_return(true)
21
+
22
+ Slicecraft::Project.build
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ describe Slicecraft::Syncer do
30
+
31
+ let(:syncer) { Slicecraft::Syncer.new(:directory => '/slice_this') }
32
+
33
+ context "#settings" do
34
+
35
+ it "should have settings" do
36
+ syncer.settings.should == {
37
+ "url" => "slicecraft.nl",
38
+ "user" => "slicecraft",
39
+ "preview_path" => "/home/slicecraft/previews/",
40
+ "result_url" => "http://preview.slicecraft.nl"
41
+ }
42
+ end
43
+
44
+ end
45
+
46
+ context "#project_name" do
47
+
48
+ it "project_name should be current folder name" do
49
+ syncer.project_name.should == 'slice_this'
50
+ end
51
+
52
+ context "with longer path" do
53
+
54
+ let(:syncer) { Slicecraft::Syncer.new(:directory => '/this/path/is/long/slice_this') }
55
+
56
+ it "project_name should be current folder name" do
57
+ syncer.project_name.should == 'slice_this'
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ context "#hashed_path" do
65
+
66
+ it "should return a path with an id hash in it" do
67
+ syncer.hashed_path.should == 'slice_this_240999fa70d7f05b158bd1170ff932ac0503bea2'
68
+ end
69
+
70
+ end
71
+
72
+ context "#result_url" do
73
+
74
+ it "should return the correct result_url" do
75
+ syncer.result_url.should == "http://preview.slicecraft.nl/slice_this_240999fa70d7f05b158bd1170ff932ac0503bea2"
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ describe Slicecraft::Preview do
83
+
84
+ let(:preview) { Slicecraft::Preview.new(:directory => '/slice_this') }
85
+
86
+ context "#build_path" do
87
+
88
+ it "should return the build path" do
89
+ preview.build_path.should == '/slice_this/build/'
90
+ end
91
+
92
+ end
93
+
94
+ context "#process" do
95
+
96
+ it "should process the preview" do
97
+ preview.should_receive(:system).
98
+ with("rsync -ave ssh /slice_this/build/ slicecraft@slicecraft.nl:/home/slicecraft/previews/slice_this_240999fa70d7f05b158bd1170ff932ac0503bea2")
99
+
100
+ preview.process
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+
107
+ describe Slicecraft::Delivery do
108
+
109
+ let(:delivery) { Slicecraft::Delivery.new(:directory => '/slice_this') }
110
+
111
+ context "#zip_path" do
112
+
113
+ it "should return the zip path" do
114
+ delivery.zip_path.should == '/slice_this/zip/'
115
+ end
116
+
117
+ end
118
+
119
+ context "#sync" do
120
+
121
+ it "should sync the zip" do
122
+ delivery.should_receive(:system).
123
+ with("rsync -ave ssh /slice_this/zip/ slicecraft@slicecraft.nl:/home/slicecraft/previews/slice_this_240999fa70d7f05b158bd1170ff932ac0503bea2/zip")
124
+
125
+ delivery.sync
126
+ end
127
+
128
+ end
129
+
130
+ context "#zip" do
131
+
132
+ it "should create zip folder and file" do
133
+ Zip::ZipFile.should_receive('open')
134
+ FileUtils.should_receive('mkdir').with('zip')
135
+
136
+ delivery.zip
137
+ end
138
+
139
+ context "with existing zip file" do
140
+
141
+ before do
142
+ FileUtils.mkdir('zip')
143
+ FileUtils.touch('zip/source.zip')
144
+ end
145
+
146
+ it "should delete the zip folder and file when a zip file exists" do
147
+ Zip::ZipFile.should_receive('open')
148
+ File.should_receive('delete').with('zip/source.zip')
149
+
150
+ delivery.zip
151
+ end
152
+
153
+ after do
154
+ FileUtils.rm_rf('zip')
155
+ end
156
+
157
+ end
158
+
159
+ end
160
+
161
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slicecraft
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ron Cadier
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: commander
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 4.1.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 4.1.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: middleman
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rubyzip
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.9
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.9
62
+ - !ruby/object:Gem::Dependency
63
+ name: net-scp
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.4
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.4
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: A commandline tool specific for the SliceCraft project flow
95
+ email: ron@80beans.com
96
+ executables:
97
+ - slicecraft
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - lib/slicecraft.rb
102
+ - spec/lib/slicecraft_spec.rb
103
+ - bin/slicecraft
104
+ - README.md
105
+ - config.yml
106
+ homepage: http://80beans.com
107
+ licenses: []
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 1.8.19
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: Internal tool for SliceCraft
130
+ test_files: []