skypager 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/ARCHITECTURE.md +34 -0
  4. data/CONTRIBUTING.md +7 -0
  5. data/README.md +94 -36
  6. data/Rakefile +1 -1
  7. data/lib/skypager.rb +6 -0
  8. data/lib/skypager/builder.rb +158 -0
  9. data/lib/skypager/builder/server.rb +63 -0
  10. data/lib/skypager/builder/webhook_handler.rb +73 -0
  11. data/lib/skypager/cli/commands/build.rb +48 -0
  12. data/lib/skypager/cli/commands/config.rb +1 -1
  13. data/lib/skypager/cli/commands/setup.rb +13 -0
  14. data/lib/skypager/cli/commands/site.rb +22 -0
  15. data/lib/skypager/cli/commands/sync.rb +1 -1
  16. data/lib/skypager/configuration.rb +32 -7
  17. data/lib/skypager/core_ext.rb +6 -0
  18. data/lib/skypager/data/google_spreadsheet.rb +3 -3
  19. data/lib/skypager/data/source.rb +24 -1
  20. data/lib/skypager/extension.rb +84 -21
  21. data/lib/skypager/proxy.rb +0 -1
  22. data/lib/skypager/router.rb +15 -0
  23. data/lib/skypager/site.rb +104 -21
  24. data/lib/skypager/sync/dropbox/delta.rb +1 -1
  25. data/lib/skypager/sync/folder.rb +7 -1
  26. data/lib/skypager/sync/github.rb +55 -0
  27. data/lib/skypager/version.rb +1 -1
  28. data/skypager.gemspec +21 -13
  29. data/spec/dummy/site-one/.gitignore +18 -0
  30. data/spec/dummy/site-one/Gemfile +14 -0
  31. data/spec/dummy/site-one/config.rb +13 -0
  32. data/spec/dummy/site-one/source/images/background.png +0 -0
  33. data/spec/dummy/site-one/source/images/middleman.png +0 -0
  34. data/spec/dummy/site-one/source/index.html.erb +10 -0
  35. data/spec/dummy/site-one/source/javascripts/all.js +1 -0
  36. data/spec/dummy/site-one/source/layouts/layout.erb +19 -0
  37. data/spec/dummy/site-one/source/stylesheets/all.css +55 -0
  38. data/spec/dummy/site-one/source/stylesheets/normalize.css +375 -0
  39. data/spec/lib/skypager/builder/server_spec.rb +5 -0
  40. data/spec/lib/skypager/configuration_spec.rb +7 -0
  41. data/spec/lib/skypager/site_spec.rb +40 -1
  42. data/spec/lib/skypager_spec.rb +9 -0
  43. data/spec/skypager-test-config.rb.example +22 -0
  44. data/spec/spec_helper.rb +38 -3
  45. data/spec/support/fixtures/cwd_config.json +3 -0
  46. data/spec/support/fixtures/home_config.json +1 -0
  47. metadata +112 -33
  48. data/lib/skypager/build_server.rb +0 -0
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'aws-sdk-core'
4
4
  require 'stringio'
5
- require 'pry'
6
5
 
7
6
  module Skypager
8
7
  class Proxy
@@ -32,6 +32,15 @@ module Skypager
32
32
  self.class.proxies
33
33
  end
34
34
 
35
+ def self.authenticator &block
36
+ @authenticator = block if block_given?
37
+ @authenticator
38
+ end
39
+
40
+ def authenticator
41
+ self.class.authenticator
42
+ end
43
+
35
44
  def call(env)
36
45
  request = Rack::Request.new(env)
37
46
  subdomain = request.host.split('.').first
@@ -40,6 +49,12 @@ module Skypager
40
49
  app
41
50
  end
42
51
 
52
+ if authenticator.respond_to?(:call)
53
+ if !!authenticator.call(env, subdomain)
54
+ return [401, {}, [""]]
55
+ end
56
+ end
57
+
43
58
  handler.call(env)
44
59
  end
45
60
  end
data/lib/skypager/site.rb CHANGED
@@ -1,8 +1,48 @@
1
1
  module Skypager
2
2
  class Site
3
3
  class << self
4
+ def directory= value
5
+ value = value.to_mash if value.respond_to?(:to_mash)
6
+ @directory = Skypager.config.home_config['sites_directory'] = {}.to_mash
7
+ end
8
+
4
9
  def directory
5
- Skypager.config.sites_directory
10
+ unless Skypager.config.home_config.key?('sites_directory')
11
+ self.directory = {}
12
+ end
13
+
14
+ @directory ||= begin
15
+ val = Skypager.config.home_config['sites_directory'] ||= {}.to_mash
16
+ val = val.to_mash if val.is_a?(Hash)
17
+ val
18
+ end
19
+ end
20
+
21
+ def sites
22
+ directory.values
23
+ end
24
+
25
+ def requiring_build
26
+ sites.select {|site| site.requires_build == "yes" }
27
+ end
28
+
29
+ def find_sites_for_dropbox_uid uid
30
+ configs = sites.select do |site|
31
+ syncables = site.syncables
32
+ dropbox = syncables.dropbox ||= {}.to_mash
33
+
34
+ uid.to_s.length > 0 && dropbox.uid.to_s == uid.to_s
35
+ end
36
+
37
+ configs.map {|cfg| Skypager::Site.new(cfg.name, config: cfg) }
38
+ end
39
+
40
+ def find_site_by_dropbox uid, path_prefix
41
+ find_sites_for_dropbox_uid(uid).find do |site|
42
+ Array(site.syncables.dropbox.paths).any? do |path|
43
+ path == path_prefix || path.match(/^#{ path_prefix }/)
44
+ end
45
+ end
6
46
  end
7
47
  end
8
48
 
@@ -10,16 +50,66 @@ module Skypager
10
50
  :name,
11
51
  :config
12
52
 
53
+
13
54
  def initialize(name, options = {})
14
55
  @name = name.to_s.downcase
15
56
  @options = options
16
- @config = self.class.directory[@name] || {
17
- name: @name
18
- }
57
+ @config = options.delete(:config)
58
+ @config ||= self.class.directory[@name] ||= {name: @name}
59
+ @config = @config.to_mash if @config.is_a?(Hash)
19
60
  end
20
61
 
21
- def deploy_options
22
- options.fetch(:deploy_options, {})
62
+ def build_command
63
+ "bundle exec middleman build"
64
+ end
65
+
66
+ def syncables
67
+ config[:syncables].try(:to_mash)
68
+ end
69
+
70
+ def delete!
71
+ directory = self.class.directory
72
+ directory.delete(name)
73
+ save!
74
+ end
75
+
76
+ def save!
77
+ directory = Skypager.config.home_config["sites_directory"] || {}
78
+ directory[name] = to_config
79
+ Skypager.config.save_home_config
80
+ end
81
+
82
+ def root
83
+ @config[:root].to_s.length > 0 && Pathname(@config[:root])
84
+ end
85
+
86
+ def load_config
87
+ if existing = self.class.directory[name]
88
+ @config = existing.to_mash
89
+ end
90
+ end
91
+
92
+ def config
93
+ @config = @config.to_mash if @config.is_a?(Hash)
94
+ @config ||= {}.to_mash
95
+ end
96
+
97
+ def to_config
98
+ config
99
+ end
100
+
101
+ def require_build!(state=true)
102
+ requires_build!(state)
103
+ end
104
+
105
+ def requires_build!(state=true)
106
+ state = !!(state) ? "yes" : "no"
107
+ set(:requires_build, state)
108
+ end
109
+
110
+ def requires_build?
111
+ value = get!(:requires_build)
112
+ value == "yes"
23
113
  end
24
114
 
25
115
  def set attribute, value
@@ -42,6 +132,12 @@ module Skypager
42
132
  @config[attribute.to_sym]
43
133
  end
44
134
 
135
+ def deploy_options
136
+ options.fetch(:deploy_options) do
137
+ config.deploy_options || {}
138
+ end
139
+ end
140
+
45
141
  def hostname= value
46
142
  set(:hostname, value)
47
143
  end
@@ -117,6 +213,8 @@ module Skypager
117
213
  get(:use_cdn) == true || get(:use_cdn) == "yes" || get(:use_cdn) == "true"
118
214
  end
119
215
 
216
+ # TODO
217
+ # Let's store build manifests in their own files
120
218
  def build_manifest
121
219
  @build_manifest ||= get!(:build_manifest) || {}
122
220
  end
@@ -253,21 +351,6 @@ module Skypager
253
351
  end
254
352
  end
255
353
 
256
- def delete!
257
- directory = self.class.directory
258
- directory.delete(name)
259
- Skypager.config.set :sites_directory, directory
260
- end
261
-
262
- def save!
263
- directory = self.class.directory
264
- directory[name] = to_config
265
- Skypager.config.set :sites_directory, directory
266
- end
267
-
268
- def to_config
269
- @config
270
- end
271
354
 
272
355
  end
273
356
  end
@@ -48,7 +48,7 @@ module Skypager
48
48
  on_reset(path_prefix, cursor)
49
49
  end
50
50
 
51
- self.entries = Hashie::Mash.new({})
51
+ self.entries = {}.to_mash
52
52
 
53
53
  response["entries"].each do |entry|
54
54
  path, meta = entry
@@ -11,10 +11,16 @@ module Skypager
11
11
  @app = options[:app]
12
12
  end
13
13
 
14
+ def type
15
+ options[:type]
16
+ end
17
+
14
18
  # Used to generate the config line in the
15
19
  # middleman config.rb
16
20
  def config_line
17
- "dropbox_sync('#{ relative_local_path }','#{ remote_path }')"
21
+ if dropbox?
22
+ "dropbox_sync('#{ relative_local_path }','#{ remote_path }')"
23
+ end
18
24
  end
19
25
 
20
26
  # Gets the reference to the dropbox folder settings for the app
@@ -0,0 +1,55 @@
1
+ module Skypager
2
+ module Sync
3
+ class Github
4
+ include Singleton
5
+
6
+ def self.method_missing(meth, *args, &block)
7
+ if client.respond_to?(meth)
8
+ return client.send(meth, *args, &block)
9
+ end
10
+
11
+ super
12
+ end
13
+
14
+ def self.client(options={})
15
+ @client ||= begin
16
+ instance.with_options(options)
17
+ end
18
+ end
19
+
20
+ def options
21
+ @options ||= {}
22
+ end
23
+
24
+ def with_options(opts={})
25
+ options.merge!(opts)
26
+ self
27
+ end
28
+
29
+ def api
30
+ @api ||= begin
31
+ Octokit::Client.new(access_token: Skypager.config.github_access_token)
32
+ end
33
+ end
34
+
35
+ def setup(options={})
36
+ access_token = options[:github_access_token] || Skypager.config.github_access_token
37
+
38
+ unless access_token.to_s.length == 40
39
+ puts "You should generate an access token to use with the Github client."
40
+ puts "Access tokens allow you to revoke and/or limit access if needed."
41
+ puts "To learn more about access tokens, and how to generate them, visit: https://help.github.com/articles/creating-an-access-token-for-command-line-use/"
42
+
43
+ access_token = ask("Enter a 40 character access token when you have one", String)
44
+ end
45
+
46
+ unless access_token.to_s.length == 40
47
+ puts "Can not proceed without a valid access token: error code #{ access_token.length }"
48
+ return
49
+ end
50
+
51
+ Skypager.config.set(:github_access_token, access_token)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,3 +1,3 @@
1
1
  module Skypager
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/skypager.gemspec CHANGED
@@ -18,19 +18,26 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency 'hashie', '~> 0'
22
- spec.add_dependency 'commander', '~> 0'
23
- spec.add_dependency 'fog', '~> 0'
24
- spec.add_dependency 'dropbox-api', '~> 0.4'
25
- spec.add_dependency 'google_drive', '~> 0'
26
- spec.add_dependency 'middleman', '~> 0'
27
- spec.add_dependency 'rack-contrib', '~> 0'
28
- spec.add_dependency 'launchy', '~> 0'
29
- spec.add_dependency 'activesupport', '~> 0'
30
- spec.add_dependency 'axlsx', '~> 0'
31
- spec.add_dependency 'uri_template', '~> 0'
32
- spec.add_dependency 'dnsimple-ruby', '~> 0'
33
- spec.add_dependency 'rack-proxy', '~> 0'
21
+ spec.add_dependency 'hashie'
22
+ spec.add_dependency 'commander'
23
+ spec.add_dependency 'fog'
24
+ spec.add_dependency 'dropbox-api'
25
+ spec.add_dependency 'google_drive'
26
+ spec.add_dependency 'middleman'
27
+ spec.add_dependency 'rack-contrib'
28
+ spec.add_dependency 'launchy'
29
+ spec.add_dependency 'activesupport', '>= 4.0.0'
30
+ spec.add_dependency 'axlsx'
31
+ spec.add_dependency 'uri_template'
32
+ spec.add_dependency 'dnsimple-ruby'
33
+ spec.add_dependency 'rack-proxy'
34
+ spec.add_dependency 'octokit', '>= 3.0.0'
35
+ spec.add_dependency 'whenever'
36
+
37
+ # If I ever wanted to try and bundle up the build server
38
+ # sweep utility, instead of making it an external cron job
39
+ # spec.add_dependency 'spawnling', '~> 2.1.5'
40
+ # spec.add_dependency 'eventmachine'
34
41
 
35
42
  spec.add_dependency "aws-sdk-core", "2.0.0.rc8"
36
43
 
@@ -39,4 +46,5 @@ Gem::Specification.new do |spec|
39
46
  spec.add_development_dependency "pry", '~> 0'
40
47
  spec.add_development_dependency "pry-nav", '~> 0'
41
48
  spec.add_development_dependency "rack-test", '~> 0'
49
+ spec.add_development_dependency 'rspec', '~> 3.0'
42
50
  end
@@ -0,0 +1,18 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the build directory
11
+ /build
12
+
13
+ # Ignore cache
14
+ /.sass-cache
15
+ /.cache
16
+
17
+ # Ignore .DS_store file
18
+ .DS_Store
@@ -0,0 +1,14 @@
1
+ # If you do not have OpenSSL installed, update
2
+ # the following line to use "http://" instead
3
+ source 'https://rubygems.org'
4
+
5
+ gem "middleman", "~>3.3.7"
6
+
7
+ # Live-reloading plugin
8
+ gem "middleman-livereload", "~> 3.1.0"
9
+
10
+ # For faster file watcher updates on Windows:
11
+ gem "wdm", "~> 0.1.0", :platforms => [:mswin, :mingw]
12
+
13
+ # Windows does not come with time zone data
14
+ gem "tzinfo-data", platforms: [:mswin, :mingw]
@@ -0,0 +1,13 @@
1
+ require "skypager"
2
+
3
+ activate :skypager, site_name: "site-one"
4
+
5
+ activate :directory_indexes
6
+
7
+ set :css_dir, 'stylesheets'
8
+ set :js_dir, 'javascripts'
9
+ set :images_dir, 'images'
10
+
11
+ configure :build do
12
+
13
+ end
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Welcome to Middleman
3
+ ---
4
+
5
+ <div class="welcome">
6
+ <h1>Middleman is Watching</h1>
7
+ <p class="doc">
8
+ <%= link_to "Read Online Documentation", "http://middlemanapp.com/" %>
9
+ </p><!-- .doc -->
10
+ </div><!-- .welcome -->
@@ -0,0 +1 @@
1
+ //= require_tree .
@@ -0,0 +1,19 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+
6
+ <!-- Always force latest IE rendering engine or request Chrome Frame -->
7
+ <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
8
+
9
+ <!-- Use title if it's in the page YAML frontmatter -->
10
+ <title><%= current_page.data.title || "The Middleman" %></title>
11
+
12
+ <%= stylesheet_link_tag "normalize", "all" %>
13
+ <%= javascript_include_tag "all" %>
14
+ </head>
15
+
16
+ <body class="<%= page_classes %>">
17
+ <%= yield %>
18
+ </body>
19
+ </html>
@@ -0,0 +1,55 @@
1
+ @charset "utf-8";
2
+
3
+ body {
4
+ background: #d4d4d4 url("../images/background.png");
5
+ text-align: center;
6
+ font-family: sans-serif; }
7
+
8
+ h1 {
9
+ color: rgba(0, 0, 0, .3);
10
+ font-weight: bold;
11
+ font-size: 32px;
12
+ letter-spacing: -1px;
13
+ text-transform: uppercase;
14
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
15
+ background: url("../images/middleman.png") no-repeat center 100px;
16
+ padding: 350px 0 10px;
17
+ margin: 0; }
18
+
19
+ .doc {
20
+ font-size: 14px;
21
+ margin: 0; }
22
+ .doc:before,
23
+ .doc:after {
24
+ opacity: .2;
25
+ padding: 6px;
26
+ font-style: normal;
27
+ position: relative;
28
+ content: "•"; }
29
+ .doc a {
30
+ color: rgba(0, 0, 0, 0.3); }
31
+ .doc a:hover {
32
+ color: #666; }
33
+
34
+ .welcome {
35
+ -webkit-animation-name: welcome;
36
+ -webkit-animation-duration: .9s; }
37
+
38
+ @-webkit-keyframes welcome {
39
+ from {
40
+ -webkit-transform: scale(0);
41
+ opacity: 0;
42
+ }
43
+ 50% {
44
+ -webkit-transform: scale(0);
45
+ opacity: 0;
46
+ }
47
+ 82.5% {
48
+ -webkit-transform: scale(1.03);
49
+ -webkit-animation-timing-function: ease-out;
50
+ opacity: 1;
51
+ }
52
+ to {
53
+ -webkit-transform: scale(1);
54
+ }
55
+ }