cloud_crooner 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0264cd064043ffa30c3b8e1f243c568614c33071
4
+ data.tar.gz: 5c5c511702a426b686d529d7e3d28b8eb219591c
5
+ SHA512:
6
+ metadata.gz: b56c82ae03ac812ba2b39c778ad0f619b62a4115e346d297b7c3b1c63cbfbe01f36d2fb444a14504fed8adc3c980e15e1f717e3a7ec251e087dbb02f2acb8e9c
7
+ data.tar.gz: 990555fd530e9372fe0efaacdb5a5c3609e990c1148eef286f734c93b59072b6cb13f1df9ac6e00b200af5d13f005705f161e4a7eda3191b4bf7b94f2661fd83
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.swp
19
+ tags
20
+ spec/rspec_output.txt
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --fail-fast
3
+ --format d
data/.rvmrc ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
+ # Only full ruby name is supported here, for short names use:
8
+ # echo "rvm use 2.0.0" > .rvmrc
9
+ environment_id="ruby-2.0.0-p247@cloud_crooner"
10
+
11
+ # Uncomment the following lines if you want to verify rvm version per project
12
+ # rvmrc_rvm_version="1.21.11 (stable)" # 1.10.1 seems like a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficient compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
+ then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+ for __hook in "${rvm_path:-$HOME/.rvm}/hooks/after_use"*
27
+ do
28
+ if [[ -f "${__hook}" && -x "${__hook}" && -s "${__hook}" ]]
29
+ then \. "${__hook}" || true
30
+ fi
31
+ done
32
+ unset __hook
33
+ if (( ${rvm_use_flag:=1} >= 2 )) # display only when forced
34
+ then
35
+ if [[ $- == *i* ]] # check for interactive shells
36
+ then printf "%b" "Using: \E[32m$GEM_HOME\E[0m
37
+ " # show the user the ruby and gemset they are using in green
38
+ else printf "%b" "Using: $GEM_HOME
39
+ " # don't use colors in non-interactive shells
40
+ fi
41
+ fi
42
+ else
43
+ # If the environment file has not yet been created, use the RVM CLI to select.
44
+ rvm --create "$environment_id" || {
45
+ echo "Failed to create RVM environment '${environment_id}'."
46
+ return 1
47
+ }
48
+ fi
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cloud_crooner.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 bambery
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # CloudCrooner
2
+
3
+ Manage your Sinatra app's assets with [Sprockets](https://github.com/sstephenson/sprockets) and sync them with [Amazon S3](http://aws.amazon.com/s3/).
4
+
5
+ Cloud Crooner will run a Sprockets instance and configure helpers for your views. Create a rake task to call the sync method to compile your assets and upload them to the cloud. The helpers will make sure you're pointing to the S3 assets in prod. Your assets will have appended to their names an MD5 hash of their contents which updates when your assets change, ensuring that your users will always be served the freshest assets without needing to worry about expiring caches.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'cloud_crooner'
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install cloud_crooner
20
+
21
+ ## Configuration
22
+
23
+ Cloud Crooner has many configuration options which can be set in a configure block:
24
+
25
+ CloudCrooner.configure do |config|
26
+ config.prefix = '/assets'
27
+ end
28
+
29
+ `remote_enabled` - true by default. When disabled, your assets will be served from your public folder instead of from S3. Only works in production. _Be aware that attempting to test this on your machine using rackup or thin will not work_. Rack does not serve files from `/public`. If you want to see static assets in action without messing with Rack internals, you must run [shotgun](https://github.com/rtomayko/shotgun) or something like it.
30
+
31
+ `public_folder` - the public folder of your application. By default set to `/public`. If you are using a different public folder, you must set it here as well as in your application.
32
+
33
+ `prefix` - the path from root where you keep your assets. By default it is `/assets`. Your compiled assets will be placed in `public_folder/prefix.` It will also be the pseudo-folder on S3 where your assets will be stored, so the paths will look something like `http://bucket-name.s3.amazonaws.com/prefix/filename`.
34
+
35
+ `sprockets` - by default, this will be your Sprockets environment and it will load paths the config option `asset_paths`.
36
+
37
+ `asset_paths` - the [load paths](https://github.com/sstephenson/sprockets#the-load-path) for your Sprockets instance. By default it will add the `prefix` directory.
38
+
39
+ `manifest` - the Sprockets manifest. By default, it will be created in `public_folder/prefix`. The manifest's location is also the folder where assets will be compiled to.
40
+
41
+ `assets_to_compile` - an array of the assets you would like compiled, given by their [logical Sprockets paths](https://github.com/sstephenson/sprockets#logical-paths). If Sprockets knows how to gzip your assets (it can do css and js by default), it will also gzip them.
42
+
43
+ `backups_to_keep` - the number of compiled asset backups to keep. Default is 2. When running the sync task, if an asset's content has changed, it will be recompiled. If there are already more than the set number of backups present, the oldest asset will be deleted locally, removed from the manifest, and deleted remotely.
44
+
45
+ `bucket_name` - the name of your AWS S3 bucket. [See below for details.](#hooking_up )
46
+
47
+ `region` - the region of your AWS S3 bucket. [See below for details.](#hooking_up )
48
+
49
+ `aws_access_id_key` - aws credentials. [See below for details.](#hooking_up )
50
+
51
+ `aws_secret_access_key` - aws credentials. [See below for details.](#hooking_up )
52
+
53
+ ### No Configuration
54
+
55
+ If you're keen to run everything on defaults, you will still need to run one command in order to get the helpers working:
56
+
57
+ CloudCrooner.configure_sprockets_helpers
58
+
59
+ Normally this is called at the end of the configure method.
60
+
61
+ ### <a id="hooking_up"></a>Hooking up with your Amazon S3 Account
62
+
63
+ After you have created an S3 account, [you will will be provided with an "access key id" and a "secret access key"](https://console.aws.amazon.com/iam/home?#security_credential). You will also need your bucket name and the bucket's region. One of the ways to find the region is by going to the [S3 console](https://console.aws.amazon.com/s3/) and checking the end of the URL: it will look something like us-west-1. Cloud Crooner will look for your AWS credentials in your ENV by default. _Do not put your credentials anywhere they can be checked into source control._ I would suggest loading them into the env with your bash login scripts. The env keys that will be checked by default are:
64
+
65
+ ENV["AWS_SECRET_ACCESS_KEY"] # the secret access key given by Amazon
66
+ ENV["AWS_ACCESS_KEY_ID"] # access key id given by Amazon
67
+ ENV["AWS_BUCKET_NAME"] # the name of your bucket
68
+ ENV["AWS_REGION"] # the region of your bucket
69
+
70
+ You may also set these in the Cloud Crooner config block, but please do not directly set the two Amazon credentials here.
71
+
72
+ CloudCrooner.configure do |config|
73
+ config.aws_secret_access_key = ENV["MY_AWS_SECRET"]
74
+ config.aws_access_key_id = ENV["MY_ACCESS_KEY"]
75
+ config.bucket_name = "super-cool-bucket"
76
+ config.aws_region = "eu-west-1"
77
+ end
78
+
79
+ ## Setting Up Your App:
80
+
81
+ I have thrown together a very simple application as an example.
82
+
83
+ In a file of your choosing (in this case `/config/cloud_crooner_config.rb`) run the configuration block with your desired settings.
84
+
85
+ require 'cloud_crooner'
86
+
87
+ CloudCrooner.configure do |config|
88
+ config.backups_to_keep = 1
89
+ config.asset_paths = %w( assets/stylesheets ) # assuming this is where I put my sass files
90
+ config.assets_to_compile %w( main.css ) # assuming this is the file I want to compile
91
+ end
92
+
93
+ In config.ru, require this file, and set up the following:
94
+
95
+ require './config/cloud_crooner_config.rb' # your Cloud Crooner config file
96
+ require './app.rb' # your app file
97
+
98
+ map '/' + CloudCrooner.prefix do
99
+ run CloudCrooner.sprockets
100
+ end
101
+
102
+ map '/' do
103
+ run App # your application class name
104
+ end
105
+
106
+ To compile and upload the assets, in your rakefile:
107
+
108
+ require './config/cloud_crooner_config.rb'
109
+
110
+ namespace :assets do
111
+ desc 'compile and sync assets' do
112
+ task :sync do
113
+ CloudCrooner.sync
114
+ end
115
+ end
116
+
117
+ Now on the command line, run `rake assets:sync` and the following will happen:
118
+
119
+ 1. new or changed assets will be compiled into `public/assets`
120
+ 2. assets will be uploaded to the S3 bucket, which is set in ENV elsewhere. If an asset has a gzipped file associated with it and the gzip is smaller than the original file, the gzip will be uploaded in its place
121
+ 3. manifest will be updated
122
+ 4. old backups locally and remotely will be deleted
123
+
124
+ Running your app in development mode will serve uncompiled assets locally (from `/assets`), and running your app in production mode will serve your compiled assets from S3. If you have `remote_assets` set to `false` and are in production mode, your compiled assets will be served from `public/assets`.
125
+
126
+ If you want to precompile and upload your assets every time you spin up your app, you can put the configure block directly into config.ru and after config run CloudCrooner.sync.
127
+
128
+ ## Notes About Sass and Sprockets
129
+
130
+ If you are using sass files, you should use the [ sprockets-sass ](https://github.com/petebrowne/sprockets-sass) and [ sass ](https://github.com/nex3/sass) gems to help Sprockets cope (sprockets-sass still necessary as of 06/30/13 for functional Sinatra @imports, email me if this changes).
131
+
132
+ Specifically for Sass files, do not use the Sprockets directives - use @include. See here for more details:
133
+
134
+ [Structure Your Sass Files with @import](http://pivotallabs.com/structure-your-sass-files-with-import/)
135
+
136
+ You can also set any sass (or other supported processor) specific options in your config.ru:
137
+ Sprockets::Sass.options[:style] = :compressed
138
+ See Sprockets for details.
139
+
140
+ ## Contributing
141
+
142
+ If there's a feature you'd like to see, when you create an issue, please supply a valid use case. If you'd like to fix a bug or add a feature yourself, please update relevant tests before submitting a pull request.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cloud_crooner/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cloud_crooner"
8
+ spec.version = CloudCrooner::VERSION
9
+ spec.authors = ["bambery"]
10
+ spec.email = ["lwszolek@gmail.com"]
11
+ spec.description = %q{Manage assets on Sinatra apps with Sprockets and S3}
12
+ spec.summary = %q{Manage assets with Sprockets, precompile them into static assets, then upload them to S3}
13
+ spec.homepage = "https://github.com/bambery/cloud_crooner"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "sinatra"
25
+ spec.add_development_dependency "test-construct"
26
+
27
+ spec.add_dependency "sprockets", "~>2.10"
28
+ spec.add_dependency "fog", "~> 1.12"
29
+ spec.add_dependency "sprockets-helpers"
30
+ end
@@ -0,0 +1,3 @@
1
+ require "cloud_crooner/version"
2
+ require 'cloud_crooner/storage'
3
+ require 'cloud_crooner/cloud_crooner'
@@ -0,0 +1,212 @@
1
+ require 'sprockets'
2
+ require 'sprockets-helpers'
3
+
4
+ module CloudCrooner
5
+
6
+ class FogSettingError < StandardError; end
7
+
8
+ VALID_AWS_REGIONS = %w(
9
+ us-west-2
10
+ us-west-1
11
+ eu-west-1
12
+ ap-southeast-1
13
+ ap-southeast-2
14
+ ap-northeast-1
15
+ sa-east-1
16
+ )
17
+
18
+ class << self
19
+
20
+ def configure(&proc)
21
+ yield self
22
+ configure_sprockets_helpers
23
+ end
24
+
25
+ def configure_sprockets_helpers
26
+ # if you're running fully on defaults, you must call this explicitly in config.ru if you want to use the helpers
27
+ Sprockets::Helpers.configure do |config|
28
+ if ENV['RACK_ENV'] == "production"
29
+ config.manifest = manifest
30
+ config.digest = true
31
+ config.debug = false
32
+ if remote_enabled?
33
+ config.asset_host = asset_host
34
+ else
35
+ config.public_path = public_folder
36
+ end
37
+ end
38
+ config.environment = sprockets
39
+ config.prefix = "/" + prefix
40
+ end
41
+ end
42
+
43
+ def storage
44
+ @storage ||= Storage.new
45
+ end
46
+
47
+ def remote_enabled?
48
+ # Disable this in prod if you want to serve compiled assets locally.
49
+ @remote_enabled.nil? ? (@remote_enabled = true) : @remote_enabled
50
+ end
51
+
52
+ def remote_enabled= (val)
53
+ @remote_enabled = val if [ true, false ].include?(val)
54
+ end
55
+
56
+ def sprockets
57
+ if @sprockets.nil?
58
+ @sprockets = Sprockets::Environment.new { |env| env.logger = Logger.new($stdout) }
59
+ asset_paths.each {|path| @sprockets.append_path(path)}
60
+ end
61
+ return @sprockets
62
+ end
63
+ attr_writer :sprockets
64
+
65
+ def manifest
66
+ @manifest ||= Sprockets::Manifest.new(sprockets, File.join(public_folder, prefix))
67
+ end
68
+ attr_writer :manifest
69
+
70
+ def prefix
71
+ @prefix ||= 'assets'
72
+ end
73
+
74
+ def prefix=(val)
75
+ #remove any slashes at beginning or end
76
+ @prefix = val.chomp('/').gsub(/^\//, "")
77
+ end
78
+
79
+ def public_folder
80
+ @public_folder ||= 'public'
81
+ end
82
+
83
+ def public_folder=(val)
84
+ #remove any slashes at beginning or end
85
+ @public_folder = val.chomp('/').gsub(/^\//, "")
86
+ end
87
+
88
+ def assets_to_compile
89
+ # list of assets to compile, given by their Sprocket's load path
90
+ # defaults to every file under the prefix directory
91
+ return @assets_to_compile if @assets_to_compile
92
+ files = Dir.glob(prefix + "**/*").select {|f| File.file?(f)}
93
+ files.collect! { |f| f.gsub(/^#{prefix}\//, "") }
94
+ end
95
+ attr_writer :assets_to_compile
96
+
97
+ # AWS bucket name, can be stored in ENV but can be overwritten in config block
98
+ # Defaults to ENV['AWS_BUCKET_NAME']
99
+ def bucket_name
100
+ if @bucket_name
101
+ return @bucket_name
102
+ elsif !ENV.has_key?('AWS_BUCKET_NAME')
103
+ raise FogSettingError, "Bucket name must be set in ENV or configure block"
104
+ end
105
+ @bucket_name = ENV['AWS_BUCKET_NAME']
106
+ end
107
+ attr_writer :bucket_name
108
+
109
+ # Region of your AWS bucket
110
+ # Defaults to looking in ENV but can be overwritten in config block
111
+ def region
112
+ if @region
113
+ return @region
114
+ elsif !ENV.has_key?('AWS_REGION')
115
+ raise FogSettingError, "AWS Region must be set in ENV or in configure block"
116
+ elsif !VALID_AWS_REGIONS.include?(ENV['AWS_REGION'])
117
+ raise FogSettingError, "Invalid region"
118
+ end
119
+ @region = ENV['AWS_REGION']
120
+ end
121
+
122
+ def region=(val)
123
+ VALID_AWS_REGIONS.include?(val) ? @region = val : (raise FogSettingError, "Invalid region")
124
+ end
125
+
126
+ # AWS access id key given by Amazon, should be stored in
127
+ # env but can be set to be elsewhere.
128
+ # Defaults to ENV["AWS_ACCESS_ID_KEY"]
129
+ def aws_access_key_id
130
+ if @aws_access_key_id
131
+ return @aws_access_key_id
132
+ elsif !ENV.has_key?('AWS_ACCESS_KEY_ID')
133
+ raise FogSettingError, "access key id must be set in ENV or configure block"
134
+ end
135
+ @aws_access_key_id ||= ENV['AWS_ACCESS_KEY_ID']
136
+ end
137
+ attr_writer :aws_access_key_id
138
+
139
+ # AWS secret access key given by Amazon, should be stored in env but can be set to be elsewhere
140
+ # Defaults to ENV["AWS_SECRET_ACCESS_KEY"]
141
+ def aws_secret_access_key
142
+ if @aws_secret_access_key
143
+ return @aws_secret_access_key
144
+ elsif !ENV.has_key?('AWS_SECRET_ACCESS_KEY')
145
+ raise FogSettingError, "secret access key must be set in ENV or configure block"
146
+ end
147
+ @aws_secret_access_key ||= ENV['AWS_SECRET_ACCESS_KEY']
148
+ end
149
+ attr_writer :aws_secret_access_key
150
+
151
+ def asset_paths
152
+ # logical paths to assets for use with Sprockets
153
+ # default: everything under the prefix dir
154
+ # note that if remote is enabled in prod, asset paths will be added, but the link helpers bypass sprockets and grab the manifest links, and will only fall back to the paths if the asset is not found in the manifest.
155
+ @asset_paths ||= [prefix]
156
+ end
157
+ attr_writer :asset_paths
158
+
159
+ def backups_to_keep
160
+ @backups_to_keep ||= 2
161
+ end
162
+ attr_writer :backups_to_keep
163
+
164
+ def fog_options
165
+ options = { :provider => provider, :aws_access_key_id => aws_access_key_id, :aws_secret_access_key => aws_secret_access_key, :region => region }
166
+ end
167
+
168
+ def compile_sprockets_assets
169
+ # compile the assets in the sprockets load path. Outputs to directory of manifest. Updates the manifest
170
+ manifest.compile(*self.assets_to_compile)
171
+ end
172
+
173
+ def clean_sprockets_assets
174
+ # if there are more backups than the requested number, delete the oldest from the file system and update the manifest
175
+ manifest.clean(backups_to_keep)
176
+ end
177
+
178
+ def clobber_sprockets_assets
179
+ # delete the manifest directory and everything in it
180
+ manifest.clobber
181
+ end
182
+
183
+ def sync
184
+ compile_sprockets_assets
185
+ clean_sprockets_assets
186
+
187
+ storage.upload_files
188
+ storage.clean_remote
189
+
190
+ end
191
+
192
+ def log(msg)
193
+ $stdout.puts msg
194
+ end
195
+
196
+ private
197
+
198
+ def provider
199
+ 'AWS'
200
+ end
201
+
202
+ def digest
203
+ true
204
+ end
205
+
206
+ def asset_host
207
+ @asset_host ||= "#{bucket_name}.s3.amazonaws.com"
208
+ end
209
+
210
+ end
211
+ end
212
+