brycethornton-integrity 0.1.7.1
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/README.markdown +66 -0
 - data/Rakefile +110 -0
 - data/VERSION.yml +4 -0
 - data/app.rb +137 -0
 - data/bin/integrity +4 -0
 - data/config/config.sample.ru +31 -0
 - data/config/config.sample.yml +38 -0
 - data/config/thin.sample.yml +13 -0
 - data/integrity.gemspec +76 -0
 - data/lib/integrity.rb +82 -0
 - data/lib/integrity/build.rb +61 -0
 - data/lib/integrity/core_ext/object.rb +6 -0
 - data/lib/integrity/core_ext/string.rb +5 -0
 - data/lib/integrity/helpers.rb +16 -0
 - data/lib/integrity/helpers/authorization.rb +33 -0
 - data/lib/integrity/helpers/breadcrumbs.rb +20 -0
 - data/lib/integrity/helpers/forms.rb +28 -0
 - data/lib/integrity/helpers/pretty_output.rb +45 -0
 - data/lib/integrity/helpers/rendering.rb +14 -0
 - data/lib/integrity/helpers/resources.rb +13 -0
 - data/lib/integrity/helpers/urls.rb +47 -0
 - data/lib/integrity/installer.rb +132 -0
 - data/lib/integrity/migrations.rb +152 -0
 - data/lib/integrity/notifier.rb +50 -0
 - data/lib/integrity/notifier/base.rb +55 -0
 - data/lib/integrity/project.rb +117 -0
 - data/lib/integrity/project_builder.rb +47 -0
 - data/lib/integrity/scm.rb +19 -0
 - data/lib/integrity/scm/git.rb +91 -0
 - data/lib/integrity/scm/git/uri.rb +57 -0
 - data/public/buttons.css +82 -0
 - data/public/reset.css +7 -0
 - data/public/spinner.gif +0 -0
 - data/test/helpers.rb +48 -0
 - data/test/helpers/acceptance.rb +126 -0
 - data/test/helpers/acceptance/git_helper.rb +99 -0
 - data/test/helpers/acceptance/textfile_notifier.rb +26 -0
 - data/test/helpers/expectations.rb +5 -0
 - data/test/helpers/expectations/be_a.rb +23 -0
 - data/test/helpers/expectations/change.rb +90 -0
 - data/test/helpers/expectations/have.rb +105 -0
 - data/test/helpers/expectations/have_tag.rb +128 -0
 - data/test/helpers/expectations/predicates.rb +37 -0
 - data/test/helpers/fixtures.rb +83 -0
 - data/views/_build_info.haml +18 -0
 - data/views/build.haml +2 -0
 - data/views/error.haml +36 -0
 - data/views/home.haml +23 -0
 - data/views/integrity.sass +387 -0
 - data/views/layout.haml +28 -0
 - data/views/new.haml +51 -0
 - data/views/not_found.haml +31 -0
 - data/views/notifier.haml +7 -0
 - data/views/project.builder +21 -0
 - data/views/project.haml +28 -0
 - data/views/unauthorized.haml +38 -0
 - metadata +243 -0
 
    
        data/lib/integrity.rb
    ADDED
    
    | 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            __DIR__ = File.dirname(__FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.unshift "#{__DIR__}/integrity", *Dir["#{__DIR__}/../vendor/**/lib"].to_a
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "rubygems"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "json"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "dm-core"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "dm-validations"
         
     | 
| 
      
 8 
     | 
    
         
            +
            require "dm-types"
         
     | 
| 
      
 9 
     | 
    
         
            +
            require "dm-timestamps"
         
     | 
| 
      
 10 
     | 
    
         
            +
            require "dm-aggregates"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            require "yaml"
         
     | 
| 
      
 13 
     | 
    
         
            +
            require "logger"
         
     | 
| 
      
 14 
     | 
    
         
            +
            require "digest/sha1"
         
     | 
| 
      
 15 
     | 
    
         
            +
            require "timeout"
         
     | 
| 
      
 16 
     | 
    
         
            +
            require "ostruct"
         
     | 
| 
      
 17 
     | 
    
         
            +
            require "fileutils"
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            require "core_ext/object"
         
     | 
| 
      
 20 
     | 
    
         
            +
            require "core_ext/string"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            require "project"
         
     | 
| 
      
 23 
     | 
    
         
            +
            require "build"
         
     | 
| 
      
 24 
     | 
    
         
            +
            require "project_builder"
         
     | 
| 
      
 25 
     | 
    
         
            +
            require "scm"
         
     | 
| 
      
 26 
     | 
    
         
            +
            require "scm/git"
         
     | 
| 
      
 27 
     | 
    
         
            +
            require "notifier"
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 30 
     | 
    
         
            +
              def self.new(config_file = nil)
         
     | 
| 
      
 31 
     | 
    
         
            +
                self.config = config_file unless config_file.nil?
         
     | 
| 
      
 32 
     | 
    
         
            +
                DataMapper.logger = self.logger if config[:log_debug_info]
         
     | 
| 
      
 33 
     | 
    
         
            +
                DataMapper.setup(:default, config[:database_uri])
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              def self.root
         
     | 
| 
      
 37 
     | 
    
         
            +
                File.expand_path(File.join(File.dirname(__FILE__), ".."))
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              def self.default_configuration
         
     | 
| 
      
 41 
     | 
    
         
            +
                @defaults ||= { :database_uri      => "sqlite3::memory:",
         
     | 
| 
      
 42 
     | 
    
         
            +
                                :export_directory  => root / "exports",
         
     | 
| 
      
 43 
     | 
    
         
            +
                                :log               => STDOUT,
         
     | 
| 
      
 44 
     | 
    
         
            +
                                :base_uri          => "http://localhost:8910",
         
     | 
| 
      
 45 
     | 
    
         
            +
                                :use_basic_auth    => false,
         
     | 
| 
      
 46 
     | 
    
         
            +
                                :build_all_commits => true,
         
     | 
| 
      
 47 
     | 
    
         
            +
                                :log_debug_info    => false }
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              def self.config
         
     | 
| 
      
 51 
     | 
    
         
            +
                @config ||= default_configuration
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              def self.config=(file)
         
     | 
| 
      
 55 
     | 
    
         
            +
                @config = default_configuration.merge(YAML.load_file(file))
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              def self.log(message, &block)
         
     | 
| 
      
 59 
     | 
    
         
            +
                logger.info(message, &block)
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              def self.logger
         
     | 
| 
      
 63 
     | 
    
         
            +
                @logger ||= Logger.new(config[:log], "daily").tap do |logger|
         
     | 
| 
      
 64 
     | 
    
         
            +
                  logger.formatter = LogFormatter.new
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              def self.version
         
     | 
| 
      
 69 
     | 
    
         
            +
                @version ||= begin
         
     | 
| 
      
 70 
     | 
    
         
            +
                  file = YAML.load_file(Integrity.root / "VERSION.yml")
         
     | 
| 
      
 71 
     | 
    
         
            +
                  "#{file['major']}.#{file['minor']}.#{file['patch']}"
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
              private
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                class LogFormatter < Logger::Formatter
         
     | 
| 
      
 78 
     | 
    
         
            +
                  def call(severity, time, progname, msg)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    time.strftime("[%H:%M:%S] ") + msg2str(msg) + "\n"
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Build
         
     | 
| 
      
 3 
     | 
    
         
            +
                include DataMapper::Resource
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                property :id,                Serial
         
     | 
| 
      
 6 
     | 
    
         
            +
                property :output,            Text,     :nullable => false, :default => ""
         
     | 
| 
      
 7 
     | 
    
         
            +
                property :successful,        Boolean,  :nullable => false, :default => false
         
     | 
| 
      
 8 
     | 
    
         
            +
                property :commit_identifier, String,   :nullable => false
         
     | 
| 
      
 9 
     | 
    
         
            +
                property :commit_metadata,   Yaml,     :nullable => false, :lazy => false
         
     | 
| 
      
 10 
     | 
    
         
            +
                property :created_at,        DateTime
         
     | 
| 
      
 11 
     | 
    
         
            +
                property :updated_at,        DateTime
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                belongs_to :project, :class_name => "Integrity::Project"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def failed?
         
     | 
| 
      
 16 
     | 
    
         
            +
                  !successful?
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def status
         
     | 
| 
      
 20 
     | 
    
         
            +
                  successful? ? :success : :failed
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def human_readable_status
         
     | 
| 
      
 24 
     | 
    
         
            +
                  successful? ? "Build Successful" : "Build Failed"
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def short_commit_identifier
         
     | 
| 
      
 28 
     | 
    
         
            +
                  sha1?(commit_identifier) ? commit_identifier[0..6] : commit_identifier
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                
         
     | 
| 
      
 31 
     | 
    
         
            +
                def commit_metadata
         
     | 
| 
      
 32 
     | 
    
         
            +
                  case data = attribute_get(:commit_metadata)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    when String; YAML.load(data)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    else data
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def commit_author
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @author ||= begin
         
     | 
| 
      
 40 
     | 
    
         
            +
                    commit_metadata[:author] =~ /^(.*) <(.*)>$/
         
     | 
| 
      
 41 
     | 
    
         
            +
                    OpenStruct.new(:name => $1.strip, :email => $2.strip, :full => commit_metadata[:author])
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def commit_message
         
     | 
| 
      
 46 
     | 
    
         
            +
                  commit_metadata[:message]
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def commited_at
         
     | 
| 
      
 50 
     | 
    
         
            +
                  case commit_metadata[:date]
         
     | 
| 
      
 51 
     | 
    
         
            +
                    when String then Time.parse(commit_metadata[:date])
         
     | 
| 
      
 52 
     | 
    
         
            +
                    else commit_metadata[:date]
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                private
         
     | 
| 
      
 57 
     | 
    
         
            +
                  def sha1?(string)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    string =~ /^[a-f0-9]{40}$/
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Dir["#{File.dirname(__FILE__)}/helpers/*.rb"].each &method(:require)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Helpers  
         
     | 
| 
      
 5 
     | 
    
         
            +
                include Authorization
         
     | 
| 
      
 6 
     | 
    
         
            +
                include Breadcrumbs
         
     | 
| 
      
 7 
     | 
    
         
            +
                include Forms
         
     | 
| 
      
 8 
     | 
    
         
            +
                include PrettyOutput
         
     | 
| 
      
 9 
     | 
    
         
            +
                include Rendering
         
     | 
| 
      
 10 
     | 
    
         
            +
                include Resources
         
     | 
| 
      
 11 
     | 
    
         
            +
                include Urls
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
                include Rack::Utils
         
     | 
| 
      
 14 
     | 
    
         
            +
                alias :h :escape_html
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "diddies"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Authorization
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Sinatra::Authorization
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def authorization_realm
         
     | 
| 
      
 9 
     | 
    
         
            +
                    "Integrity"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def authorized?
         
     | 
| 
      
 13 
     | 
    
         
            +
                    return true unless Integrity.config[:use_basic_auth]
         
     | 
| 
      
 14 
     | 
    
         
            +
                    !!request.env["REMOTE_USER"]
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def authorize(user, password)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    if Integrity.config[:hash_admin_password]
         
     | 
| 
      
 19 
     | 
    
         
            +
                      password = Digest::SHA1.hexdigest(password)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    !Integrity.config[:use_basic_auth] ||
         
     | 
| 
      
 23 
     | 
    
         
            +
                    (Integrity.config[:admin_username] == user &&
         
     | 
| 
      
 24 
     | 
    
         
            +
                      Integrity.config[:admin_password] == password)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def unauthorized!(realm=authorization_realm)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    response["WWW-Authenticate"] = %(Basic realm="#{realm}")
         
     | 
| 
      
 29 
     | 
    
         
            +
                    throw :halt, [401, show(:unauthorized, :title => "incorrect credentials")]
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Breadcrumbs
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def pages
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @pages ||= [["projects", "/"], ["new project", "/new"]]
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def breadcrumbs(*crumbs)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    crumbs[0..-2].map do |crumb|
         
     | 
| 
      
 10 
     | 
    
         
            +
                      if page_data = pages.detect {|c| c.first == crumb }
         
     | 
| 
      
 11 
     | 
    
         
            +
                        %Q(<a href="#{page_data.last}">#{page_data.first}</a>)
         
     | 
| 
      
 12 
     | 
    
         
            +
                      elsif @project && @project.permalink == crumb
         
     | 
| 
      
 13 
     | 
    
         
            +
                        %Q(<a href="#{project_url(@project)}">#{@project.permalink}</a>)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      end
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end + [crumbs.last]
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Forms
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def errors_on(object, field)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    return "" unless errors = object.errors.on(field)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    errors.map {|e| e.gsub(/#{field} /i, "") }.join(", ")
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def error_class(object, field)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    object.errors.on(field).nil? ? "" : "with_errors"
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def checkbox(name, condition, extras={})
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attrs = { :name => name, :type => "checkbox", :value => "1" }
         
     | 
| 
      
 15 
     | 
    
         
            +
                    attrs.merge!(:checked => condition ? true : nil)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    attrs.merge(extras)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def notifier_form(notifier)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    haml(notifier.to_haml, :layout => :notifier, :locals => {
         
     | 
| 
      
 21 
     | 
    
         
            +
                      :config => current_project.config_for(notifier),
         
     | 
| 
      
 22 
     | 
    
         
            +
                      :notifier => "#{notifier.to_s.split(/::/).last}",
         
     | 
| 
      
 23 
     | 
    
         
            +
                      :enabled => current_project.notifies?(notifier)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    })
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module PrettyOutput
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def cycle(*values)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @cycles ||= {}
         
     | 
| 
      
 6 
     | 
    
         
            +
                    @cycles[values] ||= -1 # first value returned is 0
         
     | 
| 
      
 7 
     | 
    
         
            +
                    next_value = @cycles[values] = (@cycles[values] + 1) % values.size
         
     | 
| 
      
 8 
     | 
    
         
            +
                    values[next_value]
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def bash_color_codes(string)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    string.gsub("\e[0m", '</span>').
         
     | 
| 
      
 13 
     | 
    
         
            +
                      gsub("\e[31m", '<span class="color31">').
         
     | 
| 
      
 14 
     | 
    
         
            +
                      gsub("\e[32m", '<span class="color32">').
         
     | 
| 
      
 15 
     | 
    
         
            +
                      gsub("\e[33m", '<span class="color33">').
         
     | 
| 
      
 16 
     | 
    
         
            +
                      gsub("\e[34m", '<span class="color34">').
         
     | 
| 
      
 17 
     | 
    
         
            +
                      gsub("\e[35m", '<span class="color35">').
         
     | 
| 
      
 18 
     | 
    
         
            +
                      gsub("\e[36m", '<span class="color36">').
         
     | 
| 
      
 19 
     | 
    
         
            +
                      gsub("\e[37m", '<span class="color37">')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  def pretty_date(date_time)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    days_away = (Date.today - Date.new(date_time.year, date_time.month, date_time.day)).to_i
         
     | 
| 
      
 24 
     | 
    
         
            +
                    if days_away == 0
         
     | 
| 
      
 25 
     | 
    
         
            +
                      "today"
         
     | 
| 
      
 26 
     | 
    
         
            +
                    elsif days_away == 1
         
     | 
| 
      
 27 
     | 
    
         
            +
                      "yesterday"
         
     | 
| 
      
 28 
     | 
    
         
            +
                    else
         
     | 
| 
      
 29 
     | 
    
         
            +
                      strftime_with_ordinal(date_time, "on %b %d%o")
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def strftime_with_ordinal(date_time, format_string)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    ordinal = case date_time.day
         
     | 
| 
      
 35 
     | 
    
         
            +
                      when 1, 21, 31 then "st"
         
     | 
| 
      
 36 
     | 
    
         
            +
                      when 2, 22     then "nd"
         
     | 
| 
      
 37 
     | 
    
         
            +
                      when 3, 23     then "rd"
         
     | 
| 
      
 38 
     | 
    
         
            +
                      else                "th"
         
     | 
| 
      
 39 
     | 
    
         
            +
                    end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                    date_time.strftime(format_string.gsub("%o", ordinal))
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Rendering
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def show(view, options={})
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @title = breadcrumbs(*options[:title])
         
     | 
| 
      
 6 
     | 
    
         
            +
                    haml view
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def partial(template, locals={})
         
     | 
| 
      
 10 
     | 
    
         
            +
                    haml("_#{template}".to_sym, :locals => locals, :layout => false)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Resources
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def current_project
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @project ||= Project.first(:permalink => params[:project]) or raise Sinatra::NotFound
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def current_build
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @build ||= current_project.builds.first(:commit_identifier => params[:build]) or raise Sinatra::NotFound
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Helpers
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Urls
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def url(path)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    url = "#{request.scheme}://#{request.host}"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    if request.scheme == "https" && request.port != 443 ||
         
     | 
| 
      
 8 
     | 
    
         
            +
                        request.scheme == "http" && request.port != 80
         
     | 
| 
      
 9 
     | 
    
         
            +
                      url << ":#{request.port}"
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    url << "/" unless path.index("/").zero?
         
     | 
| 
      
 13 
     | 
    
         
            +
                    url << path
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def root_url
         
     | 
| 
      
 17 
     | 
    
         
            +
                    url("/")
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def project_path(project, *path)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    "/" << [project.permalink, *path].join("/")
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def project_url(project, *path)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    url project_path(project, *path)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def push_url_for(project)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    Addressable::URI.parse(project_url(project, "push")).tap do |url|
         
     | 
| 
      
 30 
     | 
    
         
            +
                      if Integrity.config[:use_basic_auth]
         
     | 
| 
      
 31 
     | 
    
         
            +
                        url.user     = Integrity.config[:admin_username]
         
     | 
| 
      
 32 
     | 
    
         
            +
                        url.password = Integrity.config[:hash_admin_password] ?
         
     | 
| 
      
 33 
     | 
    
         
            +
                          "<password>" : Integrity.config[:admin_password]
         
     | 
| 
      
 34 
     | 
    
         
            +
                      end
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end.to_s
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                  def build_path(build)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    "/#{build.project.permalink}/builds/#{build.commit_identifier}"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def build_url(build)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    url build_path(build)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,132 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + "/../integrity"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "thor"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Integrity
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Installer < Thor
         
     | 
| 
      
 6 
     | 
    
         
            +
                include FileUtils
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                desc "install [PATH]",
         
     | 
| 
      
 9 
     | 
    
         
            +
                   "Copy template files to PATH. Next, go there and edit them."
         
     | 
| 
      
 10 
     | 
    
         
            +
                def install(path)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @root = File.expand_path(path)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  create_dir_structure
         
     | 
| 
      
 14 
     | 
    
         
            +
                  copy_template_files
         
     | 
| 
      
 15 
     | 
    
         
            +
                  edit_template_files
         
     | 
| 
      
 16 
     | 
    
         
            +
                  create_db(root / "config.yml")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  after_setup_message
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                desc "create_db [CONFIG]",
         
     | 
| 
      
 21 
     | 
    
         
            +
                     "Checks the `database_uri` in CONFIG and creates and bootstraps a database for integrity"
         
     | 
| 
      
 22 
     | 
    
         
            +
                def create_db(config, direction="up")
         
     | 
| 
      
 23 
     | 
    
         
            +
                  Integrity.new(config)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  migrate_db(direction)
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                desc "version",
         
     | 
| 
      
 28 
     | 
    
         
            +
                     "Print the current integrity version"
         
     | 
| 
      
 29 
     | 
    
         
            +
                def version
         
     | 
| 
      
 30 
     | 
    
         
            +
                  puts Integrity.version
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                private
         
     | 
| 
      
 34 
     | 
    
         
            +
                  attr_reader :root
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def migrate_db(direction="up")
         
     | 
| 
      
 37 
     | 
    
         
            +
                    require 'migrations'
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    set_up_migrations unless migrations_already_set_up?
         
     | 
| 
      
 40 
     | 
    
         
            +
                    add_initial_migration if tables_from_before_migrations_exist?
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    case direction.to_s
         
     | 
| 
      
 43 
     | 
    
         
            +
                    when "up"   then Integrity::Migrations.migrate_up!
         
     | 
| 
      
 44 
     | 
    
         
            +
                    when "down" then Integrity::Migrations.migrate_down!
         
     | 
| 
      
 45 
     | 
    
         
            +
                    else raise ArgumentError, "DIRECTION must be either up or down"
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def create_dir_structure
         
     | 
| 
      
 50 
     | 
    
         
            +
                    mkdir_p root
         
     | 
| 
      
 51 
     | 
    
         
            +
                    mkdir_p root / "builds"
         
     | 
| 
      
 52 
     | 
    
         
            +
                    mkdir_p root / "log"
         
     | 
| 
      
 53 
     | 
    
         
            +
                    mkdir_p root / "public" # this one is to play nice with Passenger
         
     | 
| 
      
 54 
     | 
    
         
            +
                    mkdir_p root / "tmp"    # this one is to play nice with Passenger
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  def copy_template_files
         
     | 
| 
      
 58 
     | 
    
         
            +
                    cp Integrity.root / "config" / "config.sample.ru",  root / "config.ru"
         
     | 
| 
      
 59 
     | 
    
         
            +
                    cp Integrity.root / "config" / "config.sample.yml", root / "config.yml"
         
     | 
| 
      
 60 
     | 
    
         
            +
                    cp Integrity.root / "config" / "thin.sample.yml",   root / "thin.yml"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def edit_template_files
         
     | 
| 
      
 64 
     | 
    
         
            +
                    edit_integrity_configuration
         
     | 
| 
      
 65 
     | 
    
         
            +
                    edit_thin_configuration
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def edit_integrity_configuration
         
     | 
| 
      
 69 
     | 
    
         
            +
                    config = File.read(root / "config.yml")
         
     | 
| 
      
 70 
     | 
    
         
            +
                    config.gsub! %r(sqlite3:///var/integrity.db), "sqlite3://#{root}/integrity.db"
         
     | 
| 
      
 71 
     | 
    
         
            +
                    config.gsub! %r(/path/to/scm/exports),        "#{root}/builds"
         
     | 
| 
      
 72 
     | 
    
         
            +
                    config.gsub! %r(/var/log),                    "#{root}/log"
         
     | 
| 
      
 73 
     | 
    
         
            +
                    File.open(root / "config.yml", "w") { |f| f.puts config }
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  def edit_thin_configuration
         
     | 
| 
      
 77 
     | 
    
         
            +
                    config = File.read(root / "thin.yml")
         
     | 
| 
      
 78 
     | 
    
         
            +
                    config.gsub! %r(/apps/integrity), root
         
     | 
| 
      
 79 
     | 
    
         
            +
                    File.open(root / "thin.yml", 'w') { |f| f.puts config }
         
     | 
| 
      
 80 
     | 
    
         
            +
                  end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  def after_setup_message
         
     | 
| 
      
 83 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 84 
     | 
    
         
            +
                    puts %Q(Awesome! Integrity was installed successfully!)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 86 
     | 
    
         
            +
                    puts %Q(If you want to enable notifiers, install the gems and then require them)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    puts %Q(in #{root}/config.ru)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 89 
     | 
    
         
            +
                    puts %Q(For example:)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 91 
     | 
    
         
            +
                    puts %Q(  sudo gem install -s http://gems.github.com foca-integrity-email)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 93 
     | 
    
         
            +
                    puts %Q(And then in #{root}/config.ru add:)
         
     | 
| 
      
 94 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 95 
     | 
    
         
            +
                    puts %Q(  require "notifier/email")
         
     | 
| 
      
 96 
     | 
    
         
            +
                    puts
         
     | 
| 
      
 97 
     | 
    
         
            +
                    puts %Q(Don't forget to tweak #{root / "config.yml"} to your needs.)
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  def set_up_migrations
         
     | 
| 
      
 101 
     | 
    
         
            +
                    database_adapter.execute %q(CREATE TABLE "migration_info" ("migration_name" VARCHAR(255));)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  def add_initial_migration
         
     | 
| 
      
 105 
     | 
    
         
            +
                    database_adapter.execute %q(INSERT INTO "migration_info" ("migration_name") VALUES ("initial"))
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def tables_from_before_migrations_exist?
         
     | 
| 
      
 109 
     | 
    
         
            +
                    table_exists?("integrity_projects") && 
         
     | 
| 
      
 110 
     | 
    
         
            +
                      table_exists?("integrity_builds") && 
         
     | 
| 
      
 111 
     | 
    
         
            +
                      table_exists?("integrity_notifiers")
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                  def migrations_already_set_up?
         
     | 
| 
      
 115 
     | 
    
         
            +
                    table_exists?("migration_info")
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  def without_pluralizing_table_names
         
     | 
| 
      
 119 
     | 
    
         
            +
                    database_adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::Underscored
         
     | 
| 
      
 120 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 121 
     | 
    
         
            +
                    database_adapter.resource_naming_convention = DataMapper::NamingConventions::Resource::UnderscoredAndPluralized
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  def table_exists?(table_name)
         
     | 
| 
      
 125 
     | 
    
         
            +
                    database_adapter.storage_exists?(table_name)
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  def database_adapter
         
     | 
| 
      
 129 
     | 
    
         
            +
                    DataMapper.repository(:default).adapter
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
              end
         
     | 
| 
      
 132 
     | 
    
         
            +
            end
         
     |