torquebox-stompbox 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +144 -0
- data/LICENSE.txt +21 -0
- data/README.md +125 -0
- data/app/authentication.rb +55 -0
- data/app/deployer.rb +156 -0
- data/app/helpers.rb +59 -0
- data/app/models.rb +150 -0
- data/app/tasks/deployer_task.rb +37 -0
- data/app/views/css/html5reset.sass +82 -0
- data/app/views/css/styles.scss +198 -0
- data/app/views/layout.haml +52 -0
- data/app/views/pushes/index.haml +63 -0
- data/app/views/repositories/form.haml +7 -0
- data/app/views/repositories/index.haml +38 -0
- data/app/views/sessions/new.haml +8 -0
- data/bin/dbsetup +97 -0
- data/bin/stompbox +130 -0
- data/config.ru +5 -0
- data/spec/auth_spec.rb +50 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/stompbox_spec.rb +50 -0
- data/stompbox.rb +148 -0
- metadata +324 -0
data/Gemfile.lock
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.2.5)
|
5
|
+
backports (2.0.3)
|
6
|
+
bcrypt-ruby (2.1.4-java)
|
7
|
+
data_mapper (1.1.0)
|
8
|
+
dm-aggregates (= 1.1.0)
|
9
|
+
dm-constraints (= 1.1.0)
|
10
|
+
dm-core (= 1.1.0)
|
11
|
+
dm-migrations (= 1.1.0)
|
12
|
+
dm-serializer (= 1.1.0)
|
13
|
+
dm-timestamps (= 1.1.0)
|
14
|
+
dm-transactions (= 1.1.0)
|
15
|
+
dm-types (= 1.1.0)
|
16
|
+
dm-validations (= 1.1.0)
|
17
|
+
data_objects (0.10.3)
|
18
|
+
addressable (~> 2.1)
|
19
|
+
diff-lcs (1.1.2)
|
20
|
+
dm-aggregates (1.1.0)
|
21
|
+
dm-core (~> 1.1.0)
|
22
|
+
dm-constraints (1.1.0)
|
23
|
+
dm-core (~> 1.1.0)
|
24
|
+
dm-core (1.1.0)
|
25
|
+
addressable (~> 2.2.4)
|
26
|
+
dm-do-adapter (1.1.0)
|
27
|
+
data_objects (~> 0.10.2)
|
28
|
+
dm-core (~> 1.1.0)
|
29
|
+
dm-migrations (1.1.0)
|
30
|
+
dm-core (~> 1.1.0)
|
31
|
+
dm-observer (1.1.0)
|
32
|
+
dm-core (~> 1.1.0)
|
33
|
+
dm-postgres-adapter (1.1.0)
|
34
|
+
dm-do-adapter (~> 1.1.0)
|
35
|
+
do_postgres (~> 0.10.2)
|
36
|
+
dm-serializer (1.1.0)
|
37
|
+
dm-core (~> 1.1.0)
|
38
|
+
fastercsv (~> 1.5.4)
|
39
|
+
json (~> 1.4.6)
|
40
|
+
dm-timestamps (1.1.0)
|
41
|
+
dm-core (~> 1.1.0)
|
42
|
+
dm-transactions (1.1.0)
|
43
|
+
dm-core (~> 1.1.0)
|
44
|
+
dm-types (1.1.0)
|
45
|
+
bcrypt-ruby (~> 2.1.4)
|
46
|
+
dm-core (~> 1.1.0)
|
47
|
+
fastercsv (~> 1.5.4)
|
48
|
+
json (~> 1.4.6)
|
49
|
+
stringex (~> 1.2.0)
|
50
|
+
uuidtools (~> 2.1.2)
|
51
|
+
dm-validations (1.1.0)
|
52
|
+
dm-core (~> 1.1.0)
|
53
|
+
do_jdbc (0.10.3-java)
|
54
|
+
data_objects (= 0.10.3)
|
55
|
+
do_postgres (0.10.3-java)
|
56
|
+
data_objects (= 0.10.3)
|
57
|
+
do_jdbc (= 0.10.3)
|
58
|
+
jdbc-postgres (>= 8.2)
|
59
|
+
extlib (0.9.15)
|
60
|
+
fastercsv (1.5.4)
|
61
|
+
git (1.2.5)
|
62
|
+
haml (3.0.25)
|
63
|
+
jdbc-postgres (9.0.801)
|
64
|
+
jeweler (1.5.2)
|
65
|
+
bundler (~> 1.0.0)
|
66
|
+
git (>= 1.2.5)
|
67
|
+
rake
|
68
|
+
json (1.4.6-java)
|
69
|
+
json_pure (1.5.1)
|
70
|
+
monkey-lib (0.5.4)
|
71
|
+
backports
|
72
|
+
rack (1.2.2)
|
73
|
+
rack-flash (0.1.1)
|
74
|
+
rack
|
75
|
+
rack-test (0.5.7)
|
76
|
+
rack (>= 1.0)
|
77
|
+
rake (0.8.7)
|
78
|
+
rspec (2.5.0)
|
79
|
+
rspec-core (~> 2.5.0)
|
80
|
+
rspec-expectations (~> 2.5.0)
|
81
|
+
rspec-mocks (~> 2.5.0)
|
82
|
+
rspec-core (2.5.1)
|
83
|
+
rspec-expectations (2.5.0)
|
84
|
+
diff-lcs (~> 1.1.2)
|
85
|
+
rspec-mocks (2.5.0)
|
86
|
+
sinatra (1.1.2)
|
87
|
+
rack (~> 1.1)
|
88
|
+
tilt (~> 1.2)
|
89
|
+
sinatra-advanced-routes (0.5.1)
|
90
|
+
monkey-lib (~> 0.5.0)
|
91
|
+
sinatra (~> 1.0)
|
92
|
+
sinatra-sugar (~> 0.5.0)
|
93
|
+
sinatra-reloader (0.5.0)
|
94
|
+
sinatra (~> 1.0)
|
95
|
+
sinatra-advanced-routes (~> 0.5.0)
|
96
|
+
sinatra-sugar (0.5.0)
|
97
|
+
monkey-lib (~> 0.5.0)
|
98
|
+
sinatra (~> 1.0)
|
99
|
+
state_machine (0.10.3)
|
100
|
+
stringex (1.2.1)
|
101
|
+
thor (0.14.6)
|
102
|
+
tilt (1.2.2)
|
103
|
+
torquebox (1.0.0.CR1)
|
104
|
+
torquebox-base (= 1.0.0.CR1)
|
105
|
+
torquebox-messaging (= 1.0.0.CR1)
|
106
|
+
torquebox-naming (= 1.0.0.CR1)
|
107
|
+
torquebox-rake-support (= 1.0.0.CR1)
|
108
|
+
torquebox-vfs (= 1.0.0.CR1)
|
109
|
+
torquebox-web (= 1.0.0.CR1)
|
110
|
+
torquebox-base (1.0.0.CR1-java)
|
111
|
+
torquebox-messaging (1.0.0.CR1-java)
|
112
|
+
torquebox-base (= 1.0.0.CR1)
|
113
|
+
torquebox-naming (= 1.0.0.CR1)
|
114
|
+
torquebox-naming (1.0.0.CR1-java)
|
115
|
+
torquebox-rake-support (1.0.0.CR1)
|
116
|
+
torquebox-vfs (1.0.0.CR1-java)
|
117
|
+
torquebox-web (1.0.0.CR1-java)
|
118
|
+
uuidtools (2.1.2)
|
119
|
+
|
120
|
+
PLATFORMS
|
121
|
+
java
|
122
|
+
|
123
|
+
DEPENDENCIES
|
124
|
+
bundler
|
125
|
+
data_mapper (~> 1.1)
|
126
|
+
dm-core (~> 1.1)
|
127
|
+
dm-migrations (~> 1.1)
|
128
|
+
dm-observer (~> 1.1)
|
129
|
+
dm-postgres-adapter (~> 1.1)
|
130
|
+
dm-timestamps (~> 1.1)
|
131
|
+
extlib
|
132
|
+
git
|
133
|
+
haml (~> 3.0)
|
134
|
+
jeweler
|
135
|
+
json_pure
|
136
|
+
rack-flash (= 0.1.1)
|
137
|
+
rack-test
|
138
|
+
rake
|
139
|
+
rspec
|
140
|
+
sinatra (= 1.1.2)
|
141
|
+
sinatra-reloader (= 0.5.0)
|
142
|
+
state_machine
|
143
|
+
thor
|
144
|
+
torquebox (= 1.0.0.CR1)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010, Red Hat, Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# StompBox : A Deployer for TorqueBox
|
2
|
+
|
3
|
+
StompBox is a simple Sinatra app that can be used to manage deployments on
|
4
|
+
[TorqueBox][torquebox] by accepting commit notifications from [GitHub][github].
|
5
|
+
It provides a user interface for managing one-click deployment and undeployment
|
6
|
+
of your github repositories to TorqueBox for specific branches and commit
|
7
|
+
points.
|
8
|
+
|
9
|
+
## Why?
|
10
|
+
|
11
|
+
StompBox is useful for testing and development environments where your code is
|
12
|
+
changing frequently and you want to quickly deploy working branches and staging
|
13
|
+
instances. It integrates with your [GitHub][github] repositories to enable
|
14
|
+
extremely quick and simple app deployment of any Rack-based application. And
|
15
|
+
it does all this on top of the industrial-strength TorqueBox platform,
|
16
|
+
automatically providing your application with enterprise-level functionality
|
17
|
+
such as messaging, scheduling, tasks, clustering and more.
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
If you don't already have a TorqueBox instance installed, you should do that
|
22
|
+
first. Head on over to the [TorqueBox][torquebox] web site and follow the
|
23
|
+
detailed instructions for downloading, installing, configuring and running
|
24
|
+
TorqueBox. Don't worry - it's easy.
|
25
|
+
|
26
|
+
StompBox hasn't been tested on Windows and may not work in that environment.
|
27
|
+
However, if you are running a Unix-y system such as Fedora or Mac OSX, then you
|
28
|
+
should be fine.
|
29
|
+
|
30
|
+
Once you've installed TorqueBox, clone the StompBox repository, install the
|
31
|
+
gems, and deploy it to your running TorqueBox instance.
|
32
|
+
|
33
|
+
$ git clone git@github.com:lance/stompbox.git
|
34
|
+
Cloning into stompbox...
|
35
|
+
remote: Counting objects: 187, done.
|
36
|
+
remote: Compressing objects: 100% (168/168), done.
|
37
|
+
remote: Total 187 (delta 108), reused 0 (delta 0)
|
38
|
+
Receiving objects: 100% (187/187), 22.96 KiB, done.
|
39
|
+
Resolving deltas: 100% (108/108), done.
|
40
|
+
|
41
|
+
$ cd stompbox && bundle install
|
42
|
+
<output clipped for brevity - you should see this at the end>
|
43
|
+
Your bundle is complete! It was installed into /path/to/gem/home
|
44
|
+
|
45
|
+
$ rake torquebox:deploy
|
46
|
+
|
47
|
+
## Configuration
|
48
|
+
|
49
|
+
Configuration options are found in config/torquebox.yml. Here are some things
|
50
|
+
you'll want to pay attention to.
|
51
|
+
|
52
|
+
* **DATABASE_URL** Provide a URI for connecting to your database. By convention,
|
53
|
+
StompBox uses a database called "stompbox", but you can change this to
|
54
|
+
whatever you want as long as it is supported by DataMapper. Be sure the user
|
55
|
+
specified in the connection URI has appropriate privileges for executing DDL
|
56
|
+
on your database. When the app starts for the first time, the tables will be
|
57
|
+
created and it will fail if your user doesn't have the proper permissions.
|
58
|
+
|
59
|
+
* **AUTO_MIGRATE** The first time you run StompBox, you'll want to have this on
|
60
|
+
so that your database is automagically created. After that, it's most efficient
|
61
|
+
to just unset this option by commenting it out.
|
62
|
+
|
63
|
+
* **DEPLOYMENTS** When you deploy an application using StompBox, it clones the
|
64
|
+
git repository into this directory. Make sure that your TorqueBox instance is
|
65
|
+
running as a user with enough privileges to write to this directory.
|
66
|
+
|
67
|
+
* **REQUIRE_AUTHENTICATION** To turn authentication on, set this to any non-nil
|
68
|
+
value. StompBox uses the built-in JAAS authentication provided by TorqueBox and
|
69
|
+
JBossAS. See the **Authentication** section below for more information.
|
70
|
+
|
71
|
+
* **API_KEY** This should be set to something unguessable like an SHA1 hash.
|
72
|
+
You can generate these any number of ways.
|
73
|
+
|
74
|
+
Here's one one way to generate a key.
|
75
|
+
|
76
|
+
$ echo "Now is the winter of our discontent made glorious summer by this son of York" | openssl sha1
|
77
|
+
|
78
|
+
(stdin)= e4ba3556d1d059e2eadca9488b093d6685657e00
|
79
|
+
|
80
|
+
## Authentication
|
81
|
+
|
82
|
+
StompBox uses the built-in JAAS authentication provided by JBoss and exposed
|
83
|
+
via TorqueBox. If this is a development system (it probably should be), the
|
84
|
+
simplest way to set usernames and passwords is to use the builtin rake task.
|
85
|
+
|
86
|
+
$ rake torquebox:auth:adduser username:password
|
87
|
+
|
88
|
+
Be sure to set REQUIRE_AUTHENTICATION in config/torquebox.yml as well.
|
89
|
+
Voilá, authentication is enabled.
|
90
|
+
|
91
|
+
TorqueBox (and subsequently StompBox) can also authenticate with any other
|
92
|
+
realm you have configured in your JBossAS. If you have configured JAAS settings
|
93
|
+
in your TorqueBox instance, you may authenticate against them by supplying
|
94
|
+
the authentication realm in config/torquebox.yml as shown.
|
95
|
+
|
96
|
+
auth:
|
97
|
+
default:
|
98
|
+
domain: my-configured-jaas-realm
|
99
|
+
|
100
|
+
## Usage
|
101
|
+
|
102
|
+
Start by telling StompBox what repositories and branches you want to track.
|
103
|
+
Once you've got everything configured and deployed, you can start by telling
|
104
|
+
StompBox what repositories and branches you want to track. Then, from
|
105
|
+
[GitHub][github], browse to the repository admin screen for one of the
|
106
|
+
repositories you specified in `config/stompbox.yml`. Select "Service Hooks" ->
|
107
|
+
"Post Receive URLs" and enter your StompBox URL plus your api_key (you
|
108
|
+
configured it didn't you?). It should look something like this.
|
109
|
+
|
110
|
+
http://mydomain.com/stompbox/push/3821A95D456134214FAD6FA91A2BAFE574D47151
|
111
|
+
|
112
|
+
After you save your settings, testing the service hook should send a POST
|
113
|
+
request to your StompBox. Play around.
|
114
|
+
|
115
|
+
## Caveats
|
116
|
+
|
117
|
+
This project is very immature and there are many features which are outstanding (such as any real authentication). You should **not** use it in a production environment. It is currently used for research, development and testing only.
|
118
|
+
|
119
|
+
## License
|
120
|
+
|
121
|
+
This software is distributed under an [MIT software license][license].
|
122
|
+
|
123
|
+
[torquebox]: http://torquebox.org "TorqueBox"
|
124
|
+
[github]: https://github.com "GitHub"
|
125
|
+
[license]: 'LICENSE.txt' "MIT License"
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'torquebox'
|
18
|
+
require 'org/torquebox/auth/authentication'
|
19
|
+
|
20
|
+
module StompBox
|
21
|
+
module Authentication
|
22
|
+
|
23
|
+
def login_path
|
24
|
+
"#{request.script_name}/login"
|
25
|
+
end
|
26
|
+
|
27
|
+
def authenticated?
|
28
|
+
!session[:user].nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
def authenticate(username, password)
|
32
|
+
return false if username.blank? || password.blank?
|
33
|
+
authenticator = TorqueBox::Authentication.default
|
34
|
+
authenticator.authenticate(username, password) do
|
35
|
+
session[:user] = username
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def skip_authentication
|
40
|
+
request.env['SKIP_AUTH'] = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def require_authentication
|
44
|
+
return if request.env['SKIP_AUTH']
|
45
|
+
return if authenticated?
|
46
|
+
redirect login_path
|
47
|
+
end
|
48
|
+
|
49
|
+
def logout
|
50
|
+
session[:user] = nil
|
51
|
+
redirect login_path
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
data/app/deployer.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'git'
|
18
|
+
require 'open3'
|
19
|
+
require 'models'
|
20
|
+
require 'torquebox-rake-support'
|
21
|
+
require 'torquebox/rake/tasks'
|
22
|
+
require 'app/tasks/deployer_task'
|
23
|
+
|
24
|
+
ENV['DEPLOYMENTS'] ||= '/opt/deployments'
|
25
|
+
|
26
|
+
class Deployer
|
27
|
+
|
28
|
+
attr_accessor :push
|
29
|
+
|
30
|
+
def initialize(push)
|
31
|
+
@push = push
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.deploy(push)
|
35
|
+
push.deploy
|
36
|
+
DeployerTask.async(:deploy, :id=>push.id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.undeploy(push, async = true)
|
40
|
+
push.undeploy
|
41
|
+
if async
|
42
|
+
DeployerTask.async(:undeploy, :id=>push.id)
|
43
|
+
else
|
44
|
+
Deployer.new(push).undeploy
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.undeploy_branch(branch)
|
49
|
+
Deployment.all(:branch=>branch).each do |d|
|
50
|
+
Deployer.undeploy(d.push, false)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def undeploy
|
55
|
+
TorqueBox::RakeUtils.undeploy( "#{repository_name}-knob.yml" )
|
56
|
+
remove_repo if ( File.exist?( root ) )
|
57
|
+
push.undeployed
|
58
|
+
end
|
59
|
+
|
60
|
+
def deploy
|
61
|
+
begin
|
62
|
+
clone_repo
|
63
|
+
freeze_gems
|
64
|
+
write_descriptor
|
65
|
+
push.deployed
|
66
|
+
push.save
|
67
|
+
d = Deployment.create(
|
68
|
+
:created_at=>Time.now,
|
69
|
+
:push=>push,
|
70
|
+
:branch=>push.branch,
|
71
|
+
:path=>deployment_path,
|
72
|
+
:context=>"/#{repository_name}")
|
73
|
+
d.save!
|
74
|
+
rescue Exception => ex
|
75
|
+
puts ex
|
76
|
+
push.failed
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Hack to avoid problems with github responses using git gem over https
|
81
|
+
def git_url
|
82
|
+
push.repo_url.sub('https://github.com/', 'git@github.com:')
|
83
|
+
end
|
84
|
+
|
85
|
+
def deployment_path
|
86
|
+
@deployment_path ||= ENV['DEPLOYMENTS']
|
87
|
+
end
|
88
|
+
|
89
|
+
def repository_name
|
90
|
+
@repo_name ||= push.master? ? push.repo_name : "#{push.repo_name}-#{push.branch}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def root
|
94
|
+
"#{deployment_path}/#{repository_name}"
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def remove_repo
|
100
|
+
puts "Removing #{repository_name}"
|
101
|
+
FileUtils.rm_rf( root )
|
102
|
+
end
|
103
|
+
|
104
|
+
def clone_repo
|
105
|
+
remove_repo if ( File.exist?( root ) )
|
106
|
+
puts "Cloning #{git_url} to #{root}"
|
107
|
+
git = Git.clone(git_url, repository_name, :path=>deployment_path)
|
108
|
+
puts "Resetting repo to #{push['after']}"
|
109
|
+
git.reset_hard(push['after'])
|
110
|
+
end
|
111
|
+
|
112
|
+
def freeze_gems
|
113
|
+
puts "Freezing gems"
|
114
|
+
jruby = File.join( RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'] )
|
115
|
+
if ( File.exist?( path_to('Gemfile') ) )
|
116
|
+
exec_cmd( "cd #{root} && #{jruby} -S bundle package" )
|
117
|
+
exec_cmd( "cd #{root} && #{jruby} -S bundle install --local --path vendor/bundle" )
|
118
|
+
else
|
119
|
+
exec_cmd( "cd #{root} && #{jruby} -S rake rails:freeze:gems" )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def write_descriptor
|
124
|
+
name, descriptor = deployment( repository_name, root, "/#{repository_name}" )
|
125
|
+
TorqueBox::RakeUtils.deploy_yaml( name, descriptor )
|
126
|
+
end
|
127
|
+
|
128
|
+
def path_to(file)
|
129
|
+
"#{root}/#{file}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def exec_cmd(cmd)
|
133
|
+
Open3.popen3( cmd ) do |stdin, stdout, stderr|
|
134
|
+
stdin.close
|
135
|
+
stdout_thr = Thread.new(stdout) {|stdout_io|
|
136
|
+
stdout_io.each_line do |l|
|
137
|
+
STDOUT.puts l
|
138
|
+
STDOUT.flush
|
139
|
+
end
|
140
|
+
stdout_io.close
|
141
|
+
}
|
142
|
+
stderr_thr = Thread.new(stderr) {|stderr_io|
|
143
|
+
stderr_io.each_line do |l|
|
144
|
+
STDERR.puts l
|
145
|
+
STDERR.flush
|
146
|
+
end
|
147
|
+
}
|
148
|
+
stdout_thr.join
|
149
|
+
stderr_thr.join
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
data/app/helpers.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
module StompBox
|
18
|
+
class Application < Sinatra::Base
|
19
|
+
|
20
|
+
helpers do
|
21
|
+
|
22
|
+
def config(key)
|
23
|
+
ENV[key]
|
24
|
+
end
|
25
|
+
|
26
|
+
def home_path
|
27
|
+
request.script_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def push_path
|
31
|
+
port = request.port == 80 ? "" : ":#{request.port}"
|
32
|
+
request.scheme + "://" + request.host + port + to( "push/#{config('API_KEY')}" )
|
33
|
+
end
|
34
|
+
|
35
|
+
def to(location)
|
36
|
+
location.gsub!(/^\//, '')
|
37
|
+
"#{home_path}/#{location}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def repositories
|
41
|
+
@repositories ||= Repository.ordered
|
42
|
+
end
|
43
|
+
|
44
|
+
def classes_for(push)
|
45
|
+
track = push.tracked? ? 'tracked' : 'ignored'
|
46
|
+
[push.status, track, classify(push.repo_name), classify(push.branch)]
|
47
|
+
end
|
48
|
+
|
49
|
+
def selector_for(push)
|
50
|
+
classes_for(push).join('.')
|
51
|
+
end
|
52
|
+
|
53
|
+
def classify(str)
|
54
|
+
str.gsub('.', '-')
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/app/models.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2011 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'json'
|
18
|
+
require 'state_machine'
|
19
|
+
require 'dm-core'
|
20
|
+
require 'dm-migrations'
|
21
|
+
require 'dm-timestamps'
|
22
|
+
|
23
|
+
class Push
|
24
|
+
include DataMapper::Resource
|
25
|
+
|
26
|
+
property :id, Serial
|
27
|
+
property :status, String
|
28
|
+
property :payload, Text, :required => true, :lazy => false
|
29
|
+
property :created_at, DateTime
|
30
|
+
|
31
|
+
has 1, :deployment
|
32
|
+
|
33
|
+
attr_accessor :parsed_payload
|
34
|
+
|
35
|
+
state_machine :status, :initial => :received do
|
36
|
+
|
37
|
+
event :deploy do
|
38
|
+
transition all - [:deploying, :deployed] => :deploying
|
39
|
+
end
|
40
|
+
|
41
|
+
event :deployed do
|
42
|
+
transition :deploying => :deployed
|
43
|
+
end
|
44
|
+
|
45
|
+
event :failed do
|
46
|
+
transition all => :failed
|
47
|
+
end
|
48
|
+
|
49
|
+
event :undeploy do
|
50
|
+
transition :deployed => :undeploying
|
51
|
+
end
|
52
|
+
|
53
|
+
event :undeployed do
|
54
|
+
transition all => :undeployed
|
55
|
+
end
|
56
|
+
|
57
|
+
after_transition all => :undeploying do
|
58
|
+
self.deployment.destroy unless self.deployment.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def tracked?
|
64
|
+
Repository.ordered.any? { |r| r.name == repo_name && r.branch == branch }
|
65
|
+
end
|
66
|
+
|
67
|
+
def [](property)
|
68
|
+
parse_payload[property]
|
69
|
+
end
|
70
|
+
|
71
|
+
def repo_url
|
72
|
+
self['repository']['url']
|
73
|
+
end
|
74
|
+
|
75
|
+
def repo_name
|
76
|
+
self['repository']['name']
|
77
|
+
end
|
78
|
+
|
79
|
+
def branch
|
80
|
+
self['ref'].split('/').last
|
81
|
+
end
|
82
|
+
|
83
|
+
def master?
|
84
|
+
branch == 'master'
|
85
|
+
end
|
86
|
+
|
87
|
+
def short_commit_hash
|
88
|
+
self['after'][0..6]
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.deployed
|
92
|
+
Push.all(:status=>:deployed)
|
93
|
+
end
|
94
|
+
|
95
|
+
protected
|
96
|
+
def parse_payload
|
97
|
+
@parsed_payload ||= JSON.parse(self.payload)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
class Deployment
|
103
|
+
include DataMapper::Resource
|
104
|
+
|
105
|
+
property :id, Serial
|
106
|
+
property :path, String
|
107
|
+
property :context, String
|
108
|
+
property :branch, String
|
109
|
+
property :created_at, DateTime
|
110
|
+
|
111
|
+
belongs_to :push
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
class Repository
|
116
|
+
include DataMapper::Resource
|
117
|
+
|
118
|
+
property :id, Serial
|
119
|
+
property :name, String
|
120
|
+
property :branch, String
|
121
|
+
|
122
|
+
def self.ordered
|
123
|
+
Repository.all(:order => [:name, :branch])
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
class DeploymentFile
|
129
|
+
include DataMapper::Resource
|
130
|
+
|
131
|
+
property :id, Serial
|
132
|
+
property :path, String
|
133
|
+
property :body, Text
|
134
|
+
|
135
|
+
belongs_to :repository
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
database_url = ENV['DATABASE_URL']
|
140
|
+
database_url ||= 'postgres://stompbox:stompbox@localhost/stompbox'
|
141
|
+
|
142
|
+
DataMapper::Logger.new($stdout, :info)
|
143
|
+
DataMapper.setup(:default, database_url)
|
144
|
+
DataMapper::Model.raise_on_save_failure = true
|
145
|
+
DataMapper.finalize
|
146
|
+
|
147
|
+
|
148
|
+
if ENV['AUTO_MIGRATE']
|
149
|
+
DataMapper.auto_upgrade!
|
150
|
+
end
|