deep_thought 0.1.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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +184 -0
- data/Rakefile +50 -0
- data/config.ru +5 -0
- data/db/migrate/20130414012805_create_projects.rb +15 -0
- data/db/migrate/20130426165010_create_states.rb +14 -0
- data/db/migrate/20130501003758_create_users.rb +14 -0
- data/db/migrate/20130508001711_add_api_key_to_users.rb +9 -0
- data/db/migrate/20130509014935_create_deploys.rb +27 -0
- data/db/migrate/20130514062148_create_delayed_jobs.rb +21 -0
- data/db/migrate/20130516042149_change_delayed_job_last_error_to_text.rb +9 -0
- data/db/migrate/20130517010210_add_ci_to_projects.rb +9 -0
- data/db/migrate/20130525001332_add_notification_url_to_users.rb +9 -0
- data/db/migrate/20131127022704_remove_deploy_type_and_ci_from_projects.rb +11 -0
- data/db/schema.rb +72 -0
- data/deep_thought.gemspec +45 -0
- data/lib/deep_thought.rb +62 -0
- data/lib/deep_thought/api.rb +156 -0
- data/lib/deep_thought/app.rb +342 -0
- data/lib/deep_thought/ci_service.rb +39 -0
- data/lib/deep_thought/ci_service/janky.rb +34 -0
- data/lib/deep_thought/deployer.rb +180 -0
- data/lib/deep_thought/deployer/deployer.rb +17 -0
- data/lib/deep_thought/deployer/shell.rb +45 -0
- data/lib/deep_thought/git.rb +76 -0
- data/lib/deep_thought/models/deploy.rb +27 -0
- data/lib/deep_thought/models/project.rb +32 -0
- data/lib/deep_thought/models/state.rb +6 -0
- data/lib/deep_thought/models/user.rb +45 -0
- data/lib/deep_thought/notifier.rb +13 -0
- data/lib/deep_thought/public/assets/javascripts/jquery.min.js +6 -0
- data/lib/deep_thought/public/assets/javascripts/main.js +36 -0
- data/lib/deep_thought/public/assets/stylesheets/main.css +438 -0
- data/lib/deep_thought/public/robots.txt +2 -0
- data/lib/deep_thought/scaler.rb +35 -0
- data/lib/deep_thought/tasks.rb +65 -0
- data/lib/deep_thought/version.rb +3 -0
- data/lib/deep_thought/views/history/index.haml +4 -0
- data/lib/deep_thought/views/history/show.haml +68 -0
- data/lib/deep_thought/views/layouts/layout.haml +32 -0
- data/lib/deep_thought/views/projects/edit.haml +15 -0
- data/lib/deep_thought/views/projects/index.haml +7 -0
- data/lib/deep_thought/views/projects/new.haml +8 -0
- data/lib/deep_thought/views/projects/show.haml +25 -0
- data/lib/deep_thought/views/sessions/login.haml +8 -0
- data/lib/deep_thought/views/users/index.haml +7 -0
- data/lib/deep_thought/views/users/new.haml +12 -0
- data/lib/deep_thought/views/users/show.haml +38 -0
- data/script/bootstrap +3 -0
- data/script/console +7 -0
- data/script/server +7 -0
- data/script/test +3 -0
- data/test/deep_thought_api_test.rb +114 -0
- data/test/deep_thought_app_test.rb +315 -0
- data/test/deep_thought_ci_service_test.rb +44 -0
- data/test/deep_thought_deployer_test.rb +72 -0
- data/test/deep_thought_git_test.rb +62 -0
- data/test/deep_thought_janky_test.rb +42 -0
- data/test/deep_thought_notifier_test.rb +35 -0
- data/test/deep_thought_project_test.rb +34 -0
- data/test/deep_thought_shell_test.rb +38 -0
- data/test/fixtures/project-test/HEAD +1 -0
- data/test/fixtures/project-test/config +8 -0
- data/test/fixtures/project-test/description +1 -0
- data/test/fixtures/project-test/hooks/applypatch-msg.sample +15 -0
- data/test/fixtures/project-test/hooks/commit-msg.sample +24 -0
- data/test/fixtures/project-test/hooks/post-update.sample +8 -0
- data/test/fixtures/project-test/hooks/pre-applypatch.sample +14 -0
- data/test/fixtures/project-test/hooks/pre-commit.sample +49 -0
- data/test/fixtures/project-test/hooks/pre-push.sample +54 -0
- data/test/fixtures/project-test/hooks/pre-rebase.sample +169 -0
- data/test/fixtures/project-test/hooks/prepare-commit-msg.sample +36 -0
- data/test/fixtures/project-test/hooks/update.sample +128 -0
- data/test/fixtures/project-test/info/exclude +6 -0
- data/test/fixtures/project-test/objects/13/8b8baba400e64fc384d468e80f10cf707e38d7 +1 -0
- data/test/fixtures/project-test/objects/6b/8fb16e1675767742afc70ac2ce038da46461f8 +0 -0
- data/test/fixtures/project-test/objects/7f/fc496d150b8a0015e3a16be8bacd47daed1a1c +0 -0
- data/test/fixtures/project-test/objects/8f/8606174a2aa11545d119fe3c4d6840fe0c4825 +0 -0
- data/test/fixtures/project-test/objects/9c/362942288a8ff6dc1addf7c5199bd9837e09de +0 -0
- data/test/fixtures/project-test/objects/b5/f7341de6145d3f8b95877cd2675d798fd172f1 +0 -0
- data/test/fixtures/project-test/objects/d1/f1e8664b0326316fb18796ac4ae1171e239cb6 +1 -0
- data/test/fixtures/project-test/objects/e6/d7ad6d61242936a2cd2bb9ae236adf43e59718 +0 -0
- data/test/fixtures/project-test/objects/fa/4cf5ff52462d17b6378a06fae8771c13b654b0 +1 -0
- data/test/fixtures/project-test/objects/fa/dda6bc20afa5cf93196bfb08a4989ee3b75ed7 +0 -0
- data/test/fixtures/project-test/packed-refs +4 -0
- data/test/fixtures/project-test/refs/heads/.gitkeep +0 -0
- data/test/fixtures/project-test/refs/tags/.gitkeep +0 -0
- data/test/test_helper.rb +42 -0
- metadata +462 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module DeepThought
|
|
2
|
+
module CIService
|
|
3
|
+
class CIServiceNotFoundError < StandardError; end
|
|
4
|
+
class CIBuildNotGreenError < StandardError; end
|
|
5
|
+
class CIProjectAccessError < StandardError; end
|
|
6
|
+
|
|
7
|
+
class << self
|
|
8
|
+
attr_accessor :adapters, :ci_service
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.adapters
|
|
12
|
+
@adapters ||= {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.register_adapter(name, service)
|
|
16
|
+
self.adapters[name] = service
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.setup(settings)
|
|
20
|
+
if settings['CI_SERVICE']
|
|
21
|
+
if @adapters.keys.include?(settings['CI_SERVICE'])
|
|
22
|
+
klass = adapters[settings['CI_SERVICE']]
|
|
23
|
+
@ci_service = klass.new
|
|
24
|
+
@ci_service.setup(settings)
|
|
25
|
+
else
|
|
26
|
+
raise CIServiceNotFoundError, "I don't have a CI service called \"#{settings['CI_SERVICE']}\"."
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.is_branch_green?(app, branch, hash)
|
|
32
|
+
begin
|
|
33
|
+
@ci_service.is_branch_green?(app, branch, hash)
|
|
34
|
+
rescue
|
|
35
|
+
raise CIProjectAccessError, "Something went wrong asking #{ENV['CI_SERVICE']} about commit #{hash} in #{app} on the #{branch} branch."
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'httparty'
|
|
2
|
+
|
|
3
|
+
module DeepThought
|
|
4
|
+
module CIService
|
|
5
|
+
class Janky
|
|
6
|
+
attr_accessor :endpoint, :username, :password
|
|
7
|
+
|
|
8
|
+
def setup(settings)
|
|
9
|
+
@endpoint = settings['CI_SERVICE_ENDPOINT']
|
|
10
|
+
@username = settings['CI_SERVICE_USERNAME']
|
|
11
|
+
@password = settings['CI_SERVICE_PASSWORD']
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def is_branch_green?(app, branch, hash)
|
|
15
|
+
is_green = false
|
|
16
|
+
|
|
17
|
+
response = HTTParty.get("#{@endpoint}/_hubot/#{app}/#{branch}", {:basic_auth => {:username => @username, :password => @password}})
|
|
18
|
+
builds = JSON.parse(response.body)
|
|
19
|
+
|
|
20
|
+
builds.each do |build|
|
|
21
|
+
if build['sha1'].to_s == hash.to_s
|
|
22
|
+
if build['green']
|
|
23
|
+
is_green = true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
break
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
is_green
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'deep_thought/git'
|
|
3
|
+
|
|
4
|
+
module DeepThought
|
|
5
|
+
module Deployer
|
|
6
|
+
class DeployerNotFoundError < StandardError; end
|
|
7
|
+
class DeploymentFailedError < StandardError; end
|
|
8
|
+
class DeploymentInProgressError < StandardError; end
|
|
9
|
+
|
|
10
|
+
class << self
|
|
11
|
+
attr_accessor :adapters
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.adapters
|
|
15
|
+
@adapters ||= {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.register_adapter(name, service)
|
|
19
|
+
self.adapters[name] = service
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.create(project, user, via, options = {})
|
|
23
|
+
branch = options[:branch] || 'master'
|
|
24
|
+
actions = options[:actions] if options[:actions]
|
|
25
|
+
environment = options[:environment] if options[:environment]
|
|
26
|
+
box = options[:box] if options[:box]
|
|
27
|
+
variables = options[:variables] if options[:variables]
|
|
28
|
+
on_behalf_of = options[:on_behalf_of] if options[:on_behalf_of]
|
|
29
|
+
|
|
30
|
+
if is_deploying?
|
|
31
|
+
raise DeploymentInProgressError, "Sorry, but I'm currently in mid-deployment. Ask me again when I'm done."
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
project.setup
|
|
35
|
+
|
|
36
|
+
hash = Git.get_latest_commit_for_branch(project, branch)
|
|
37
|
+
|
|
38
|
+
project_config = YAML.load_file(".projects/#{project.name}/.deepthought.yml")
|
|
39
|
+
|
|
40
|
+
if project_config['ci']
|
|
41
|
+
uses_ci = project_config['ci']['enabled'] || false
|
|
42
|
+
else
|
|
43
|
+
uses_ci = false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if DeepThought::CIService.ci_service
|
|
47
|
+
if uses_ci
|
|
48
|
+
ci_project_name = project_config['ci']['name'] || project.name
|
|
49
|
+
if !DeepThought::CIService.is_branch_green?(ci_project_name, branch, hash)
|
|
50
|
+
raise DeepThought::CIService::CIBuildNotGreenError, "Commit #{hash} on project #{app} (in branch #{branch}) is not green. Fix it before deploying."
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
deploy = DeepThought::Deploy.new
|
|
56
|
+
deploy.project_id = project.id
|
|
57
|
+
deploy.user_id = user.id
|
|
58
|
+
deploy.branch = branch
|
|
59
|
+
deploy.commit = hash.to_s
|
|
60
|
+
deploy.via = via
|
|
61
|
+
deploy.actions = actions.to_yaml if actions
|
|
62
|
+
deploy.environment = environment if environment
|
|
63
|
+
deploy.box = box if environment && box
|
|
64
|
+
deploy.variables = variables.to_yaml if variables
|
|
65
|
+
deploy.on_behalf_of = on_behalf_of if on_behalf_of
|
|
66
|
+
deploy.save!
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.execute(deploy)
|
|
70
|
+
if !is_deploying?
|
|
71
|
+
Git.switch_to_branch(deploy.project, deploy.branch)
|
|
72
|
+
|
|
73
|
+
deploy.project.setup
|
|
74
|
+
|
|
75
|
+
project_config = YAML.load_file(".projects/#{deploy.project.name}/.deepthought.yml") || {}
|
|
76
|
+
deploy_type = project_config['deploy_type'] || 'shell'
|
|
77
|
+
|
|
78
|
+
if @adapters.keys.include?(deploy_type)
|
|
79
|
+
lock_deployer
|
|
80
|
+
|
|
81
|
+
deploy.started_at = DateTime.now
|
|
82
|
+
deploy.in_progress = true
|
|
83
|
+
deploy.save!
|
|
84
|
+
|
|
85
|
+
klass = adapters[deploy_type]
|
|
86
|
+
deployer = klass.new
|
|
87
|
+
deployer.setup(deploy.project, project_config)
|
|
88
|
+
deploy_status = deployer.execute(deploy, project_config)
|
|
89
|
+
|
|
90
|
+
unlock_deployer
|
|
91
|
+
|
|
92
|
+
deploy.finished_at = DateTime.now
|
|
93
|
+
deploy.in_progress = false
|
|
94
|
+
|
|
95
|
+
deploy_summary = deploy.project.name
|
|
96
|
+
|
|
97
|
+
if deploy.actions
|
|
98
|
+
actions = YAML.load(deploy.actions)
|
|
99
|
+
actions.each do |action|
|
|
100
|
+
deploy_summary += "/#{action}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
deploy_summary += " #{deploy.branch}"
|
|
105
|
+
|
|
106
|
+
if deploy.environment
|
|
107
|
+
deploy_summary += " to #{deploy.environment}"
|
|
108
|
+
|
|
109
|
+
if deploy.box
|
|
110
|
+
deploy_summary += "/#{deploy.box}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
if deploy.variables
|
|
115
|
+
variables = YAML.load(deploy.variables)
|
|
116
|
+
variables.each do |k, v|
|
|
117
|
+
deploy_summary += " #{k}=#{v}"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if deploy_status
|
|
122
|
+
deploy.was_successful = true
|
|
123
|
+
deploy.save!
|
|
124
|
+
|
|
125
|
+
DeepThought::Notifier.notify(deploy.user, "SUCCESS: #{deploy_summary}")
|
|
126
|
+
|
|
127
|
+
true
|
|
128
|
+
else
|
|
129
|
+
deploy.was_successful = false
|
|
130
|
+
deploy.save!
|
|
131
|
+
|
|
132
|
+
DeepThought::Notifier.notify(deploy.user, "FAILED: #{deploy_summary}")
|
|
133
|
+
|
|
134
|
+
raise DeploymentFailedError, "The deployment pondered its own short existence before hitting the ground with a sudden wet thud."
|
|
135
|
+
end
|
|
136
|
+
else
|
|
137
|
+
raise DeployerNotFoundError, "I don't have a deployer called \"#{deploy_type}\"."
|
|
138
|
+
end
|
|
139
|
+
else
|
|
140
|
+
raise DeploymentInProgressError, "Sorry, but I'm currently in mid-deployment. Ask me again when I'm done."
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.is_deploying?
|
|
145
|
+
deployer_state = get_or_create_deployer_state
|
|
146
|
+
|
|
147
|
+
if deployer_state.state == 'true'
|
|
148
|
+
true
|
|
149
|
+
else
|
|
150
|
+
false
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def self.lock_deployer
|
|
155
|
+
deployer_state = get_or_create_deployer_state
|
|
156
|
+
|
|
157
|
+
deployer_state.state = 'true'
|
|
158
|
+
deployer_state.save
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def self.unlock_deployer
|
|
162
|
+
deployer_state = get_or_create_deployer_state
|
|
163
|
+
|
|
164
|
+
deployer_state.state = 'false'
|
|
165
|
+
deployer_state.save
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
private
|
|
169
|
+
|
|
170
|
+
def self.get_or_create_deployer_state
|
|
171
|
+
deployer_state = DeepThought::State.find_by_name('deployer')
|
|
172
|
+
|
|
173
|
+
if !deployer_state
|
|
174
|
+
deployer_state = DeepThought::State.create(:name => 'deployer', :state => 'false')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
deployer_state
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module DeepThought
|
|
2
|
+
module Deployer
|
|
3
|
+
class Deployer
|
|
4
|
+
def initialize
|
|
5
|
+
if self.class.name == 'DeepThought::Deployer::Deployer'
|
|
6
|
+
raise "#{self.class.name} is abstract, you cannot instantiate it directly."
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def setup(project, config)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute(deploy, config)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'deep_thought/deployer/deployer'
|
|
2
|
+
|
|
3
|
+
module DeepThought
|
|
4
|
+
module Deployer
|
|
5
|
+
class Shell < DeepThought::Deployer::Deployer
|
|
6
|
+
def execute(deploy, config)
|
|
7
|
+
environment = deploy.environment || "development"
|
|
8
|
+
|
|
9
|
+
root = config['root'] || "script/deploy"
|
|
10
|
+
|
|
11
|
+
command = "#{root} #{environment} deploy"
|
|
12
|
+
|
|
13
|
+
if deploy.actions
|
|
14
|
+
actions = YAML.load(deploy.actions)
|
|
15
|
+
actions.each do |action|
|
|
16
|
+
command += ":#{action}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
command += " branch=#{deploy.branch}"
|
|
21
|
+
command += " box=#{deploy.box}" if deploy.box
|
|
22
|
+
|
|
23
|
+
if deploy.variables
|
|
24
|
+
variables = YAML.load(deploy.variables)
|
|
25
|
+
variables.each do |k, v|
|
|
26
|
+
command += " #{k}=#{v}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
commands = []
|
|
31
|
+
|
|
32
|
+
commands << "cd ./.projects/#{deploy.project.name}"
|
|
33
|
+
commands << "#{command} 2>&1"
|
|
34
|
+
|
|
35
|
+
executable = commands.join(" && ")
|
|
36
|
+
|
|
37
|
+
log = `#{executable}`
|
|
38
|
+
|
|
39
|
+
deploy.log = log
|
|
40
|
+
|
|
41
|
+
$?.success?
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
require 'rugged'
|
|
2
|
+
|
|
3
|
+
module DeepThought
|
|
4
|
+
module Git
|
|
5
|
+
class GitRepositoryNotFoundError < StandardError; end
|
|
6
|
+
class GitBranchNotFoundError < StandardError; end
|
|
7
|
+
|
|
8
|
+
def self.setup(project)
|
|
9
|
+
if !File.directory?(".projects/#{project.name}/.git")
|
|
10
|
+
exit_status = system "git clone #{project.repo_url} .projects/#{project.name} > /dev/null 2>&1"
|
|
11
|
+
|
|
12
|
+
if exit_status
|
|
13
|
+
if !File.directory?(".projects/#{project.name}/.git")
|
|
14
|
+
false
|
|
15
|
+
else
|
|
16
|
+
if Dir.entries(".projects/#{project.name}") == [".", "..", ".git"]
|
|
17
|
+
false
|
|
18
|
+
else
|
|
19
|
+
true
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
else
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.get_list_of_branches(project)
|
|
31
|
+
self.clone_if_not_exists(project)
|
|
32
|
+
|
|
33
|
+
system "cd ./.projects/#{project.name} && git fetch -p > /dev/null 2>&1"
|
|
34
|
+
|
|
35
|
+
repo = Rugged::Repository.new(".projects/#{project.name}")
|
|
36
|
+
|
|
37
|
+
branches = Rugged::Branch.each_name(repo, :remote).sort
|
|
38
|
+
branches.map! { |x| x.sub!('origin/', '') }
|
|
39
|
+
branches.delete('HEAD')
|
|
40
|
+
|
|
41
|
+
branches
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.get_latest_commit_for_branch(project, branch)
|
|
45
|
+
self.clone_if_not_exists(project)
|
|
46
|
+
|
|
47
|
+
system "cd ./.projects/#{project.name} && git fetch -p > /dev/null 2>&1"
|
|
48
|
+
|
|
49
|
+
repo = Rugged::Repository.new(".projects/#{project.name}")
|
|
50
|
+
|
|
51
|
+
switch_to_branch(project, branch)
|
|
52
|
+
|
|
53
|
+
repo.head.target
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.switch_to_branch(project, branch)
|
|
57
|
+
self.clone_if_not_exists(project)
|
|
58
|
+
|
|
59
|
+
exit_status = system "cd ./.projects/#{project.name} && git fetch -p > /dev/null 2>&1 && git reset --hard origin/#{branch} > /dev/null 2>&1"
|
|
60
|
+
|
|
61
|
+
if exit_status
|
|
62
|
+
true
|
|
63
|
+
else
|
|
64
|
+
raise GitBranchNotFoundError, "#{project.name} doesn't appear to have a branch called #{branch}. Have you pushed it?"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def self.clone_if_not_exists(project)
|
|
71
|
+
if !self.setup(project)
|
|
72
|
+
raise DeepThought::Git::GitRepositoryNotFoundError, "I can't seem to access that repo. Are you sure the URL is correct and that I have access to it?"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module DeepThought
|
|
2
|
+
class Deploy < ActiveRecord::Base
|
|
3
|
+
belongs_to :project
|
|
4
|
+
belongs_to :user
|
|
5
|
+
|
|
6
|
+
after_create :queue
|
|
7
|
+
|
|
8
|
+
validates_presence_of :branch
|
|
9
|
+
validates_presence_of :commit
|
|
10
|
+
validates_presence_of :project
|
|
11
|
+
validates_presence_of :user
|
|
12
|
+
|
|
13
|
+
def queue
|
|
14
|
+
Delayed::Job.enqueue self
|
|
15
|
+
|
|
16
|
+
DeepThought::Scaler.scale
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def perform
|
|
20
|
+
DeepThought::Deployer.execute(self)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def max_attempts
|
|
24
|
+
return 1
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
module DeepThought
|
|
4
|
+
class ProjectConfigNotFoundError < StandardError; end
|
|
5
|
+
|
|
6
|
+
class Project < ActiveRecord::Base
|
|
7
|
+
has_many :deploys
|
|
8
|
+
|
|
9
|
+
before_destroy :delete_repo
|
|
10
|
+
|
|
11
|
+
validates :name, presence: true, uniqueness: true
|
|
12
|
+
validates :repo_url, presence: true
|
|
13
|
+
|
|
14
|
+
def setup
|
|
15
|
+
if DeepThought::Git.setup(self)
|
|
16
|
+
if !File.exists?(".projects/#{self.name}/.deepthought.yml")
|
|
17
|
+
delete_repo
|
|
18
|
+
|
|
19
|
+
raise DeepThought::ProjectConfigNotFoundError, "#{self.name} does not appear to have a .deepthought.yml config file. Add one and try again."
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
raise DeepThought::Git::GitRepositoryNotFoundError, "I can't seem to access that repo. Are you sure the URL is correct and that I have access to it?"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def delete_repo
|
|
27
|
+
if File.directory?(".projects/#{self.name}")
|
|
28
|
+
FileUtils.rm_rf(".projects/#{self.name}")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|