codefumes 0.1.10 → 0.2.0

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.
Files changed (68) hide show
  1. data/Gemfile +19 -0
  2. data/Gemfile.lock +135 -0
  3. data/History.txt +12 -0
  4. data/LICENSE +20 -0
  5. data/Manifest.txt +40 -19
  6. data/README.txt +11 -29
  7. data/Rakefile +15 -10
  8. data/bin/fumes +214 -0
  9. data/config/website.yml +2 -0
  10. data/cucumber.yml +2 -0
  11. data/features/claiming_a_project.feature +46 -0
  12. data/features/deleting_a_project.feature +32 -0
  13. data/features/releasing_a_project.feature +50 -0
  14. data/features/step_definitions/cli_steps.rb +98 -0
  15. data/features/step_definitions/common_steps.rb +168 -0
  16. data/features/step_definitions/filesystem_steps.rb +19 -0
  17. data/features/storing_user_api_key.feature +41 -0
  18. data/features/support/common.rb +29 -0
  19. data/features/support/env.rb +24 -0
  20. data/features/support/matchers.rb +11 -0
  21. data/features/synchronizing_repository_with_project.feature +33 -0
  22. data/lib/codefumes.rb +10 -8
  23. data/lib/codefumes/api.rb +20 -11
  24. data/lib/codefumes/api/build.rb +139 -0
  25. data/lib/codefumes/api/claim.rb +74 -0
  26. data/lib/codefumes/api/commit.rb +150 -0
  27. data/lib/codefumes/api/payload.rb +93 -0
  28. data/lib/codefumes/api/project.rb +158 -0
  29. data/lib/codefumes/cli_helpers.rb +54 -0
  30. data/lib/codefumes/config_file.rb +3 -2
  31. data/lib/codefumes/errors.rb +21 -0
  32. data/lib/codefumes/exit_codes.rb +10 -0
  33. data/lib/codefumes/harvester.rb +113 -0
  34. data/lib/codefumes/quick_build.rb +43 -0
  35. data/lib/codefumes/quick_metric.rb +20 -0
  36. data/lib/codefumes/source_control.rb +137 -0
  37. data/lib/integrity_notifier/codefumes.haml +11 -0
  38. data/lib/integrity_notifier/codefumes.rb +62 -0
  39. data/spec/codefumes/{build_spec.rb → api/build_spec.rb} +14 -24
  40. data/spec/codefumes/{claim_spec.rb → api/claim_spec.rb} +42 -3
  41. data/spec/codefumes/{commit_spec.rb → api/commit_spec.rb} +34 -24
  42. data/spec/codefumes/api/payload_spec.rb +148 -0
  43. data/spec/codefumes/api/project_spec.rb +286 -0
  44. data/spec/codefumes/api_spec.rb +38 -15
  45. data/spec/codefumes/config_file_spec.rb +69 -13
  46. data/spec/codefumes/harvester_spec.rb +118 -0
  47. data/spec/codefumes/source_control_spec.rb +199 -0
  48. data/spec/codefumes_service_helpers.rb +23 -19
  49. data/spec/fixtures/sample_project_dirs/no_scm/description +4 -0
  50. data/spec/spec_helper.rb +1 -0
  51. data/tasks/cucumber.rake +11 -0
  52. metadata +145 -60
  53. data/bin/cf_claim_project +0 -9
  54. data/bin/cf_release_project +0 -10
  55. data/bin/cf_store_credentials +0 -10
  56. data/lib/cf_claim_project/cli.rb +0 -95
  57. data/lib/cf_release_project/cli.rb +0 -76
  58. data/lib/cf_store_credentials/cli.rb +0 -50
  59. data/lib/codefumes/build.rb +0 -131
  60. data/lib/codefumes/claim.rb +0 -57
  61. data/lib/codefumes/commit.rb +0 -144
  62. data/lib/codefumes/payload.rb +0 -103
  63. data/lib/codefumes/project.rb +0 -129
  64. data/spec/cf_claim_project/cli_spec.rb +0 -17
  65. data/spec/cf_release_project/cli_spec.rb +0 -41
  66. data/spec/cf_store_credentials/cli_spec.rb +0 -28
  67. data/spec/codefumes/payload_spec.rb +0 -155
  68. data/spec/codefumes/project_spec.rb +0 -274
data/bin/cf_claim_project DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Created on 2009-9-21.
4
- # Copyright (c) 2009. All rights reserved.
5
-
6
- require File.expand_path(File.dirname(__FILE__) + "/../lib/codefumes")
7
- require File.expand_path(File.dirname(__FILE__) + "/../lib/cf_claim_project/cli")
8
-
9
- CfClaimProject::CLI.execute(STDOUT, ARGV)
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Created on 2009-10-2.
4
- # Copyright (c) 2009. All rights reserved.
5
-
6
- require 'rubygems'
7
- require File.expand_path(File.dirname(__FILE__) + "/../lib/codefumes")
8
- require "cf_release_project/cli"
9
-
10
- CfReleaseProject::CLI.execute(STDOUT, ARGV)
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Created on 2009-9-18.
4
- # Copyright (c) 2009. All rights reserved.
5
-
6
- require 'rubygems'
7
- require File.expand_path(File.dirname(__FILE__) + "/../lib/codefumes")
8
- require File.expand_path(File.dirname(__FILE__) + "/../lib/cf_store_credentials/cli")
9
-
10
- CfStoreCredentials::CLI.execute(STDOUT, ARGV)
@@ -1,95 +0,0 @@
1
- require 'optparse'
2
- require 'codefumes/config_file'
3
- include CodeFumes
4
-
5
- module CfClaimProject #:nodoc:
6
- class CLI #:nodoc:
7
- @attempt_to_claim_all = false
8
- @private_project = false
9
-
10
- def self.execute(stdout, arguments=[])
11
- @stdout = stdout
12
- parse_cli_arguments!(arguments)
13
- retrieve_users_credentials_or_exit
14
-
15
-
16
- @public_keys.each do |public_key|
17
- project = Project.find(public_key)
18
-
19
- if project.nil?
20
- @stdout.puts "Claiming...'#{public_key}': Not found"
21
- next
22
- end
23
-
24
- @stdout.print "Claiming...'#{public_key}': "
25
- @stdout.puts Claim.create(project, @users_api_key, visibility) ? 'Success!' : 'Denied.'
26
- end
27
-
28
- @stdout.puts ""
29
- @stdout.puts "Done!"
30
- end
31
-
32
- private
33
- def self.parse_cli_arguments!(arguments)
34
- OptionParser.new do |opts|
35
- opts.banner = <<-BANNER.gsub(/^ /,'')
36
- Used to 'claim' a project on CodeFumes.com. The claim request has a
37
- "visibility" attribute as well, which defaults to "public", but can
38
- be set to "private" using the -p/--private flag.
39
-
40
- Usage: #{File.basename($0)} [options]
41
-
42
- Options are:
43
- BANNER
44
- opts.separator ""
45
- opts.on("-a", "--all", String,
46
- "Attempt to claim all projects in your CodeFumes config file."
47
- ) {@attempt_to_claim_all = true}
48
- opts.on("-p", "--private", String,
49
- "Claims the project(s) as a 'private' project."
50
- ) {@private_project = true}
51
- opts.on("-l", "--local",
52
- "Send requests to localhost. (Testing/Development)") { CodeFumes::API.mode(:local) }
53
- opts.on("-t", "--test",
54
- "Send requests to test.codefumes.com. (Testing/Development)") { CodeFumes::API.mode(:test) }
55
- opts.on("-h", "--help",
56
- "Show this help message.") { @stdout.puts opts; exit(1) }
57
- opts.parse!(arguments)
58
- end
59
-
60
- @public_keys = claim_all_projects_flag_set? ? ConfigFile.public_keys : arguments.compact
61
- if @public_keys.empty?
62
- print_missing_arguments_message
63
- exit
64
- end
65
-
66
- end
67
-
68
- def self.claim_all_projects_flag_set?
69
- @attempt_to_claim_all == true
70
- end
71
-
72
- def self.visibility
73
- @private_project == true ? :private : :public
74
- end
75
-
76
- def self.print_missing_arguments_message
77
- @stdout.puts "You must specify either a public key of a project, or -a/--all to"
78
- @stdout.puts "claim all projects in your CodeFumes config file"
79
- @stdout.puts ""
80
- @stdout.puts "Exiting."
81
- end
82
-
83
- def self.retrieve_users_credentials_or_exit
84
- @users_api_key = ConfigFile.api_key
85
- return @users_api_key unless @users_api_key.nil?
86
- @stdout.puts "No API key saved in your CodeFumes config file!"
87
- @stdout.puts ""
88
- @stdout.puts "Grab your API key from CodeFumes.com and run 'store_codefumes_credentials [api_key]."
89
- @stdout.puts "Then try again."
90
- @stdout.puts ""
91
- @stdout.puts "Exiting."
92
- exit
93
- end
94
- end
95
- end
@@ -1,76 +0,0 @@
1
- require 'optparse'
2
- include CodeFumes
3
-
4
- module CfReleaseProject #:nodoc:
5
- class CLI #:nodoc:
6
- def self.execute(stdout, arguments=[])
7
- @stdout = stdout
8
- @users_api_key = ConfigFile.api_key
9
- parse_cli_options(arguments)
10
-
11
- @public_keys.each do |public_key|
12
- project = Project.find(public_key)
13
-
14
- if project.nil?
15
- @stdout.puts "Releasing...'#{public_key}': Not found"
16
- next
17
- end
18
-
19
- @stdout.print "Releasing...'#{public_key}': "
20
- @stdout.puts Claim.destroy(project, @users_api_key) ? 'Success!' : 'Denied.'
21
- end
22
-
23
- @stdout.puts ""
24
- stdout.puts "Done."
25
- end
26
-
27
- private
28
- def self.parse_cli_options(arguments)
29
- parser = OptionParser.new do |opts|
30
- opts.banner = <<-BANNER.gsub(/^ /,'')
31
- Removes the claim of ownership on a CodeFumes project, making
32
- the project visible to the public and possible for other users
33
- to claim.
34
-
35
- Usage: #{File.basename($0)} [PROJECT_PUBLIC_KEY]
36
-
37
- Options are:
38
- BANNER
39
- opts.separator ""
40
- opts.on("-a", "--all",
41
- "Release all projects listed in your CodeFumes config file."
42
- ) {@attempt_to_release_all = true}
43
- opts.on("-l", "--local",
44
- "Send requests to localhost. (Testing/Development)") { CodeFumes::API.mode(:local) }
45
- opts.on("-t", "--test",
46
- "Send requests to test.codefumes.com. (Testing/Development)") { CodeFumes::API.mode(:test) }
47
- opts.on("-h", "--help",
48
- "Show this help message."
49
- ) {@stdout.puts opts; exit}
50
- opts.parse!(arguments)
51
-
52
- @public_keys = release_all_projects_flag_set? ? ConfigFile.public_keys : arguments.compact
53
- if @public_keys.empty?
54
- print_missing_arguments_message
55
- exit
56
- end
57
-
58
- if arguments.empty?
59
- @stdout.puts "No public key specified"
60
- @stdout.puts opts; exit
61
- end
62
- end
63
- end
64
-
65
- def self.release_all_projects_flag_set?
66
- @attempt_to_release_all == true
67
- end
68
-
69
- def self.print_missing_arguments_message
70
- @stdout.puts "You must specify either a public key of a project, or -a/--all to"
71
- @stdout.puts "claim all projects in your CodeFumes config file"
72
- @stdout.puts ""
73
- @stdout.puts "Exiting."
74
- end
75
- end
76
- end
@@ -1,50 +0,0 @@
1
- require 'optparse'
2
-
3
- module CfStoreCredentials #:nodoc:
4
- class CLI #:nodoc:
5
- def self.execute(stdout, arguments=[])
6
- @stdout = stdout
7
- parse_command_line_options!(arguments)
8
- api_key = arguments.first
9
-
10
- if CodeFumes::ConfigFile.credentials.empty? || @force_overwrite == true
11
- CodeFumes::ConfigFile.save_credentials(api_key)
12
- @stdout.puts "Saved credentials to codefumes config file.\n\nExiting."
13
- else
14
- if CodeFumes::ConfigFile.credentials == api_key
15
- @stdout.puts "Credentials already stored in config file!\n"
16
- else
17
- @stdout.puts "You have already stored CodeFumes credentials.\n\n"
18
- @stdout.puts "The current value you have stored is: #{CodeFumes::ConfigFile.credentials[:api_key]}\n\n"
19
- @stdout.puts "If you would like to replace this value, execute:\n\n"
20
- @stdout.puts "\t#{File.basename($0)} --force #{api_key}\n\n"
21
- end
22
- end
23
- end
24
-
25
- private
26
- def self.parse_command_line_options!(arguments)
27
- @force_overwrite = false
28
-
29
- parser = OptionParser.new do |opts|
30
- opts.banner = <<-BANNER.gsub(/^ /,'')
31
- Stores user's API_KEY from CodFumes.com in the CodeFumes global config file.
32
-
33
- Usage: #{File.basename($0)} [options] api_key
34
-
35
- Options are:
36
- BANNER
37
- opts.separator ""
38
- opts.on("-h", "--help",
39
- "Show this help message.") { @stdout.puts opts; exit }
40
- opts.on("-f", "--force",
41
- "Force overwrite of existing API key in config file.") { @force_overwrite = true }
42
- opts.parse!(arguments)
43
-
44
- if arguments.size != 1
45
- @stdout.puts opts; exit
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,131 +0,0 @@
1
- module CodeFumes
2
- # A Build represents a specific instance of tests running on
3
- # a continuous integration server. Builds have a name and are
4
- # associated with # a specific Commit of a Project and can track
5
- # the current status (running, failed, success) and the
6
- # start & end times of the Build process.
7
- class Build < CodeFumes::API
8
- attr_reader :project_public_key, :project_private_key, :created_at, :api_uri, :identifier, :commit_identifier
9
- attr_accessor :started_at, :ended_at, :state, :name
10
-
11
- # Initializes new instance of a Build.
12
- #
13
- # Accepts an +options+ Hash with support for the following keys:
14
- # :public_key (*)
15
- # :private_key (*)
16
- # :commit_identifier (*)
17
- # :identifier
18
- # :name (*)
19
- # :state (*)
20
- # :api_uri
21
- # :started_at (*)
22
- # :ended_at
23
- #
24
- # NOTE: (*) denotes a required key/value pair
25
- def initialize(options = {})
26
- @project_public_key = options[:public_key] || options['public_key']
27
- @project_private_key = options[:private_key] || options['private_key']
28
- @commit_identifier = options[:commit_identifier] || options['commit_identifier']
29
- @identifier = options[:identifier] || options['identifier']
30
- @name = options[:name] || options['name']
31
- @state = options[:state] || options['state']
32
- @api_uri = options[:api_uri] || options['api_uri']
33
- @started_at = options[:started_at] || options['started_at']
34
- @ended_at = options[:ended_at] || options['ended_at']
35
- end
36
-
37
- # Saves the Build instance to CodeFumes.com
38
- #
39
- # Returns +true+ if successful
40
- #
41
- # Returns +false+ if request fails
42
- def save
43
- response = exists? ? update : create
44
-
45
- case response.code
46
- when 201,200
47
- @identifier = response['build']['identifier']
48
- @name = response['build']['name']
49
- @created_at = response['build']['created_at']
50
- @started_at = response['build']['started_at']
51
- @ended_at = response['build']['ended_at']
52
- @state = response['build']['state']
53
- @api_uri = response['build']['build_api_uri']
54
- @commit_identifier = response['build']['commit_identifier']
55
- @project_public_key = response['build']['public_key']
56
- @project_private_key = response['build']['private_key']
57
- true
58
- else
59
- false
60
- end
61
- end
62
-
63
- # Searches website for Build with the supplied identifier.
64
- #
65
- # Returns a Build instance if the Build exists and is available,
66
- # to the user making the request.
67
- #
68
- # Returns +nil+ in all other cases.
69
- def self.find(options)
70
- uri = "/projects/#{options[:public_key]}/commits/#{options[:commit_identifier]}/builds/#{options[:identifier]}"
71
-
72
- response = get(uri)
73
-
74
- case response.code
75
- when 200
76
- build_params = response["build"] || {}
77
- Build.new(build_params.merge(:private_key => options[:private_key]))
78
- else
79
- nil
80
- end
81
- end
82
-
83
-
84
- # Returns true if the request was successful
85
- #
86
- # Returns +false+ in all other cases.
87
- def destroy
88
- uri = "/projects/#{@project_public_key}/commits/#{@commit_identifier}/builds/#{@identifier}"
89
- auth_args = {:username => @project_public_key, :password => @project_private_key}
90
-
91
- response = self.class.delete(uri, :basic_auth => auth_args)
92
-
93
- case response.code
94
- when 200 : true
95
- else false
96
- end
97
- end
98
-
99
- private
100
- # Verifies existence of Build on website.
101
- #
102
- # Returns +true+ if a build with the specified identifier or name is associated with
103
- # the specified project/commit
104
- #
105
- # Returns +false+ if the public key of the Project is not available.
106
- def exists?
107
- !self.class.find(:public_key => @project_public_key,
108
- :commit_identifier => @commit_identifier,
109
- :identifier => @identifier || @name,
110
- :private_key => @project_private_key).nil?
111
- end
112
-
113
- # Saves a new build (makes POST request)
114
- def create
115
- content = standard_content_hash
116
- self.class.post("/projects/#{@project_public_key}/commits/#{@commit_identifier}/builds", :query => {:build => content}, :basic_auth => {:username => @project_public_key, :password => @project_private_key})
117
- end
118
-
119
- # Updates an existing build (makes PUT request)
120
- def update
121
- content = standard_content_hash
122
- # HACK!
123
- searchable_identifier = @identifier || @name
124
- self.class.put("/projects/#{@project_public_key}/commits/#{@commit_identifier}/builds/#{searchable_identifier}", :query => {:build => content}, :basic_auth => {:username => @project_public_key, :password => @project_private_key})
125
- end
126
-
127
- def standard_content_hash
128
- {:name => @name,:started_at => @started_at, :ended_at => @ended_at, :state => @state}
129
- end
130
- end
131
- end
@@ -1,57 +0,0 @@
1
- module CodeFumes
2
- class Claim < CodeFumes::API
3
- attr_accessor :created_at
4
- SUPPORTED_VISIBILITIES = [:public, :private]
5
-
6
- # Attempts to claim the specified Project instance using the
7
- # supplied API key.
8
- #
9
- # +visibility+ defaults to +:public+. Valid options are +public+
10
- # and +private+.
11
- #
12
- # Similar to Project#claim, but more explicit.
13
- #
14
- # Returns +true+ if the request is successful, or if the project
15
- # was already owned by the user associated with the privided API
16
- # key.
17
- #
18
- # Returns +false+ in all other cases.
19
- def self.create(project, api_key, visibility = :public)
20
- unless SUPPORTED_VISIBILITIES.include?(visibility.to_sym)
21
- msg = "Unsupported visibility supplied (#{visibility.to_s}). "
22
- msg << "Valid options are: #{SUPPORTED_VISIBILITIES.join(', ')}"
23
- raise ArgumentError, msg
24
- end
25
-
26
- auth_args = {:username => project.public_key, :password => project.private_key}
27
-
28
- uri = "/projects/#{project.public_key}/claim"
29
- response = put(uri, :query => {:api_key => api_key, :visibility => visibility}, :basic_auth => auth_args)
30
-
31
- case response.code
32
- when 200 : true
33
- else false
34
- end
35
- end
36
-
37
- # Removes a claim on the specified Project instance using the
38
- # supplied API key, releasing ownership. If the project was a
39
- # "private" project, this method will convert it to "public".
40
- #
41
- # Returns true if the request was successful or there was not
42
- # an existing owner (the action is idempotent).
43
- #
44
- # Returns +false+ in all other cases.
45
- def self.destroy(project, api_key)
46
- auth_args = {:username => project.public_key, :password => project.private_key}
47
-
48
- uri = "/projects/#{project.public_key}/claim"
49
- response = delete(uri, :query => {:api_key => api_key}, :basic_auth => auth_args)
50
-
51
- case response.code
52
- when 200 : true
53
- else false
54
- end
55
- end
56
- end
57
- end