skypager 0.0.4 → 0.0.5

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.
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
+ }