octopusci 0.3.6 → 0.3.7

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.
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+
5
+ APP_NAME = "octopusci-install"
6
+
7
+ require 'rubygems'
8
+ require 'octopusci/version'
9
+ require 'trollop'
10
+
11
+ module Octopusci
12
+ class Installer
13
+ def initialize(opts)
14
+ @opts = opts
15
+ end
16
+
17
+ def install
18
+ # Create user account for octopusci to use.
19
+ warn(account_exists?(@opts[:account]), "The \"#{@opts[:account]}\" user account already exists.") {
20
+ delete_account(@opts[:account])
21
+ }
22
+ create_account(@opts[:account], @opts[:shell], @opts[:uid], @opts[:gid])
23
+ puts "Created the \"#{@opts[:account]}\" account."
24
+
25
+ # Do the same stuff octopusci-skel currently does but also include the user and group that the octopusci-tentacles should run as
26
+ # in the config.yml so that when octopusci-tentacles launches as root at boot it can properly switch to the proper uid and guid
27
+
28
+ # Make sure that there exists a .ssh/config in the account home directory with the proper permissions and that config has the
29
+ # option that makes it so that when sshing to github it doesn't make you manually accept the server host key.
30
+ end
31
+
32
+ private
33
+
34
+ def create_account(account_name, shell, uid, gid)
35
+ if on_mac?
36
+ # Create the user entry.
37
+ `dscl . -create /Users/#{account_name}`
38
+
39
+ # Set the users shell.
40
+ `dscl . -create /Users/#{account_name} UserShell ${shell}`
41
+
42
+ # Set the users full name.
43
+ `dscl . -create /Users/#{account_name} RealName "#{account_name}"`
44
+
45
+ # Associate the user with a unique id.
46
+ `dscl . -create /Users/#{account_name} UniqueID #{uid}`
47
+
48
+ # Associate the user with a primary gorup id.
49
+ `dscl . -create /Users/#{account_name} PrimaryGroupID #{gid}`
50
+
51
+ # Create the users home directory.
52
+ `dscl . -create /Users/#{account_name} NFSHomeDirectory /Users/#{account_name}`
53
+
54
+ # Create the home directory and set the ownership properly.
55
+ `mkdir -p /Users/#{account_name}`
56
+ `chown -R #{uid}:#{gid} /Users/#{account_name}`
57
+
58
+ # Set the users password.
59
+ puts "Please enter the password for the \"#{account_name}\" account."
60
+ `passwd ${account_name}`
61
+ else
62
+ not_implemented
63
+ end
64
+ end
65
+
66
+ def delete_account(account_name)
67
+ if on_mac?
68
+ # Remove the directory services record
69
+ `dscl . -delete /Users/#{account_name}`
70
+ else
71
+ not_implemented
72
+ end
73
+ end
74
+
75
+ # Returns a boolean identifying if an account with the given name already exists or not
76
+ def account_exists?(account_name)
77
+ if on_mac?
78
+ cmd_out = `dscl . -search /Users name "#{account_name}"`
79
+ return cmd_out.empty? ? false : true
80
+ else
81
+ not_implenented
82
+ end
83
+ end
84
+
85
+ # Get a boolean representing if this is running on a Mac or not.
86
+ def on_mac?
87
+ return RUBY_PLATFORM.downcase.include?("darwin") ? true : false
88
+ end
89
+
90
+ def warn(warn, msg)
91
+ if warn
92
+ if @opts[:force]
93
+ puts "Warning: (Bypassed by -f) #{msg}"
94
+ yield
95
+ else
96
+ puts "Warning: #{msg}"
97
+ exit 2
98
+ end
99
+ end
100
+ end
101
+
102
+ def error(msg)
103
+ puts "Error: #{msg}"
104
+ exit 1
105
+ end
106
+
107
+ def not_implemented
108
+ error("Not currently implemented")
109
+ end
110
+
111
+ end
112
+ end
113
+
114
+ opts = Trollop::options do
115
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
116
+ banner """Usage: #{APP_NAME} [-i|--install|-a|--account|-v|--version|-h|--help]"""
117
+ opt :install, "Actually install Octopusci.", :short => "-i", :default => false
118
+ opt :force, "Force the install to continue ignoring warnings", :short => "-f", :default => false
119
+ opt :account, "Account name to create for the Octopusci install", :short => "-a", :default => "octopusci"
120
+ opt :uid, "User id to assign to the user account that is going to be created", :short => "-u", :default => "498"
121
+ opt :gid, "Primary group id to assign to the user account that is going to be created", :short => "-g", :default => "1000"
122
+ opt :shell, "Shell that used by the account that is going to be created", :short => "-s", :default => "/bin/bash"
123
+ end
124
+
125
+ if Process.uid != 0
126
+ error("Must run as root.")
127
+ end
128
+
129
+ installer = Octopusci::Installer.new(opts)
130
+
131
+ installer.install
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'rubygems'
6
+ require 'octopusci/version'
7
+ require 'trollop'
8
+ require "uri"
9
+ require "net/http"
10
+
11
+ opts = Trollop::options do
12
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
13
+ banner """Usage: octopusci-post-build-request [-v|--version|-h|--help]"""
14
+ opt :hostname, "Hostname/IP address to send the POST request to", :short => "-n", :default => '127.0.0.1'
15
+ opt :port, "Port number to connect to", :short => "-p", :default => 80
16
+ opt :repo_name, "Repository name to send build request for", :short => "-r", :default => "octopusci"
17
+ opt :branch_name, "Branch name to send build request for", :short => "-b", :default => 'master'
18
+ opt :owner_email, "Repository owner's email address", :short => "-o", :default => 'cyphactor@gmail.com'
19
+ opt :owner_name, "Repository owner's name", :short => "-w", :default => 'cyphactor'
20
+ opt :pusher_name, "Pusher's name", :short => "-u", :default => 'cyphactor'
21
+ opt :pusher_email, "Pusher's email address", :short => "-s", :default => 'pusher@example.com'
22
+ end
23
+
24
+ http = Net::HTTP.new(opts[:hostname], opts[:port])
25
+ path = '/github-build'
26
+
27
+ # POST request -> logging in
28
+ params = { 'payload' => "{\"base_ref\":null,\"ref\":\"refs/heads/#{opts[:branch_name]}\",\"commits\":[{\"message\":\"shit son\",\"removed\":[],\"modified\":[\"test.txt\"],\"added\":[],\"author\":{\"username\":\"cyphactor\",\"email\":\"cyphactor@gmail.com\",\"name\":\"Andrew De Ponte\"},\"distinct\":true,\"timestamp\":\"2011-09-06T22:01:12-07:00\",\"id\":\"8573e06a3cb511babd9d19d33be637b661232011\",\"url\":\"https://github.com/cyphactor/octopusci/commit/8573e06a3cb511babd9d19d33be637b661232011\"},{\"message\":\"again broham\",\"removed\":[],\"modified\":[\"test.txt\"],\"added\":[],\"author\":{\"username\":\"cyphactor\",\"email\":\"cyphactor@gmail.com\",\"name\":\"Andrew De Ponte\"},\"distinct\":true,\"timestamp\":\"2011-09-06T23:01:07-07:00\",\"id\":\"771adb4b75694804f256e7e61704648a14d52afc\",\"url\":\"https://github.com/cyphactor/octopusci/commit/771adb4b75694804f256e7e61704648a14d52afc\"},{\"message\":\"again broham\",\"removed\":[],\"modified\":[\"test.txt\"],\"added\":[],\"author\":{\"username\":\"cyphactor\",\"email\":\"cyphactor@gmail.com\",\"name\":\"Andrew De Ponte\"},\"distinct\":true,\"timestamp\":\"2011-09-06T23:03:16-07:00\",\"id\":\"dadf8446b2037960cc6223d60a7d57c5d264fa48\",\"url\":\"https://github.com/cyphactor/octopusci/commit/dadf8446b2037960cc6223d60a7d57c5d264fa48\"}],\"created\":false,\"before\":\"e5a1385fd8654c46d2b52d90c1ba31c865493602\",\"repository\":{\"created_at\":\"2011/09/02 12:40:14 -0700\",\"open_issues\":0,\"forks\":1,\"description\":\"Temp repo for testing pusci as I dev it\",\"has_wiki\":true,\"fork\":false,\"watchers\":1,\"has_downloads\":true,\"homepage\":\"\",\"has_issues\":true,\"private\":false,\"size\":116,\"owner\":{\"email\":\"#{opts[:owner_email]}\",\"name\":\"#{opts[:owner_name]}\"},\"name\":\"#{opts[:repo_name]}\",\"pushed_at\":\"2011/09/06 23:03:21 -0700\",\"url\":\"https://github.com/cyphactor/octopusci\"},\"pusher\":{\"email\":\"#{opts[:pusher_email]}\",\"name\":\"#{opts[:pusher_name]}\"},\"forced\":false,\"after\":\"dd6e7913cc12937db88e469684e8698f8eee8c14\",\"deleted\":false,\"compare\":\"https://github.com/cyphactor/octopusci/compare/e5a1385...dd6e791\"}" }
29
+
30
+ data = URI.encode_www_form(params)
31
+ headers = {
32
+ 'Accept' => '*/*',
33
+ 'Content-Type' => 'application/x-www-form-urlencoded',
34
+ 'X-Github-Event' => 'push'
35
+ }
36
+
37
+ resp, data = http.post(path, data, headers)
38
+
39
+ puts 'Code = ' + resp.code
40
+ puts 'Message = ' + resp.message
41
+ resp.each {|key, val| puts key + ' = ' + val}
42
+ puts data
@@ -3,24 +3,51 @@
3
3
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
4
 
5
5
  require 'rubygems'
6
- require 'octopusci'
6
+ require 'octopusci/version'
7
+ require 'octopusci/job_store'
8
+ require 'trollop'
9
+
10
+ opts = Trollop::options do
11
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
12
+ banner """Usage: octopusci-reset-redis [-r|-v|--version|-h|--help]"""
13
+ opt :reset, "Actually reset the redis datastore", :short => "-r", :default => false
14
+ end
7
15
 
8
- num_jobs = Octopusci::JobStore.size
9
- jobs = Octopusci::JobStore.list(0, num_jobs)
16
+ if opts[:reset]
17
+ num_jobs = Octopusci::JobStore.size
18
+ jobs = Octopusci::JobStore.list(0, num_jobs)
10
19
 
11
- jobs.each do |j|
12
- # delete the actual job record
13
- Octopusci::JobStore.redis.del("octopusci:jobs:#{j['id']}")
20
+ jobs.each do |j|
21
+ # delete the actual job record
22
+ Octopusci::JobStore.redis.del("octopusci:jobs:#{j['id']}")
14
23
 
15
- # delete the repo_name, branch_name job references
16
- Octopusci::JobStore.redis.del("octopusci:#{j['repo_name']}:#{j['branch_name']}:jobs")
24
+ # delete the repo_name, branch_name job references
25
+ Octopusci::JobStore.redis.del("octopusci:#{j['repo_name']}:#{j['branch_name']}:jobs")
17
26
 
18
- # delete the github payload for the repo_name, branch_name
19
- Octopusci::JobStore.redis.del("octopusci:github_payload:#{j['repo_name']}:#{j['branch_name']}")
27
+ # delete the github payload for the repo_name, branch_name
28
+ Octopusci::JobStore.redis.del("octopusci:github_payload:#{j['repo_name']}:#{j['branch_name']}")
20
29
 
21
- end
30
+ end
31
+
32
+ Octopusci::JobStore.redis.del('octopusci:job_count')
33
+ Octopusci::JobStore.redis.del('octopusci:jobs')
34
+ Octopusci::JobStore.redis.del('octopusci:stagelocker')
35
+ Octopusci::JobStore.redis.del('queue:octopusci:commit')
36
+ else
37
+ puts %Q{THIS IS A WARNING. THIS IS A DESTRUCTIVE COMMAND!
38
+
39
+ This command is designed to allow you to reset/clear out the values in your redis
40
+ data store associated with Octopusci. If you run this command with the proper option
41
+ it will actually get rid of all of the data stored in the redis datae store for Octopusci.
42
+ It is intended to be used very rarely and only by people that understand exactly what it
43
+ is going to do (primarily Octopusci Developers).
22
44
 
23
- Octopusci::JobStore.redis.del('octopusci:job_count')
24
- Octopusci::JobStore.redis.del('octopusci:jobs')
25
- Octopusci::JobStore.redis.del('octopusci:stagelocker')
26
- Octopusci::JobStore.redis.del('queue:octopusci:commit')
45
+ To go forward and actually reset the redis data store with respect to Octopusci run it using
46
+ the following example.
47
+
48
+ Example:
49
+ octopusci-reset-redis -r
50
+
51
+ }
52
+
53
+ end
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'rubygems'
6
+ require 'octopusci/version'
7
+ require 'trollop'
8
+
9
+ opts = Trollop::options do
10
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
11
+ banner """Usage: octopusci-reset-stage-locker [-r|-v|--version|-h|--help]"""
12
+ opt :reset, "Actually reset the stage locker", :short => "-r", :default => false
13
+ end
14
+
15
+ if opts[:reset]
16
+ puts "Reseting the Octopusci StageLocker, please wait..."
17
+ require 'octopusci'
18
+ Octopusci::StageLocker.load(Octopusci::Config['stages'])
19
+ puts "Succesfully Reset the Octopusci StageLocker"
20
+ else
21
+ puts %Q{THIS IS A WARNING. THIS IS A DESTRUCTIVE COMMAND!
22
+
23
+ This command is designed to allow you to reset/clear out the Octopusci StageLocker
24
+ and repopulate it with the stages defined in the config. If you run this command
25
+ with the proper option it will actually get rid of the Octopusci StageLocker and
26
+ recreate it with the stage values from the Octopusci config. It is intended to be
27
+ used very rarely.
28
+
29
+ The primary use case for it is that you have added a stage to your Octopusci setup
30
+ after already doing the initial setup. Running this command is necessary to make
31
+ Octopusci aware of the new stages you have added to the config since the initial
32
+ setup.
33
+
34
+ WARNING: You should not run this command until all job processes have completed.
35
+ Running 'octopusci-tentacles stop' only requests that the tentacles stop running
36
+ future jobs and that they kill themselves off once they are done with any current
37
+ jobs they are running. So, be sure you wait for the currently running jobs to
38
+ exit before you run this command or you could end up with multiple jobs running
39
+ on a single stage.
40
+
41
+ To go forward and actually reset the Octopusci StageLocker simply run the command
42
+ using the following example.
43
+
44
+ Example:
45
+ octopusci-reset-stage-locker -r
46
+
47
+ }
48
+
49
+ end
data/bin/octopusci-skel CHANGED
@@ -2,25 +2,34 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
4
 
5
+ APP_NAME = "octopusci-skel"
6
+
5
7
  require 'rubygems'
8
+ require 'octopusci/version'
6
9
  require 'fileutils'
10
+ require 'trollop'
7
11
 
8
12
  if Process.uid != 0
9
13
  puts "Must run as root"
10
14
  exit 1
11
15
  end
12
16
 
17
+ opts = Trollop::options do
18
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
19
+ banner """Usage: #{APP_NAME} [-c|-v|--version|-h|--help]"""
20
+ opt :create, "Actually create any missing pieces of the Octopusci Skeleton.", :short => "-c", :default => false
21
+ end
22
+
13
23
  JOBS_PATH = '/etc/octopusci/jobs'
14
24
  CONFIG_PATH = '/etc/octopusci/config.yml'
25
+ OCTOPUSCI_BUILD_PATH = '/etc/octopusci/jobs/octopusci_rspec_build_local.rb'
26
+ WORKSPACE_BASE_PATH = '/var/octopusci'
15
27
 
16
- FileUtils.mkdir_p(JOBS_PATH)
17
-
18
- if !File.exists?(CONFIG_PATH)
19
- File.open(CONFIG_PATH, 'w') do |f|
20
- f << "general:
21
- jobs_path: \"/etc/octopusci/jobs\"
22
- base_url: \"http://localhost:9998\"
23
- workspace_base_path: \"/Users/octopusci/.octopusci\"
28
+ config_default_content = %Q{
29
+ general:
30
+ jobs_path: "/etc/octopusci/jobs"
31
+ workspace_base_path: "#{WORKSPACE_BASE_PATH}"
32
+ base_url: "http://localhost:9998"
24
33
 
25
34
  http_basic:
26
35
  username: admin
@@ -37,15 +46,52 @@ smtp:
37
46
  raise_delivery_errors: true
38
47
 
39
48
  projects:
40
- - { name: octopusci, owner: cyphactor, job_klass: SomeJobClass, repo_uri: 'git@github.com:cyphactor/octopusci.git', default_email: devs@example.com }
49
+ - { name: octopusci, owner: cyphactor, job_klass: OctopusciRSpecBuildLocal, repo_uri: 'git@github.com:cyphactor/octopusci.git', default_email: devs@example.com }
41
50
 
42
51
  stages:
43
- - test_b
44
- "
52
+ - test_a
53
+ }
54
+
55
+ octopusci_build_default_content = %Q{
56
+ class OctopusciRSpecBuildLocal < Octopusci::Job
57
+ def self.run(job_rec)
58
+ context "RSpec Tests (commit)" do
59
+ run_shell_cmd!("bundle install", true)
60
+ run_shell_cmd!("STAGE=\#{job_rec['stage']} bundle exec rspec spec 2>&1")
61
+ end
45
62
  end
46
- puts "Created example #{CONFIG_PATH}, please modify appropriately"
47
- else
48
- puts "#{CONFIG_PATH} already exists, exiting to avoid modification."
49
- puts "If you would like to generated the example config again please rename the existing #{CONFIG_PATH}."
50
63
  end
64
+ }
51
65
 
66
+ if opts[:create]
67
+ FileUtils.mkdir_p(JOBS_PATH)
68
+ puts "1. Ran mkdir -p #{JOBS_PATH}"
69
+ FileUtils.mkdir_p(WORKSPACE_BASE_PATH)
70
+ puts "2. Ran mkdir -p #{WORKSPACE_BASE_PATH}"
71
+
72
+ if !File.exists?(CONFIG_PATH)
73
+ File.open(CONFIG_PATH, 'w') do |f|
74
+ f << config_default_content
75
+ end
76
+ puts "3. Created example #{CONFIG_PATH}. Please modify appropriately"
77
+ else
78
+ puts "3. #{CONFIG_PATH} already exists. It has NOT been modified."
79
+ puts " If you would like to generate the example config again please rename the existing #{CONFIG_PATH} and rerun #{APP_NAME}."
80
+ end
81
+
82
+ if !File.exists?(OCTOPUSCI_BUILD_PATH)
83
+ File.open(OCTOPUSCI_BUILD_PATH, 'w') do |f|
84
+ f << octopusci_build_default_content
85
+ end
86
+ puts "4. Created example job definition (#{OCTOPUSCI_BUILD_PATH}). Please use as a starting point for your own jobs."
87
+ else
88
+ puts "4. #{OCTOPUSCI_BUILD_PATH} already exists. It has NOT been modified."
89
+ puts " If you would like to generate the example job definition again please rename the existing #{OCTOPUSCI_BUILD_PATH} and rerun #{APP_NAME}"
90
+ end
91
+ else
92
+ puts "This is a Dry Run\n No actions have been taken this is simply a description of what would take place if you ran this command with the create option (-c).\n\n"
93
+ puts " 1. mkdir -p #{JOBS_PATH}"
94
+ puts " 2. mkdir -p #{WORKSPACE_BASE_PATH}"
95
+ puts " 3. Create example config (#{CONFIG_PATH}) if one doesn't exist"
96
+ puts " 4. Create example job definition (#{OCTOPUSCI_BUILD_PATH}) if it doesn't exist"
97
+ end
@@ -1,44 +1,58 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- def display_help
4
- puts "Usage: octopusci-tentacles <command>"
5
- puts " Acceptable Commands:"
6
- puts " start - Cleanup existing workers and start new worker processes in the background"
7
- puts " stop - Signals workers to exit when current job is finished"
8
- puts " restart - Synonym for the 'start' command, just here for convenience"
9
- puts " help - Display this help"
10
- puts ""
11
- puts " Example: octopusci-tentacles start"
12
- puts ""
13
- end
14
-
15
- if !["start", "stop", "restart", "help"].include?(ARGV[0])
16
- display_help()
17
- exit 1
18
- end
19
-
20
3
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
21
4
 
22
5
  require 'rubygems'
23
6
  require 'octopusci'
7
+ require 'trollop'
8
+
9
+ SUB_COMMANDS = %w(start, restart, stop, help)
10
+
11
+ p = Trollop::Parser.new do
12
+ version "Octopusci v#{Octopusci::Version} (c) Andrew De Ponte"
13
+ banner """Usage: octopusci-tentacles [-v|--version|-h|--help] <subcommand>
14
+ Acceptable SubCommands:
15
+ start - Cleanup existing workers and start new worker processes in the background
16
+ stop - Signals workers to exit when current job is finished
17
+ restart - Synonym for the 'start' command, just here for convenience
18
+ help - Display this help
19
+
20
+ Available Options:
21
+ """
22
+ stop_on SUB_COMMANDS
23
+ end
24
+
25
+ opts = Trollop::with_standard_exception_handling(p) do
26
+ o = p.parse ARGV
27
+ raise Trollop::HelpNeeded if ARGV.empty? # show help screen
28
+ o
29
+ end
30
+
31
+ def start_or_restart
32
+ # The StageLocker.load() method is called here not only to set things into
33
+ # valid initial state. But, also in the case that octopusci-tentacles was
34
+ # killed it nukes the potentially screwed up state the redis data is in and
35
+ # initializes it the proper state based on the config.
36
+ if Octopusci::Config.has_key?('stages') && Octopusci::StageLocker.empty?
37
+ puts "Reseting stage locker and loading stages in from config."
38
+ Octopusci::StageLocker.load(Octopusci::Config['stages'])
39
+ end
24
40
 
25
- # The StageLocker.load() method is called here not only to set things into
26
- # valid initial state. But, also in the case that octopusci-tentacles was
27
- # killed it nukes the potentially screwed up state the redis data is in and
28
- # initializes it the proper state based on the config.
29
- if Octopusci::Config.has_key?('stages')
30
- Octopusci::StageLocker.load(Octopusci::Config['stages'])
41
+ Octopusci::WorkerLauncher.cleanup_existing_workers()
42
+ Octopusci::WorkerLauncher.launch()
31
43
  end
32
44
 
33
- case ARGV[0]
45
+ cmd = ARGV.shift # get the subcommand
46
+ case cmd
34
47
  when "start"
35
- Octopusci::WorkerLauncher.cleanup_existing_workers()
36
- Octopusci::WorkerLauncher.launch()
48
+ start_or_restart()
37
49
  when "restart"
38
- Octopusci::WorkerLauncher.cleanup_existing_workers()
39
- Octopusci::WorkerLauncher.launch()
50
+ start_or_restart()
40
51
  when "stop"
41
52
  Octopusci::WorkerLauncher.cleanup_existing_workers()
42
53
  when "help"
43
- display_help()
54
+ p.educate
55
+ else
56
+ p.die "unknown subcommand #{cmd.inspect}", nil
44
57
  end
58
+
data/lib/octopusci/job.rb CHANGED
@@ -118,7 +118,7 @@ module Octopusci
118
118
  end
119
119
 
120
120
  def self.checkout_branch(job_conf)
121
- return run_shell_cmd("cd #{repository_path} 2>&1 && git fetch --all -p 2>&1 && git checkout #{@job['branch_name']} 2>&1 && git pull -f origin #{@job['branch_name']}:#{@job['branch_name']} 2>&1", true, false)
121
+ return run_shell_cmd("cd #{repository_path} 2>&1 && git fetch --all -p 2>&1 && git reset --hard && git checkout #{@job['branch_name']} 2>&1 && git pull -f origin #{@job['branch_name']}:#{@job['branch_name']} 2>&1", true, false)
122
122
  end
123
123
 
124
124
  def self.get_recip_email
@@ -1,3 +1,6 @@
1
+ require 'resque'
2
+ require 'yaml'
3
+
1
4
  module Octopusci
2
5
  class JobStore
3
6
  def self.prepend(job)
@@ -22,6 +22,11 @@
22
22
  color: white;
23
23
  background-color: #333;
24
24
  }
25
+
26
+ .version {
27
+ font-size: 11px;
28
+ margin-right: 10px;
29
+ }
25
30
 
26
31
  #main_content_area {
27
32
  width: 960px;
@@ -161,7 +166,7 @@
161
166
  <body>
162
167
  <div id="header">
163
168
  <div id="logo">
164
- Octopusci <% if @page_logo %> - <%= @page_logo %><% end %>
169
+ Octopusci <span class="version">v<%= Octopusci::Version %></span><% if @page_logo %>( <%= @page_logo %> )<% end %>
165
170
  </div>
166
171
  <div id="main_nav">
167
172
  <a href="/">Dashboard</a>
@@ -6,6 +6,14 @@ module Octopusci
6
6
  clear
7
7
  stages.each { |s| push(s) }
8
8
  end
9
+
10
+ def self.exists?
11
+ self.redis.exists('octopusci:stagelocker')
12
+ end
13
+
14
+ def self.empty?
15
+ !exists?
16
+ end
9
17
 
10
18
  def self.clear
11
19
  self.redis.del('octopusci:stagelocker')
@@ -1,3 +1,3 @@
1
1
  module Octopusci
2
- Version = VERSION = '0.3.6'
2
+ Version = VERSION = '0.3.7'
3
3
  end
@@ -17,6 +17,35 @@ describe "Octopusci::StageLocker" do
17
17
  end
18
18
  end
19
19
 
20
+ describe "#exists?" do
21
+ it "should check if the redis key exists for the stage locker" do
22
+ @mock_redis.should_receive(:exists).with('octopusci:stagelocker')
23
+ Octopusci::StageLocker.exists?
24
+ end
25
+
26
+ it "should return fales if the stage locker key does not exists in redis" do
27
+ @mock_redis.stub(:exists).and_return(false)
28
+ Octopusci::StageLocker.exists?.should == false
29
+ end
30
+
31
+ it "should return true if the stage locker key exists in redis" do
32
+ @mock_redis.stub(:exists).and_return(true)
33
+ Octopusci::StageLocker.exists?.should == true
34
+ end
35
+ end
36
+
37
+ describe "#empty?" do
38
+ it "should return true if exists? returns false" do
39
+ Octopusci::StageLocker.stub(:exists?).and_return(false)
40
+ Octopusci::StageLocker.empty?.should == true
41
+ end
42
+
43
+ it "should return false if exists? returns true" do
44
+ Octopusci::StageLocker.stub(:exists?).and_return(true)
45
+ Octopusci::StageLocker.empty?.should == false
46
+ end
47
+ end
48
+
20
49
  describe "#clear" do
21
50
  it "should clear all of the stages out of the stage locker" do
22
51
  r = mock('redis')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octopusci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.3.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-11-12 00:00:00.000000000 Z
13
+ date: 2011-12-12 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: sinatra
17
- requirement: &70209939639560 !ruby/object:Gem::Requirement
17
+ requirement: &70349244223700 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70209939639560
25
+ version_requirements: *70349244223700
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &70209939638360 !ruby/object:Gem::Requirement
28
+ requirement: &70349244223280 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70209939638360
36
+ version_requirements: *70349244223280
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: resque
39
- requirement: &70209939637360 !ruby/object:Gem::Requirement
39
+ requirement: &70349244222860 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70209939637360
47
+ version_requirements: *70349244222860
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: actionmailer
50
- requirement: &70209939636720 !ruby/object:Gem::Requirement
50
+ requirement: &70349244222440 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70209939636720
58
+ version_requirements: *70349244222440
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: multi_json
61
- requirement: &70209939635860 !ruby/object:Gem::Requirement
61
+ requirement: &70349244222020 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: '0'
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70209939635860
69
+ version_requirements: *70349244222020
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: time-ago-in-words
72
- requirement: &70209939635160 !ruby/object:Gem::Requirement
72
+ requirement: &70349244221600 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '0'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *70209939635160
80
+ version_requirements: *70349244221600
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: ansi2html
83
- requirement: &70209939634180 !ruby/object:Gem::Requirement
83
+ requirement: &70349244221180 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,21 @@ dependencies:
88
88
  version: '0'
89
89
  type: :runtime
90
90
  prerelease: false
91
- version_requirements: *70209939634180
91
+ version_requirements: *70349244221180
92
+ - !ruby/object:Gem::Dependency
93
+ name: trollop
94
+ requirement: &70349244220760 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: *70349244220760
92
103
  - !ruby/object:Gem::Dependency
93
104
  name: rake
94
- requirement: &70209939632520 !ruby/object:Gem::Requirement
105
+ requirement: &70349244220340 !ruby/object:Gem::Requirement
95
106
  none: false
96
107
  requirements:
97
108
  - - ! '>='
@@ -99,10 +110,10 @@ dependencies:
99
110
  version: '0'
100
111
  type: :development
101
112
  prerelease: false
102
- version_requirements: *70209939632520
113
+ version_requirements: *70349244220340
103
114
  - !ruby/object:Gem::Dependency
104
115
  name: rspec
105
- requirement: &70209939632020 !ruby/object:Gem::Requirement
116
+ requirement: &70349244219920 !ruby/object:Gem::Requirement
106
117
  none: false
107
118
  requirements:
108
119
  - - ! '>='
@@ -110,10 +121,10 @@ dependencies:
110
121
  version: '0'
111
122
  type: :development
112
123
  prerelease: false
113
- version_requirements: *70209939632020
124
+ version_requirements: *70349244219920
114
125
  - !ruby/object:Gem::Dependency
115
126
  name: rack-test
116
- requirement: &70209939631460 !ruby/object:Gem::Requirement
127
+ requirement: &70349244219500 !ruby/object:Gem::Requirement
117
128
  none: false
118
129
  requirements:
119
130
  - - ! '>='
@@ -121,10 +132,10 @@ dependencies:
121
132
  version: '0'
122
133
  type: :development
123
134
  prerelease: false
124
- version_requirements: *70209939631460
135
+ version_requirements: *70349244219500
125
136
  - !ruby/object:Gem::Dependency
126
137
  name: guard
127
- requirement: &70209939630660 !ruby/object:Gem::Requirement
138
+ requirement: &70349244235460 !ruby/object:Gem::Requirement
128
139
  none: false
129
140
  requirements:
130
141
  - - ! '>='
@@ -132,10 +143,10 @@ dependencies:
132
143
  version: '0'
133
144
  type: :development
134
145
  prerelease: false
135
- version_requirements: *70209939630660
146
+ version_requirements: *70349244235460
136
147
  - !ruby/object:Gem::Dependency
137
148
  name: rb-fsevent
138
- requirement: &70209939628140 !ruby/object:Gem::Requirement
149
+ requirement: &70349244235040 !ruby/object:Gem::Requirement
139
150
  none: false
140
151
  requirements:
141
152
  - - ! '>='
@@ -143,10 +154,10 @@ dependencies:
143
154
  version: '0'
144
155
  type: :development
145
156
  prerelease: false
146
- version_requirements: *70209939628140
157
+ version_requirements: *70349244235040
147
158
  - !ruby/object:Gem::Dependency
148
159
  name: growl_notify
149
- requirement: &70209939626500 !ruby/object:Gem::Requirement
160
+ requirement: &70349244234620 !ruby/object:Gem::Requirement
150
161
  none: false
151
162
  requirements:
152
163
  - - ! '>='
@@ -154,10 +165,10 @@ dependencies:
154
165
  version: '0'
155
166
  type: :development
156
167
  prerelease: false
157
- version_requirements: *70209939626500
168
+ version_requirements: *70349244234620
158
169
  - !ruby/object:Gem::Dependency
159
170
  name: guard-rspec
160
- requirement: &70209939624700 !ruby/object:Gem::Requirement
171
+ requirement: &70349244234200 !ruby/object:Gem::Requirement
161
172
  none: false
162
173
  requirements:
163
174
  - - ! '>='
@@ -165,8 +176,8 @@ dependencies:
165
176
  version: '0'
166
177
  type: :development
167
178
  prerelease: false
168
- version_requirements: *70209939624700
169
- description: A multi-branch Continous Integration server that integrates with GitHub
179
+ version_requirements: *70349244234200
180
+ description: A multi-branch Continuous Integration server that integrates with GitHub
170
181
  email:
171
182
  - cyphactor@gmail.com
172
183
  - sarmiena@gmail.com
@@ -174,6 +185,8 @@ executables:
174
185
  - octopusci-tentacles
175
186
  - octopusci-skel
176
187
  - octopusci-reset-redis
188
+ - octopusci-reset-stage-locker
189
+ - octopusci-post-build-request
177
190
  extensions: []
178
191
  extra_rdoc_files: []
179
192
  files:
@@ -204,11 +217,12 @@ files:
204
217
  - lib/octopusci/version.rb
205
218
  - lib/octopusci/worker_launcher.rb
206
219
  - lib/octopusci.rb
207
- - bin/octopusci
220
+ - bin/octopusci-install
221
+ - bin/octopusci-post-build-request
208
222
  - bin/octopusci-reset-redis
223
+ - bin/octopusci-reset-stage-locker
209
224
  - bin/octopusci-skel
210
225
  - bin/octopusci-tentacles
211
- - bin/pusci-stage
212
226
  - spec/lib/octopusci/config_spec.rb
213
227
  - spec/lib/octopusci/io_spec.rb
214
228
  - spec/lib/octopusci/job_spec.rb
data/bin/octopusci DELETED
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
-
5
- require 'rubygems'
6
- require 'optparse'
7
-
8
- # This hash will hold all of the options
9
- # parsed from the command-line by
10
- # OptionParser.
11
- options = {}
12
-
13
- optparse = OptionParser.new do|opts|
14
- # Set a banner, displayed at the top
15
- # of the help screen.
16
- opts.banner = "Usage: optparse1.rb [options] file1 file2 ..."
17
-
18
- # Define the options, and what they do
19
- options[:verbose] = false
20
- opts.on( '-v', '--verbose', 'Output more information' ) do
21
- options[:verbose] = true
22
- end
23
-
24
- options[:quick] = false
25
- opts.on( '-q', '--quick', 'Perform the task quickly' ) do
26
- options[:quick] = true
27
- end
28
-
29
- options[:logfile] = nil
30
- opts.on( '-l', '--logfile FILE', 'Write log to FILE' ) do |file|
31
- options[:logfile] = file
32
- end
33
-
34
- # This displays the help screen, all programs are
35
- # assumed to have this option.
36
- opts.on( '-h', '--help', 'Display this screen' ) do
37
- puts opts
38
- exit
39
- end
40
- end
41
-
42
- # Parse the command-line. Remember there are two forms
43
- # of the parse method. The 'parse' method simply parses
44
- # ARGV, while the 'parse!' method parses ARGV and removes
45
- # any options found there, as well as any parameters for
46
- # the options. What's left is the list of files to resize.
47
- optparse.parse!
48
-
49
- puts "Being verbose" if options[:verbose]
50
- puts "Being quick" if options[:quick]
51
- puts "Logging to file #{options[:logfile]}" if options[:logfile]
52
-
53
- ARGV.each do|f|
54
- puts "Resizing image #{f}..."
55
- sleep 0.5
56
- end
data/bin/pusci-stage DELETED
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
-
5
- require 'rubygems'
6
- require 'optparse'
7
- require 'octopusci'
8
-
9
- # This hash will hold all of the options
10
- # parsed from the command-line by
11
- # OptionParser.
12
- options = {}
13
-
14
- optparse = OptionParser.new do|opts|
15
- # Set a banner, displayed at the top
16
- # of the help screen.
17
- opts.banner = "Usage: pusci-stage [options] stage_name"
18
-
19
- # Define the options, and what they do
20
- options[:add] = false
21
- opts.on('-a', '--add', 'Add a stage back into the pool') do
22
- options[:add] = true
23
- end
24
-
25
- options[:rem] = false
26
- opts.on( '-r', '--rem', 'Rem a stage from the pool' ) do
27
- options[:rem] = true
28
- end
29
-
30
- options[:list] = false
31
- opts.on( '-l', '--list', 'List all stages' ) do
32
- options[:list] = true
33
- end
34
-
35
- options[:pool] = false
36
- opts.on( '-p', '--pool', 'List all stages currently in the pool' ) do
37
- options[:pool] = true
38
- end
39
-
40
- # This displays the help screen, all programs are
41
- # assumed to have this option.
42
- opts.on( '-h', '--help', 'Display the help screen' ) do
43
- puts opts
44
- exit
45
- end
46
- end
47
-
48
- # Parse the command-line. Remember there are two forms
49
- # of the parse method. The 'parse' method simply parses
50
- # ARGV, while the 'parse!' method parses ARGV and removes
51
- # any options found there, as well as any parameters for
52
- # the options. What's left is the list of files to resize.
53
- optparse.parse!
54
-
55
- if options[:list] == true
56
- Octopusci::StageLocker.stages.each do |s|
57
- puts s
58
- end
59
- elsif options[:pool] == true
60
- puts Octopusci::StageLocker.pool
61
- elsif options[:add] == true
62
- Octopusci::StageLocker.push(ARGV[0])
63
- elsif options[:rem] == true
64
- Octopusci::StageLocker.rem(ARGV[0])
65
- end
66
-
67
- exit