slicecraft 0.1.0

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.
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: []