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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/ARCHITECTURE.md +34 -0
- data/CONTRIBUTING.md +7 -0
- data/README.md +94 -36
- data/Rakefile +1 -1
- data/lib/skypager.rb +6 -0
- data/lib/skypager/builder.rb +158 -0
- data/lib/skypager/builder/server.rb +63 -0
- data/lib/skypager/builder/webhook_handler.rb +73 -0
- data/lib/skypager/cli/commands/build.rb +48 -0
- data/lib/skypager/cli/commands/config.rb +1 -1
- data/lib/skypager/cli/commands/setup.rb +13 -0
- data/lib/skypager/cli/commands/site.rb +22 -0
- data/lib/skypager/cli/commands/sync.rb +1 -1
- data/lib/skypager/configuration.rb +32 -7
- data/lib/skypager/core_ext.rb +6 -0
- data/lib/skypager/data/google_spreadsheet.rb +3 -3
- data/lib/skypager/data/source.rb +24 -1
- data/lib/skypager/extension.rb +84 -21
- data/lib/skypager/proxy.rb +0 -1
- data/lib/skypager/router.rb +15 -0
- data/lib/skypager/site.rb +104 -21
- data/lib/skypager/sync/dropbox/delta.rb +1 -1
- data/lib/skypager/sync/folder.rb +7 -1
- data/lib/skypager/sync/github.rb +55 -0
- data/lib/skypager/version.rb +1 -1
- data/skypager.gemspec +21 -13
- data/spec/dummy/site-one/.gitignore +18 -0
- data/spec/dummy/site-one/Gemfile +14 -0
- data/spec/dummy/site-one/config.rb +13 -0
- data/spec/dummy/site-one/source/images/background.png +0 -0
- data/spec/dummy/site-one/source/images/middleman.png +0 -0
- data/spec/dummy/site-one/source/index.html.erb +10 -0
- data/spec/dummy/site-one/source/javascripts/all.js +1 -0
- data/spec/dummy/site-one/source/layouts/layout.erb +19 -0
- data/spec/dummy/site-one/source/stylesheets/all.css +55 -0
- data/spec/dummy/site-one/source/stylesheets/normalize.css +375 -0
- data/spec/lib/skypager/builder/server_spec.rb +5 -0
- data/spec/lib/skypager/configuration_spec.rb +7 -0
- data/spec/lib/skypager/site_spec.rb +40 -1
- data/spec/lib/skypager_spec.rb +9 -0
- data/spec/skypager-test-config.rb.example +22 -0
- data/spec/spec_helper.rb +38 -3
- data/spec/support/fixtures/cwd_config.json +3 -0
- data/spec/support/fixtures/home_config.json +1 -0
- metadata +112 -33
- data/lib/skypager/build_server.rb +0 -0
data/lib/skypager/proxy.rb
CHANGED
data/lib/skypager/router.rb
CHANGED
@@ -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 =
|
17
|
-
|
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
|
22
|
-
|
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
|
data/lib/skypager/sync/folder.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/skypager/version.rb
CHANGED
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'
|
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', '
|
30
|
-
spec.add_dependency 'axlsx'
|
31
|
-
spec.add_dependency 'uri_template'
|
32
|
-
spec.add_dependency 'dnsimple-ruby'
|
33
|
-
spec.add_dependency 'rack-proxy'
|
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]
|
Binary file
|
Binary file
|
@@ -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
|
+
}
|