lib/glitter.rb in glitter-1.0.0 vs lib/glitter.rb in glitter-2.0.0.alpha1

- old
+ new

@@ -1,209 +1,16 @@ -require 's3' -require 'thor' -require 'erb' +require 'glitter/version' module Glitter - # This mix-in Creates a DSL for configuring a class. - module Configurable - def self.included(base) - base.send :extend, ClassMethods - base.send :include, InstanceMethods - end - - module InstanceMethods - def configure(path=nil,&block) - path ? instance_eval(File.read(path), path) : instance_eval(&block) - self - end - end - - module ClassMethods - def attr_configurable(*attrs) - attrs.each do |attr| - class_eval %( - attr_writer :#{attr} - attr_overloaded :#{attr}) - end - end - - def attr_overloaded(*attrs) - attrs.each do |attr| - class_eval(%{ - def #{attr}(val=nil) - val ? instance_variable_set('@#{attr}', val) : instance_variable_get('@#{attr}') - end}) - end - end - - def configure(*args, &block) - new.configure(*args, &block) - end - end + ExistingReleaseError = Class.new(RuntimeError) + + # Relative paths for glitter. Mostly our templating engines use this. + def self.path(*segments) + File.join File.expand_path('../glitter', __FILE__), *segments end - # The App class that a release uses to deploy - class App - TemplatePath = File.expand_path('../glitter/templates/Glitterfile', __FILE__).to_s.freeze - RssTemplate = File.expand_path('../glitter/templates/rss.xml.erb', __FILE__).to_s.freeze - AppcastXml = 'appcast.xml' - - include Configurable - attr_configurable :name, :version, :short_version_string, :release_notes_link, :notes, :archive, :s3 - - class S3 - include Configurable - attr_configurable :bucket_name, :access_key, :secret_access_key, :subdomain_bucket - - def url_for(path) - if subdomain_bucket - "https://#{bucket_name}.s3.amazonaws.com/#{path}" - else - "https://s3.amazonaws.com/#{bucket_name}/#{path}" - end - end - - def service - @service ||= ::S3::Service.new(:access_key_id => access_key, :secret_access_key => secret_access_key, :use_ssl => true) - end - - def bucket - service.buckets.find(bucket_name) - end - end - - def s3(&block) - @s3 ||= S3.configure(&block) - end - - class Appcast - ObjectName = 'appcast.xml' - - attr_reader :app - - def initialize(app) - @app = app - end - - def url - app.s3.url_for ObjectName - end - - def push - object.content = rss - object.save - end - - def rss - @rss ||= ERB.new(File.read(RssTemplate)).result(binding) - end - - private - def object - @object ||= app.s3.bucket.objects.build(ObjectName) - end - end - - def appcast - @appcast ||= Appcast.new(self) - end - - def latest - assets[version] - end - - def assets - @assets ||= Hash.new do |hash,key| - hash[key] = Asset.new do |r| - r.version = key - r.short_version_string = short_version_string - r.release_notes_link = release_notes_link - r.notes = notes - r.app = self - end - end - end - end - - class Asset - attr_accessor :app, :version, :short_version_string, :release_notes_link, :notes, :published_at, :object - - def initialize - @published_at = Time.now - yield self if block_given? - end - - def name - "#{app.name} #{version}" - end - - def object_name - "#{name.gsub(/\s/,'-').downcase}#{File.extname(file.path)}" - end - - def object - @object ||= app.s3.bucket.objects.build(object_name) - end - - def url - app.s3.url_for object_name - end - - def push - object.content = file - object.save - self - end - - # Sets this asset as the head on the S3 bucket - def head - @head ||= self.class.new do |a| - a.app = app - a.version = "head" - a.short_version_string = short_version_string - a.release_notes_link = release_notes_link - a.notes = app.notes - a.published_at = published_at - a.object = object.copy(:key => a.object_name) - end - end - - def file - File.new(app.archive) - end - end - - # Command line interface for cutting glitter builds - class CLI < Thor - desc "init PATH", "Generate a Glitterfile for the path" - def init(path) - glitterfile_path = File.join(path, 'Glitterfile') - puts "Writing new Glitterfile to #{File.expand_path glitterfile_path}" - - File.open glitterfile_path, 'w+' do |file| - file.write File.read(App::TemplatePath) - end - end - - desc "push", "pushes a build to S3 with release notes." - method_option :release_notes, :type => :string, :aliases => "-m" - def push - puts "Pushing app #{app.latest.object_name}" - # Push the latest release with release notes - puts "Notes are the following" - puts app.notes - #app.latest.notes = options[:release_notes] if options[:release_notes] - app.latest.push - puts "Asset pushed to #{app.latest.url}" - app.latest.head # Sets this release as the head. - puts "Updated head #{app.latest.head.url} to #{app.latest.url}" - # Update the appcast file - app.appcast.push - puts "Updated #{app.appcast.url}" - end - - private - def app - @config ||= App.configure('./Glitterfile') - end - end + autoload :Configurable, Glitter.path('configurable') + autoload :Channel, Glitter.path('channel') + autoload :Release, Glitter.path('release') + autoload :Server, Glitter.path('server') + autoload :CLI, Glitter.path('cli') end