pandemonium 0.0.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.md +17 -0
- data/bin/pandemonium +12 -0
- data/bin/worker.sh +18 -0
- data/config/pandemonium.rb +11 -0
- data/lib/pandemonium/api.rb +52 -0
- data/lib/pandemonium/boss.rb +16 -0
- data/lib/pandemonium/cli.rb +66 -0
- data/lib/pandemonium/job.rb +22 -0
- data/lib/pandemonium/loader.rb +25 -0
- data/lib/pandemonium/message.rb +3 -0
- data/lib/pandemonium/repo.rb +15 -0
- data/lib/pandemonium/repos.rb +23 -0
- data/lib/pandemonium/usain_bolt.rb +35 -0
- data/pandemonium.gemspec +16 -0
- metadata +108 -0
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Pandemonium
|
2
|
+
|
3
|
+

|
4
|
+
|
5
|
+
Everything started with this tweet:
|
6
|
+
https://twitter.com/poteland/status/339436974261805059
|
7
|
+
|
8
|
+
And then I tried to think the quickest (and probably dirtiest) way to do a
|
9
|
+
deploy app (aka Big Red Button)
|
10
|
+
|
11
|
+
## Commands
|
12
|
+
|
13
|
+
```bash
|
14
|
+
pandemonium add [repository] [deploy command]
|
15
|
+
pandemonium list
|
16
|
+
pandemonium run
|
17
|
+
```
|
data/bin/pandemonium
ADDED
data/bin/worker.sh
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
name="$1"
|
4
|
+
repo="$2"
|
5
|
+
deploy_script="$3"
|
6
|
+
branch=$4 || "master"
|
7
|
+
destination_folder="/tmp/$name"
|
8
|
+
|
9
|
+
|
10
|
+
if [ -d $destination_folder ]; then
|
11
|
+
cd $destination_folder
|
12
|
+
git pull
|
13
|
+
else
|
14
|
+
git clone $repo $destination_folder
|
15
|
+
fi
|
16
|
+
|
17
|
+
cd $destination_folder
|
18
|
+
$deploy_script
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "toml"
|
2
|
+
require "pandemonium/boss"
|
3
|
+
require "pandemonium/loader"
|
4
|
+
|
5
|
+
EM.kqueue = true
|
6
|
+
EventMachine.watch_file(Pandemonium::Loader::REPO_FILE, Pandemonium::Loader, config)
|
7
|
+
Pandemonium::ConfigLoader.new(config).load_repos
|
8
|
+
|
9
|
+
config["jobs"] = Hash.new do |h, k|
|
10
|
+
h[k] = Pandemonium::Boss.new(EM::Channel.new)
|
11
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "goliath/api"
|
2
|
+
|
3
|
+
EM.kqueue = true
|
4
|
+
|
5
|
+
module Pandemonium
|
6
|
+
class API < Goliath::API
|
7
|
+
use Goliath::Rack::Params
|
8
|
+
use Goliath::Rack::Render, ["json"]
|
9
|
+
|
10
|
+
def response(env)
|
11
|
+
case env["PATH_INFO"]
|
12
|
+
when "/"
|
13
|
+
puts env.repos
|
14
|
+
[200, {}, "Pandemonium"]
|
15
|
+
when "/attach"
|
16
|
+
project_name = env.params["project_name"]
|
17
|
+
boss = env.jobs[project_name]
|
18
|
+
channel = boss.channel
|
19
|
+
|
20
|
+
env.stream_close if !boss || !boss.running?
|
21
|
+
|
22
|
+
env["subscription"] = channel.subscribe do |message|
|
23
|
+
case message.type
|
24
|
+
when :data
|
25
|
+
env.stream_send(message.content)
|
26
|
+
when :exit_status
|
27
|
+
env.stream_send("Exit status: #{message.content}")
|
28
|
+
when :action
|
29
|
+
if message.content == :finish
|
30
|
+
channel.unsubscribe(env["subscription"])
|
31
|
+
env.stream_close
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
streaming_response(202, {"X-Stream" => "Pandemonium"})
|
37
|
+
when "/deploy"
|
38
|
+
project_name = env.params["project_name"]
|
39
|
+
project = env.repos[project_name]
|
40
|
+
|
41
|
+
boss = env.jobs[project_name]
|
42
|
+
|
43
|
+
if boss.running?
|
44
|
+
[200, {}, "Already deploying"]
|
45
|
+
else
|
46
|
+
boss.run_command project
|
47
|
+
[201, {}, "Deploying"]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "pandemonium/job"
|
2
|
+
|
3
|
+
module Pandemonium
|
4
|
+
Boss = Struct.new(:channel) do
|
5
|
+
def run_command(repo)
|
6
|
+
puts "Starting Job"
|
7
|
+
|
8
|
+
@working_on = Pandemonium::Job.new(repo, channel)
|
9
|
+
@working_on.run
|
10
|
+
end
|
11
|
+
|
12
|
+
def running?
|
13
|
+
!!@working_on && @working_on.running?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "goliath/runner"
|
2
|
+
require "toml"
|
3
|
+
require "uri"
|
4
|
+
require "pandemonium/api"
|
5
|
+
require "pandemonium/loader"
|
6
|
+
|
7
|
+
module Pandemonium
|
8
|
+
module CLI
|
9
|
+
class << self
|
10
|
+
def run
|
11
|
+
# There must be a prettier way to pass options to the runner
|
12
|
+
argv = ["-sv"]
|
13
|
+
argv << "-c"
|
14
|
+
argv << File.join(File.expand_path("../../..", __FILE__), "config/pandemonium.rb")
|
15
|
+
|
16
|
+
runner = Goliath::Runner.new(argv, nil)
|
17
|
+
api = Pandemonium::API
|
18
|
+
|
19
|
+
runner.api = api.new
|
20
|
+
runner.app = Goliath::Rack::Builder.build(api, runner.api)
|
21
|
+
runner.run
|
22
|
+
end
|
23
|
+
|
24
|
+
def help
|
25
|
+
end
|
26
|
+
|
27
|
+
def list
|
28
|
+
get_projects.each do |name, items|
|
29
|
+
if !items["last_status"].to_s.empty?
|
30
|
+
message = "#{name}: [#{items["last_run"]}] #{items["deploy_script"]}"
|
31
|
+
puts colorize(message, items["last_status"] == 0 ? 32 : 31)
|
32
|
+
else
|
33
|
+
puts "#{name}: #{items["deploy_script"]}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def colorize(text, color_code)
|
39
|
+
"\e[#{color_code}m#{text}\e[0m"
|
40
|
+
end
|
41
|
+
|
42
|
+
def add(repo, script)
|
43
|
+
config = get_projects
|
44
|
+
project_name = File.basename(repo, ".git")
|
45
|
+
repo_name = escape_key(project_name)
|
46
|
+
|
47
|
+
config[repo_name] = {
|
48
|
+
repository: repo,
|
49
|
+
deploy_script: script,
|
50
|
+
last_run: "",
|
51
|
+
last_status: ""
|
52
|
+
}
|
53
|
+
|
54
|
+
File.open(Pandemonium::Loader::REPO_FILE, "w") << TOML.dump(config)
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_projects
|
58
|
+
TOML.load_file(Pandemonium::Loader::REPO_FILE)
|
59
|
+
end
|
60
|
+
|
61
|
+
def escape_key(key)
|
62
|
+
key.tr("-", "_")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "pandemonium/usain_bolt"
|
2
|
+
|
3
|
+
module Pandemonium
|
4
|
+
Job = Struct.new(:repo, :output) do
|
5
|
+
def run
|
6
|
+
worker = File.join(File.expand_path("../../..", __FILE__), "bin/worker.sh")
|
7
|
+
command = "#{worker} '#{repo.name}' '#{repo.repository}' '#{repo.deploy_script}'"
|
8
|
+
puts "Unix, do your thing. Running #{command}"
|
9
|
+
|
10
|
+
@shell_command = EM.popen(command, Pandemonium::UsainBolt, self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def running?
|
14
|
+
@shell_command.running?
|
15
|
+
end
|
16
|
+
|
17
|
+
def finish(exit_status)
|
18
|
+
repo.last_status = exit_status
|
19
|
+
repo.save
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "pandemonium/repos"
|
2
|
+
|
3
|
+
module Pandemonium
|
4
|
+
module Loader
|
5
|
+
REPO_FILE = File.expand_path("~/.pandemonium").freeze
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_repos
|
12
|
+
puts "reloading repos"
|
13
|
+
repos = TOML.load_file(REPO_FILE)
|
14
|
+
|
15
|
+
@config["repos"] = Pandemonium::Repos.new
|
16
|
+
@config["repos"].load(repos)
|
17
|
+
end
|
18
|
+
|
19
|
+
alias file_modified load_repos
|
20
|
+
end
|
21
|
+
|
22
|
+
class ConfigLoader
|
23
|
+
include Loader
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pandemonium
|
2
|
+
Repo = Struct.new(:name, :repository, :deploy_script, :last_run, :last_status) do
|
3
|
+
def save
|
4
|
+
config = TOML.load_file(Pandemonium::Loader::REPO_FILE)
|
5
|
+
config[name].merge!({
|
6
|
+
"last_run" => Time.now,
|
7
|
+
"last_status" => last_status
|
8
|
+
})
|
9
|
+
|
10
|
+
toml_file = TOML.dump(config)
|
11
|
+
|
12
|
+
File.write(Pandemonium::Loader::REPO_FILE, toml_file)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "pandemonium/repo"
|
2
|
+
|
3
|
+
module Pandemonium
|
4
|
+
class Repos
|
5
|
+
def initialize
|
6
|
+
@repos = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](name)
|
10
|
+
@repos.select { |item| item.name == name }.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def <<(repo)
|
14
|
+
@repos << repo
|
15
|
+
end
|
16
|
+
|
17
|
+
def load(array)
|
18
|
+
Array(array).each do |name, repo|
|
19
|
+
@repos << Repo.new(name, repo["repository"], repo["deploy_script"])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "pandemonium/message"
|
2
|
+
|
3
|
+
module Pandemonium
|
4
|
+
class UsainBolt < EM::Connection
|
5
|
+
def initialize(job)
|
6
|
+
@job = job
|
7
|
+
@output = job.output
|
8
|
+
@buffer = StringIO.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def post_init
|
12
|
+
@running = true
|
13
|
+
puts "Running!"
|
14
|
+
end
|
15
|
+
|
16
|
+
def receive_data(data)
|
17
|
+
@output << Pandemonium::Message.new(:data, data)
|
18
|
+
@buffer << data
|
19
|
+
|
20
|
+
puts "Command output: #{data}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def unbind
|
24
|
+
@running = false
|
25
|
+
@buffer = nil
|
26
|
+
|
27
|
+
@job.finish(get_status.exitstatus)
|
28
|
+
|
29
|
+
@output << Pandemonium::Message.new(:exit_status, get_status.exitstatus)
|
30
|
+
@output << Pandemonium::Message.new(:action, :finish)
|
31
|
+
end
|
32
|
+
|
33
|
+
def running?; @running; end
|
34
|
+
end
|
35
|
+
end
|
data/pandemonium.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "pandemonium"
|
3
|
+
s.executables = ["pandemonium"]
|
4
|
+
s.version = "0.0.1"
|
5
|
+
s.summary = "Pandemonium the deployer"
|
6
|
+
s.description = "Pandemonium is an app to run deployment instructions"
|
7
|
+
s.authors = ["elcuervo"]
|
8
|
+
s.email = ["yo@brunoaguirre.com"]
|
9
|
+
s.homepage = "http://github.com/elcuervo/pandemonium"
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.test_files = `git ls-files test`.split("\n")
|
12
|
+
|
13
|
+
s.add_dependency("goliath", "~> 1.0.2")
|
14
|
+
s.add_dependency("clap", "~> 1.0.0")
|
15
|
+
s.add_dependency("toml-rb", "~> 0.1.3")
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pandemonium
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- elcuervo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: goliath
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.0.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.0.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: clap
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 1.0.0
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: toml-rb
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.1.3
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.1.3
|
62
|
+
description: Pandemonium is an app to run deployment instructions
|
63
|
+
email:
|
64
|
+
- yo@brunoaguirre.com
|
65
|
+
executables:
|
66
|
+
- pandemonium
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- README.md
|
71
|
+
- bin/pandemonium
|
72
|
+
- bin/worker.sh
|
73
|
+
- config/pandemonium.rb
|
74
|
+
- lib/pandemonium/api.rb
|
75
|
+
- lib/pandemonium/boss.rb
|
76
|
+
- lib/pandemonium/cli.rb
|
77
|
+
- lib/pandemonium/job.rb
|
78
|
+
- lib/pandemonium/loader.rb
|
79
|
+
- lib/pandemonium/message.rb
|
80
|
+
- lib/pandemonium/repo.rb
|
81
|
+
- lib/pandemonium/repos.rb
|
82
|
+
- lib/pandemonium/usain_bolt.rb
|
83
|
+
- pandemonium.gemspec
|
84
|
+
homepage: http://github.com/elcuervo/pandemonium
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.23
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Pandemonium the deployer
|
108
|
+
test_files: []
|