glitter 0.0.1 → 0.0.2
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/.gitignore +1 -0
- data/README.md +2 -4
- data/glitter.gemspec +1 -1
- data/lib/glitter.rb +82 -52
- data/lib/glitter/templates/Glitterfile +1 -2
- data/lib/glitter/templates/rss.xml.erb +21 -0
- data/lib/glitter/version.rb +1 -1
- data/spec/lib/glitter_spec.rb +20 -28
- metadata +6 -6
- data/lib/glitter/templates/rss.xml +0 -14
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -17,14 +17,12 @@ It should also be noted that Glitter uses HTTPS S3 URLs to eliminate the need fo
|
|
17
17
|
3. Edit the Glitterfile
|
18
18
|
|
19
19
|
# After you configure this file, deploy your app with `glitter push`
|
20
|
-
|
21
20
|
name "My App"
|
22
|
-
version "1.0.0"
|
21
|
+
version "1.0.0" # Don't forget, its ruby! This could read a version from a plist file
|
23
22
|
archive "my_app.zip"
|
24
|
-
release_notes "http://myapp.com/release_notes/"
|
25
23
|
|
26
24
|
s3 {
|
27
|
-
|
25
|
+
bucket_name "my_app"
|
28
26
|
access_key "access"
|
29
27
|
secret_access_key "sekret"
|
30
28
|
}
|
data/glitter.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.description = %q{Glitter makes it easy to publish software updates via the Sparkle framework by using S3 buckets.}
|
14
14
|
|
15
15
|
s.rubyforge_project = "glitter"
|
16
|
-
s.add_dependency "
|
16
|
+
s.add_dependency "s3"
|
17
17
|
s.add_dependency "haml"
|
18
18
|
s.add_dependency "thor"
|
19
19
|
|
data/lib/glitter.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 's3'
|
2
2
|
require 'thor'
|
3
3
|
require 'erb'
|
4
4
|
|
@@ -41,81 +41,114 @@ module Glitter
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
# The
|
45
|
-
class
|
44
|
+
# The App class that a release uses to deploy
|
45
|
+
class App
|
46
46
|
TemplatePath = File.expand_path('../glitter/templates/Glitterfile', __FILE__).to_s.freeze
|
47
|
+
RssTemplate = File.expand_path('../glitter/templates/rss.xml.erb', __FILE__).to_s.freeze
|
48
|
+
AppcastXml = 'appcast.xml'
|
47
49
|
|
48
50
|
include Configurable
|
49
|
-
attr_configurable :name, :version, :archive, :
|
51
|
+
attr_configurable :name, :version, :archive, :s3
|
50
52
|
|
51
53
|
class S3
|
52
54
|
include Configurable
|
53
|
-
attr_configurable :
|
55
|
+
attr_configurable :bucket_name, :access_key, :secret_access_key
|
54
56
|
|
55
|
-
def
|
56
|
-
{
|
57
|
+
def url_for(path)
|
58
|
+
"https://s3.amazonaws.com/#{bucket_name}/#{path}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def service
|
62
|
+
@service ||= ::S3::Service.new(:access_key_id => access_key, :secret_access_key => secret_access_key)
|
63
|
+
end
|
64
|
+
|
65
|
+
def bucket
|
66
|
+
service.buckets.find(bucket_name)
|
57
67
|
end
|
58
68
|
end
|
59
69
|
|
60
70
|
def s3(&block)
|
61
71
|
@s3 ||= S3.configure(&block)
|
62
72
|
end
|
63
|
-
end
|
64
73
|
|
65
|
-
|
66
|
-
|
74
|
+
class Appcast
|
75
|
+
ObjectName = 'appcast.xml'
|
76
|
+
|
77
|
+
attr_reader :app
|
67
78
|
|
68
|
-
|
79
|
+
def initialize(app)
|
80
|
+
@app = app
|
81
|
+
end
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
def url
|
84
|
+
app.s3.url_for ObjectName
|
85
|
+
end
|
86
|
+
|
87
|
+
def push
|
88
|
+
object.content = rss
|
89
|
+
object.save
|
90
|
+
end
|
91
|
+
|
92
|
+
def rss
|
93
|
+
@rss ||= ERB.new(File.read(RssTemplate)).result(binding)
|
94
|
+
end
|
73
95
|
|
74
|
-
|
75
|
-
|
76
|
-
|
96
|
+
private
|
97
|
+
def object
|
98
|
+
@object ||= app.s3.bucket.objects.build(ObjectName)
|
99
|
+
end
|
77
100
|
end
|
78
101
|
|
79
|
-
def
|
80
|
-
|
102
|
+
def appcast
|
103
|
+
@appcast ||= Appcast.new(self)
|
81
104
|
end
|
82
105
|
|
83
|
-
def
|
84
|
-
|
106
|
+
def head
|
107
|
+
releases[version]
|
85
108
|
end
|
86
109
|
|
87
|
-
def
|
88
|
-
|
110
|
+
def releases
|
111
|
+
@releases ||= Hash.new do |hash,key|
|
112
|
+
hash[key] = Release.new do |r|
|
113
|
+
r.version = key
|
114
|
+
r.app = self
|
115
|
+
end
|
116
|
+
end
|
89
117
|
end
|
118
|
+
end
|
90
119
|
|
91
|
-
|
92
|
-
|
120
|
+
class Release
|
121
|
+
attr_accessor :app, :version, :notes, :published_at
|
122
|
+
attr_reader :object
|
123
|
+
|
124
|
+
def initialize
|
125
|
+
@published_at = Time.now
|
126
|
+
yield self if block_given?
|
93
127
|
end
|
94
128
|
|
95
|
-
def
|
96
|
-
|
129
|
+
def name
|
130
|
+
"#{app.name} #{version}"
|
97
131
|
end
|
98
132
|
|
99
|
-
def
|
100
|
-
|
133
|
+
def object_name
|
134
|
+
"#{name.gsub(/\s/,'-').downcase}#{File.extname(file.path)}"
|
101
135
|
end
|
102
136
|
|
103
|
-
def
|
104
|
-
@
|
137
|
+
def object
|
138
|
+
@object ||= app.s3.bucket.objects.build(object_name)
|
105
139
|
end
|
106
140
|
|
107
|
-
def
|
108
|
-
|
109
|
-
AWS::S3::S3Object.store('appcast.xml', to_rss, config.s3.bucket)
|
141
|
+
def url
|
142
|
+
app.s3.url_for object_name
|
110
143
|
end
|
111
144
|
|
112
|
-
def
|
113
|
-
|
145
|
+
def push
|
146
|
+
object.content = file
|
147
|
+
object.save
|
114
148
|
end
|
115
149
|
|
116
|
-
|
117
|
-
|
118
|
-
"https://s3.amazonaws.com/#{config.s3.bucket}/#{path}"
|
150
|
+
def file
|
151
|
+
File.new(app.archive)
|
119
152
|
end
|
120
153
|
end
|
121
154
|
|
@@ -127,24 +160,21 @@ module Glitter
|
|
127
160
|
puts "Writing new Glitterfile to #{File.expand_path glitterfile_path}"
|
128
161
|
|
129
162
|
File.open glitterfile_path, 'w+' do |file|
|
130
|
-
file.write File.read(
|
131
|
-
end
|
163
|
+
file.write File.read(App::TemplatePath)
|
164
|
+
end
|
132
165
|
end
|
133
166
|
|
134
|
-
desc "push", "pushes a build to S3"
|
135
|
-
def push
|
136
|
-
puts "Pushing #{
|
137
|
-
|
138
|
-
|
167
|
+
desc "push RELEASE_NOTES", "pushes a build to S3 with release notes."
|
168
|
+
def push(release_notes)
|
169
|
+
puts "Pushing #{app.head.object_name} to bucket #{app.s3.bucket_name}..."
|
170
|
+
app.head.push
|
171
|
+
app.appcast.push
|
172
|
+
puts "App pushed to #{app.head.url}"
|
139
173
|
end
|
140
174
|
|
141
175
|
private
|
142
|
-
def
|
143
|
-
@config ||=
|
144
|
-
end
|
145
|
-
|
146
|
-
def release
|
147
|
-
@release ||= Release.new(config)
|
176
|
+
def app
|
177
|
+
@config ||= App.configure('./Glitterfile')
|
148
178
|
end
|
149
179
|
end
|
150
180
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
2
|
+
<channel>
|
3
|
+
<title><%= app.name %></title>
|
4
|
+
<link><%= app.appcast.url %></link>
|
5
|
+
<description>Software updates for <%= app.name %></description>
|
6
|
+
<language>en</language>
|
7
|
+
<% app.releases.each do |version, release| %>
|
8
|
+
<item>
|
9
|
+
<title>Version <%= version %></title>
|
10
|
+
<description>
|
11
|
+
<![CDATA[
|
12
|
+
<h2>New Features</h2>
|
13
|
+
<p><%= release.notes %></p>
|
14
|
+
]]>
|
15
|
+
</description>
|
16
|
+
<pubDate><%= release.published_at.strftime("%a, %d %b %Y %H:%M:%S %z") %></pubDate>
|
17
|
+
<enclosure url="<%= release.url %>" sparkle:version="2.0" length="<%= release.file.stat.size %>" type="application/octet-stream" />
|
18
|
+
</item>
|
19
|
+
<% end %>
|
20
|
+
</channel>
|
21
|
+
</rss>
|
data/lib/glitter/version.rb
CHANGED
data/spec/lib/glitter_spec.rb
CHANGED
@@ -1,36 +1,33 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rexml/document'
|
3
3
|
|
4
|
-
describe Glitter::
|
4
|
+
describe Glitter::App do
|
5
5
|
before(:all) do
|
6
|
-
@
|
6
|
+
@app = Glitter::App.configure do
|
7
7
|
name "My App"
|
8
8
|
version "1.0.0"
|
9
9
|
archive "lib/glitter.rb"
|
10
|
-
|
11
|
-
|
10
|
+
|
12
11
|
s3 {
|
13
|
-
|
12
|
+
bucket_name "my_app"
|
14
13
|
access_key "access"
|
15
14
|
secret_access_key "sekret"
|
16
15
|
}
|
17
|
-
|
18
|
-
end
|
16
|
+
end
|
19
17
|
|
20
|
-
|
21
|
-
@
|
18
|
+
# Leave this in this order to test sorting.
|
19
|
+
@app.releases["3.0"].notes = "I'm the newest and greatest of them all. 3.0 I am!"
|
20
|
+
@app.releases["1.0"].notes = "Hi dude, 1.0"
|
21
|
+
@app.releases["2.0"].notes = "I'm way better than 2.0"
|
22
22
|
end
|
23
23
|
|
24
|
-
it "should
|
25
|
-
|
24
|
+
it "should have head" do
|
25
|
+
@app.head.version.should eql("1.0.0")
|
26
26
|
end
|
27
27
|
|
28
|
-
it "should
|
29
|
-
@
|
28
|
+
it "should generate rss" do
|
29
|
+
REXML::Document.new(@app.appcast.rss).root.attributes["sparkle"].should eql('http://www.andymatuschak.org/xml-namespaces/sparkle')
|
30
30
|
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe Glitter::Configuration do
|
34
31
|
|
35
32
|
shared_examples_for "configuration" do
|
36
33
|
it "should read name" do
|
@@ -45,13 +42,9 @@ describe Glitter::Configuration do
|
|
45
42
|
@config.archive.should eql("my_app.zip")
|
46
43
|
end
|
47
44
|
|
48
|
-
it "should read release notes" do
|
49
|
-
@config.release_notes.should eql("http://myapp.com/release_notes/")
|
50
|
-
end
|
51
|
-
|
52
45
|
context "s3" do
|
53
|
-
it "should read
|
54
|
-
@config.s3.
|
46
|
+
it "should read bucket_name" do
|
47
|
+
@config.s3.bucket_name.should eql("my_app")
|
55
48
|
end
|
56
49
|
|
57
50
|
it "should read access_key" do
|
@@ -64,20 +57,19 @@ describe Glitter::Configuration do
|
|
64
57
|
end
|
65
58
|
|
66
59
|
it "should have a valid Glitterfile template path" do
|
67
|
-
File.exists?(Glitter::
|
60
|
+
File.exists?(Glitter::App::TemplatePath).should be_true
|
68
61
|
end
|
69
62
|
end
|
70
|
-
|
63
|
+
|
71
64
|
context "block configuration" do
|
72
65
|
before(:all) do
|
73
|
-
@config = Glitter::
|
66
|
+
@config = Glitter::App.configure do
|
74
67
|
name "My App"
|
75
68
|
version "1.0.0"
|
76
69
|
archive "my_app.zip"
|
77
|
-
release_notes "http://myapp.com/release_notes/"
|
78
70
|
|
79
71
|
s3 {
|
80
|
-
|
72
|
+
bucket_name "my_app"
|
81
73
|
access_key "access"
|
82
74
|
secret_access_key "sekret"
|
83
75
|
}
|
@@ -89,7 +81,7 @@ describe Glitter::Configuration do
|
|
89
81
|
|
90
82
|
context "file configuration" do
|
91
83
|
before(:all) do
|
92
|
-
@config = Glitter::
|
84
|
+
@config = Glitter::App.configure File.expand_path('../../../lib/glitter/templates/Glitterfile', __FILE__)
|
93
85
|
end
|
94
86
|
|
95
87
|
it_should_behave_like "configuration"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glitter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brad Gessler
|
@@ -15,11 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-07 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
22
|
+
name: s3
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
@@ -79,7 +79,7 @@ files:
|
|
79
79
|
- glitter.gemspec
|
80
80
|
- lib/glitter.rb
|
81
81
|
- lib/glitter/templates/Glitterfile
|
82
|
-
- lib/glitter/templates/rss.xml
|
82
|
+
- lib/glitter/templates/rss.xml.erb
|
83
83
|
- lib/glitter/version.rb
|
84
84
|
- spec/lib/glitter_spec.rb
|
85
85
|
- spec/spec_helper.rb
|
@@ -1,14 +0,0 @@
|
|
1
|
-
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
|
2
|
-
<channel>
|
3
|
-
<title><%= config.name %></title>
|
4
|
-
<link><%= appcast_url %></link>
|
5
|
-
<description>Software updates for <%= config.name %></description>
|
6
|
-
<language>en</language>
|
7
|
-
<item>
|
8
|
-
<title><%= name %></title>
|
9
|
-
<sparkle:releaseNotesLink><%= config.release_notes %></sparkle:releaseNotesLink>
|
10
|
-
<pubDate><%= pub_date %></pubDate>
|
11
|
-
<enclosure url="<%= url %>" sparkle:version="2.0" length="<%= file.stat.size %>" type="application/octet-stream" />
|
12
|
-
</item>
|
13
|
-
</channel>
|
14
|
-
</rss>
|