kapost_deploy 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +56 -19
- data/lib/kapost_deploy.rb +0 -1
- data/lib/kapost_deploy/heroku/app_promoter.rb +53 -0
- data/lib/kapost_deploy/heroku/app_releases.rb +36 -0
- data/lib/kapost_deploy/heroku/shell.rb +42 -0
- data/lib/kapost_deploy/identity.rb +1 -2
- data/lib/kapost_deploy/plugins/db_migrate.rb +25 -0
- data/lib/kapost_deploy/plugins/slack_after_promote.rb +19 -6
- data/lib/kapost_deploy/plugins/slack_github_diff.rb +29 -28
- data/lib/kapost_deploy/slack/notifier.rb +30 -0
- data/lib/kapost_deploy/task.rb +56 -77
- data/lib/tasks/console.rake +1 -0
- data/lib/tasks/rspec.rake +1 -0
- data/lib/tasks/rubocop.rake +1 -0
- metadata +14 -10
- data/lib/kapost_deploy/plugins/slack/notifier.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 465752e220872c86cf728e906b64fa82ff5ba691
|
4
|
+
data.tar.gz: 5592571df0b04754ce3ed7ba452d7defba8d6b3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34aa223ee90e83d688b15bacc6464ec20f9608ebd82b8a52e202ce4b491060c4b2fae5c8fb1090cd971f51d298e8f628158bdec4f398798cb7bfda8d1d973e58
|
7
|
+
data.tar.gz: 86b999a1120428691ae4bb0c6d660c64360e01cf21140d114275a4368c0c47d6b5b04053bff21c8f70489851a69200e5cab93665cf054bd22d18941b331a09f9
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
# Features
|
24
24
|
|
25
|
-
`KapostDeploy::Task.
|
25
|
+
`KapostDeploy::Task.define` creates the following rake tasks to aid in the pipeline promotion deployment of Heroku applications
|
26
26
|
|
27
27
|
[promote]
|
28
28
|
Promotes a source environment to production
|
@@ -35,11 +35,13 @@
|
|
35
35
|
|
36
36
|
Simple Example:
|
37
37
|
|
38
|
-
require
|
38
|
+
require "kapost_deploy/task"
|
39
39
|
|
40
|
-
KapostDeploy::Task.
|
41
|
-
config.app =
|
42
|
-
config.to =
|
40
|
+
KapostDeploy::Task.define do |config|
|
41
|
+
config.app = "cabbage-staging"
|
42
|
+
config.to = "cabbage-production"
|
43
|
+
config.pipeline = "cabbage"
|
44
|
+
config.heroku_api_token = "123"
|
43
45
|
|
44
46
|
config.after do
|
45
47
|
puts "It's Miller time"
|
@@ -49,26 +51,56 @@ Simple Example:
|
|
49
51
|
A slightly more complex example which will create 6 rake tasks: stage:before_stage, stage,
|
50
52
|
stage:after_stage, promote:before_promote, promote, promote:after_promote
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
require "kapost_deploy/task"
|
55
|
+
require "kapost_deploy/plugins/slack_after_promote"
|
56
|
+
require "kapost_deploy/plugins/slack_github_diff"
|
57
|
+
require "kapost_deploy/plugins/db_migrate"
|
58
|
+
|
59
|
+
CONFIG = {
|
60
|
+
slack_config: {
|
61
|
+
webhook_url: "https://hooks.slack.com/services/34326/FDSJFH127/68357sdhfjhHSJGFNMDngsd",
|
62
|
+
channel: "#danger",
|
63
|
+
icon_url: "http://yourcompany.s3.amazonaws.com/logo.png"
|
64
|
+
},
|
65
|
+
git_config: {
|
66
|
+
github_repo: "yourcompany/widget"
|
67
|
+
}
|
68
|
+
}.freeze
|
69
|
+
|
70
|
+
KapostDeploy::Task.define(:stage) do |config|
|
71
|
+
config.app = "cabbage-staging"
|
72
|
+
config.to = "cabbage-sandbox"
|
73
|
+
config.pipeline = "cabbage"
|
74
|
+
config.heroku_api_token = "123"
|
75
|
+
|
76
|
+
config.options = CONFIG
|
55
77
|
|
56
78
|
config.after do
|
57
79
|
sleep 60*2 wait for dynos to restart
|
58
80
|
slack.notify "The eagle has landed. [Go validate](https://testbed.sandbox.com/dashboard)!"
|
59
81
|
Launchy.open("https://testbed.sandbox.com/dashboard")
|
60
82
|
end
|
83
|
+
|
84
|
+
config.add_plugin(KapostDeploy::Plugins::DbMigrate)
|
61
85
|
end
|
62
86
|
|
63
|
-
KapostDeploy::Task.
|
64
|
-
config.app =
|
65
|
-
config.to =
|
87
|
+
KapostDeploy::Task.define do |config|
|
88
|
+
config.app = "cabbage-sandboxc"
|
89
|
+
config.to = "cabbage-production"
|
90
|
+
config.pipeline = "cabbage"
|
91
|
+
config.heroku_api_token = "123"
|
92
|
+
|
93
|
+
config.options = CONFIG
|
66
94
|
|
67
95
|
config.before do
|
68
|
-
puts
|
96
|
+
puts "Are you sure you did x, y, and z? yes/no: "
|
69
97
|
confirm = gets.strip
|
70
|
-
exit(1) unless confirm.downcase ==
|
98
|
+
exit(1) unless confirm.downcase == "yes"
|
71
99
|
end
|
100
|
+
|
101
|
+
config.add_plugin(KapostDeploy::Plugins::SlackGithubDiff)
|
102
|
+
config.add_plugin(KapostDeploy::Plugins::DbMigrate)
|
103
|
+
config.add_plugin(KapostDeploy::Plugins::SlackAfterPromote)
|
72
104
|
end
|
73
105
|
|
74
106
|
# Requirements
|
@@ -78,14 +110,19 @@ stage:after_stage, promote:before_promote, promote, promote:after_promote
|
|
78
110
|
|
79
111
|
# Configuration Options
|
80
112
|
|
113
|
+
* `pipeline`: The application pipeline to promote
|
114
|
+
* `heroku_api_token`: Your platform api token. You can retrieve this using `heroku auth:token`
|
81
115
|
* `app`: The application to be promoted
|
82
116
|
* `to`: The downstream application(s) to receive the promotion. For multiple environments, use an array.
|
83
|
-
* `
|
84
|
-
* `
|
85
|
-
|
86
|
-
* `
|
87
|
-
|
88
|
-
|
117
|
+
* `options`: An options hash containing plugin options:
|
118
|
+
* `git_config`: If using github plugins, an options hash containing the following keys:
|
119
|
+
* `github_repo`: The owner/repo string, such as `kapost/kapost_deploy`
|
120
|
+
* `slack_config`: If using slack plugins, an options hash containing the following keys:
|
121
|
+
* `webhook_url`: The webhook URL you added to your slack integrations
|
122
|
+
* `username`: The apparent username of the notifier *defaults to "webhooks bot"*
|
123
|
+
* `channel`: The channel name to post the notification to *defaults to "#general"*
|
124
|
+
* `icon_url`: A URL for the icon image *optional*
|
125
|
+
* `icon_emoji`: Emoji name to use instead of an icon *optional*
|
89
126
|
|
90
127
|
# Setup
|
91
128
|
|
data/lib/kapost_deploy.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "platform-api"
|
3
|
+
|
4
|
+
module KapostDeploy
|
5
|
+
module Heroku
|
6
|
+
# Promotes a heroku app via Heroku Plaform API
|
7
|
+
class AppPromoter
|
8
|
+
def initialize(pipeline, token:)
|
9
|
+
self.pipeline = pipeline
|
10
|
+
self.token = token
|
11
|
+
end
|
12
|
+
|
13
|
+
def promote(from:, to:)
|
14
|
+
pipeline_id = discover_pipeline(pipeline)["id"]
|
15
|
+
from_id = discover_app(from)["id"]
|
16
|
+
to_id = discover_app(to)["id"]
|
17
|
+
|
18
|
+
promotion_data = {
|
19
|
+
pipeline: { id: pipeline_id },
|
20
|
+
source: { app: { id: from_id } },
|
21
|
+
targets: [{ app: { id: to_id } }]
|
22
|
+
}
|
23
|
+
|
24
|
+
wait_for_promotion(heroku.pipeline_promotion.create(promotion_data))
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_accessor :pipeline
|
30
|
+
attr_accessor :token
|
31
|
+
|
32
|
+
def wait_for_promotion(promotion)
|
33
|
+
while promotion["status"] == "pending"
|
34
|
+
print "."
|
35
|
+
sleep 1
|
36
|
+
promotion = heroku.pipeline_promotion.info(promotion["id"])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def discover_pipeline(pipeline)
|
41
|
+
heroku.pipeline.info(pipeline)
|
42
|
+
end
|
43
|
+
|
44
|
+
def discover_app(app_name)
|
45
|
+
heroku.app.info(app_name)
|
46
|
+
end
|
47
|
+
|
48
|
+
def heroku
|
49
|
+
@heroku ||= PlatformAPI.connect(token)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "platform-api"
|
3
|
+
|
4
|
+
module KapostDeploy
|
5
|
+
module Heroku
|
6
|
+
# Promotes a heroku app via Heroku Plaform API
|
7
|
+
class AppReleases
|
8
|
+
def initialize(app, token:)
|
9
|
+
self.app = app
|
10
|
+
self.token = token
|
11
|
+
end
|
12
|
+
|
13
|
+
def latest_deploy_version
|
14
|
+
# This appears to be conventional for pipelines and standard heroku deploys and not a
|
15
|
+
# good way to get the deployed git version.
|
16
|
+
list.each do |item|
|
17
|
+
return Regexp.last_match[:sha1] if item["description"] =~ /^Deploy (?<sha1>[a-f0-9]+)$/
|
18
|
+
end
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def list
|
23
|
+
heroku.release.list(app)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_accessor :app
|
29
|
+
attr_accessor :token
|
30
|
+
|
31
|
+
def heroku
|
32
|
+
@heroku ||= PlatformAPI.connect(token, default_headers: { "Range" => "version ..; order=desc" })
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "bundler"
|
3
|
+
require "English"
|
4
|
+
|
5
|
+
module KapostDeploy
|
6
|
+
module Heroku
|
7
|
+
# Wraps the heroku shell environment
|
8
|
+
# Derived from https://github.com/fastestforward/heroku_san
|
9
|
+
class Shell
|
10
|
+
def initialize(app)
|
11
|
+
self.app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(command)
|
15
|
+
sh("run " + command)
|
16
|
+
end
|
17
|
+
|
18
|
+
def sh(command)
|
19
|
+
preflight_check_for_cli
|
20
|
+
|
21
|
+
cmd = command.split(" ")
|
22
|
+
cmd += ["--app", app]
|
23
|
+
cmd << "--exit-code" if command =~ /^run/
|
24
|
+
|
25
|
+
show_command = cmd.join(" ")
|
26
|
+
ok = ::Bundler.with_clean_env { system "heroku", *cmd }
|
27
|
+
|
28
|
+
ok or fail "Command failed with status (#{$CHILD_STATUS.exitstatus}): [heroku #{show_command}]"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_accessor :app
|
34
|
+
|
35
|
+
def preflight_check_for_cli
|
36
|
+
if Bundler.with_clean_env { system("heroku version").nil? }
|
37
|
+
fail "The Heroku Toolbelt is required for this action. http://toolbelt.heroku.com"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "kapost_deploy/heroku/shell"
|
3
|
+
|
4
|
+
module KapostDeploy
|
5
|
+
module Plugins
|
6
|
+
# After-promotion task to run rake db:migrate
|
7
|
+
class DbMigrate
|
8
|
+
def initialize(config,
|
9
|
+
shell: KapostDeploy::Heroku::Shell.new(config.to))
|
10
|
+
self.shell = shell
|
11
|
+
end
|
12
|
+
|
13
|
+
def before
|
14
|
+
end
|
15
|
+
|
16
|
+
def after
|
17
|
+
shell.run("rake db:migrate")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_accessor :shell
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "kapost_deploy/slack/notifier"
|
2
3
|
|
3
4
|
module KapostDeploy
|
4
5
|
module Plugins
|
5
6
|
# After-promotion plugin to notify via slack after a promotion is complete with an
|
6
7
|
# optional message.
|
7
8
|
class SlackAfterPromote
|
8
|
-
def initialize(config,
|
9
|
+
def initialize(config,
|
10
|
+
notifier: KapostDeploy::Slack::Notifier.new(config.options.fetch(:slack_config, nil)))
|
9
11
|
self.config = config
|
10
12
|
self.notifier = notifier
|
11
13
|
end
|
@@ -16,18 +18,29 @@ module KapostDeploy
|
|
16
18
|
def after
|
17
19
|
return unless notifier.configured?
|
18
20
|
|
19
|
-
|
20
|
-
addl = "\n#{addl}" unless addl.empty?
|
21
|
-
|
22
|
-
message = "#{identity} promoted *#{config.app}* to *#{config.to.join(",")}*#{addl}"
|
21
|
+
message = "#{identity} promoted *#{config.app}* to *#{config.to}*#{additional_message}"
|
23
22
|
notifier.notify(message)
|
24
23
|
end
|
25
24
|
|
26
25
|
private
|
27
26
|
|
27
|
+
def additional_message
|
28
|
+
slack_config = config.options.fetch(:slack_config)
|
29
|
+
addl = ""
|
30
|
+
addl = slack_config.fetch(:additional_message, "") unless slack_config.nil?
|
31
|
+
addl = "\n#{addl}" unless addl.empty?
|
32
|
+
addl
|
33
|
+
end
|
34
|
+
|
35
|
+
def identity
|
36
|
+
@identity ||= `whoami`.chomp
|
37
|
+
end
|
38
|
+
|
28
39
|
attr_accessor :notifier
|
29
40
|
|
30
41
|
attr_accessor :config
|
42
|
+
|
43
|
+
attr_accessor :slack_config
|
31
44
|
end
|
32
45
|
end
|
33
46
|
end
|
@@ -1,24 +1,31 @@
|
|
1
|
-
|
2
|
-
require "
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "kapost_deploy/slack/notifier"
|
3
|
+
require "kapost_deploy/heroku/app_releases"
|
3
4
|
|
4
5
|
module KapostDeploy
|
5
6
|
module Plugins
|
6
7
|
# Before-promotion plugin to notify slack with a github comparison warning
|
7
8
|
class SlackGithubDiff
|
8
|
-
def initialize(config,
|
9
|
-
|
9
|
+
def initialize(config,
|
10
|
+
notifier: KapostDeploy::Slack::Notifier.new(config.options.fetch(:slack_config, nil)),
|
11
|
+
behind_releases: KapostDeploy::Heroku::AppReleases.new(config.to, token: config.heroku_api_token),
|
12
|
+
ahead_releases: KapostDeploy::Heroku::AppReleases.new(config.app, token: config.heroku_api_token))
|
13
|
+
|
10
14
|
self.ahead_app = config.app
|
11
|
-
self.
|
15
|
+
self.behind_app = config.to
|
16
|
+
self.git_config = config.options.fetch(:git_config, nil)
|
12
17
|
self.notifier = notifier
|
18
|
+
self.behind_releases = behind_releases
|
19
|
+
self.ahead_releases = ahead_releases
|
13
20
|
end
|
14
21
|
|
15
22
|
def before
|
16
23
|
return unless configured?
|
17
24
|
|
18
|
-
|
19
|
-
|
25
|
+
msg = "#{identity} is promoting <#{github_compare_url}|#{ahead_sha1}>"\
|
26
|
+
" from *#{ahead_app}* to *#{behind_app}*"
|
20
27
|
|
21
|
-
notifier.notify(
|
28
|
+
notifier.notify(msg)
|
22
29
|
end
|
23
30
|
|
24
31
|
def after
|
@@ -26,37 +33,31 @@ module KapostDeploy
|
|
26
33
|
|
27
34
|
private
|
28
35
|
|
29
|
-
def behind_sha1
|
30
|
-
@behind_sha1 ||= heroku_head_sha1(behind_app)
|
31
|
-
end
|
32
|
-
|
33
|
-
def ahead_sha1
|
34
|
-
@ahead_sha1 ||= heroku_head_sha1(ahead_app)
|
35
|
-
end
|
36
|
-
|
37
36
|
attr_accessor :notifier
|
38
|
-
attr_accessor :
|
39
|
-
attr_accessor :
|
37
|
+
attr_accessor :git_config
|
38
|
+
attr_accessor :behind_releases
|
39
|
+
attr_accessor :ahead_releases
|
40
40
|
attr_accessor :ahead_app
|
41
|
+
attr_accessor :behind_app
|
41
42
|
|
42
|
-
def
|
43
|
-
|
43
|
+
def behind_sha1
|
44
|
+
@behind_sha1 ||= behind_releases.latest_deploy_version
|
44
45
|
end
|
45
46
|
|
46
|
-
def
|
47
|
-
|
47
|
+
def ahead_sha1
|
48
|
+
@ahead_sha1 ||= ahead_releases.latest_deploy_version
|
48
49
|
end
|
49
50
|
|
50
|
-
def
|
51
|
-
|
51
|
+
def identity
|
52
|
+
@identity ||= `whoami`.chomp
|
52
53
|
end
|
53
54
|
|
54
|
-
def
|
55
|
-
|
55
|
+
def configured?
|
56
|
+
!git_config.nil? && notifier.configured?
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
|
59
|
+
def github_compare_url
|
60
|
+
"https://github.com/#{git_config[:github_repo]}/compare/#{behind_sha1}...#{ahead_sha1}"
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "slack-notify"
|
3
|
+
|
4
|
+
module KapostDeploy
|
5
|
+
module Slack
|
6
|
+
# Wrapper for slack-notify gem
|
7
|
+
class Notifier
|
8
|
+
def initialize(slack_config)
|
9
|
+
self.slack_config = slack_config
|
10
|
+
end
|
11
|
+
|
12
|
+
def notify(message)
|
13
|
+
return unless configured?
|
14
|
+
slack.notify(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
def configured?
|
18
|
+
!slack_config.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def slack
|
24
|
+
@slack ||= SlackNotify::Client.new(slack_config)
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_accessor :slack_config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/kapost_deploy/task.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "rake"
|
2
3
|
require "rake/tasklib"
|
3
|
-
require "
|
4
|
+
require "kapost_deploy/heroku/app_promoter"
|
4
5
|
|
5
6
|
module KapostDeploy
|
6
7
|
##
|
@@ -8,7 +9,9 @@ module KapostDeploy
|
|
8
9
|
#
|
9
10
|
# require 'kapost_deploy/task'
|
10
11
|
#
|
11
|
-
# KapostDeploy::Task.
|
12
|
+
# KapostDeploy::Task.define do |config|
|
13
|
+
# config.pipeline = 'cabbage'
|
14
|
+
# config.heroku_api_token = ENV.fetch('HEROKU_API_TOKEN')
|
12
15
|
# config.app = 'cabbage-democ'
|
13
16
|
# config.to = 'cabbage-prodc'
|
14
17
|
#
|
@@ -17,48 +20,27 @@ module KapostDeploy
|
|
17
20
|
# end
|
18
21
|
# end
|
19
22
|
#
|
20
|
-
# A slightly more complex example which will create 6 rake tasks: before_stage, stage,
|
21
|
-
# after_stage, before_promote, promote, after_promote
|
22
|
-
#
|
23
|
-
# KapostDeploy::Task.new(:stage) do |config|
|
24
|
-
# config.app = 'cabbage-stagingc'
|
25
|
-
# config.to = %w[cabbage-sandboxc cabbage-democ]
|
26
|
-
#
|
27
|
-
# config.after do
|
28
|
-
# sleep 60*2 # wait for dynos to restart
|
29
|
-
# notifier.ping "The eagle has landed. [Go validate](https://testbed.sandbox.com/dashboard)!"
|
30
|
-
# Launchy.open("https://testbed.sandbox.com/dashboard")
|
31
|
-
# end
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# KapostDeploy::Task.new(:promote) do |config|
|
35
|
-
# config.app = 'cabbage-sandbox1c'
|
36
|
-
# config.to = 'cabbage-prodc'
|
37
|
-
#
|
38
|
-
# config.before do
|
39
|
-
# puts 'Are you sure you did x, y, and z? yes/no: '
|
40
|
-
# confirm = gets.strip
|
41
|
-
# exit(1) unless confirm.downcase == 'yes'
|
42
|
-
# end
|
43
|
-
# end
|
44
23
|
class Task < Rake::TaskLib
|
45
24
|
attr_accessor :app
|
46
25
|
|
47
|
-
|
26
|
+
attr_accessor :to
|
27
|
+
|
28
|
+
attr_accessor :pipeline
|
29
|
+
|
30
|
+
attr_accessor :heroku_api_token
|
48
31
|
|
49
32
|
attr_accessor :name
|
50
33
|
|
51
|
-
attr_accessor :
|
34
|
+
attr_accessor :options
|
52
35
|
|
53
|
-
def
|
54
|
-
|
55
|
-
@name = name
|
56
|
-
@shell = shell
|
36
|
+
def self.define(name = :promote) # :yield: self
|
37
|
+
instance = new(name)
|
57
38
|
|
58
|
-
yield
|
39
|
+
yield instance if block_given?
|
59
40
|
|
60
|
-
validate
|
61
|
-
define
|
41
|
+
instance.validate
|
42
|
+
instance.define
|
43
|
+
instance
|
62
44
|
end
|
63
45
|
|
64
46
|
def before(&block)
|
@@ -69,81 +51,78 @@ module KapostDeploy
|
|
69
51
|
@after = block
|
70
52
|
end
|
71
53
|
|
72
|
-
def
|
73
|
-
|
54
|
+
def add_plugin(plugin)
|
55
|
+
plugins << plugin
|
74
56
|
end
|
75
57
|
|
76
58
|
def defaults
|
77
59
|
@name = :promote
|
60
|
+
@pipeline = nil
|
61
|
+
@heroku_api_token = nil
|
78
62
|
@app = nil
|
79
|
-
@
|
80
|
-
@to = []
|
63
|
+
@to = nil
|
81
64
|
@before = -> {}
|
82
65
|
@after = -> {}
|
66
|
+
@plugins = []
|
67
|
+
@options = {}
|
83
68
|
end
|
84
69
|
|
85
70
|
def validate
|
71
|
+
fail "No 'heroku_api_token' configured."\
|
72
|
+
"Set config.heroku_api_token to your API secret token" if heroku_api_token.nil?
|
73
|
+
fail "No 'pipeline' configured. Set config.pipeline to the name of your pipeline" if pipeline.nil?
|
86
74
|
fail "No 'app' configured. Set config.app to the application to be promoted" if app.nil?
|
87
|
-
fail "No 'to' configured. Set config.to to the downstream application
|
75
|
+
fail "No 'to' configured. Set config.to to the downstream application to be promoted to" if to.nil?
|
88
76
|
end
|
89
77
|
|
90
78
|
def define
|
91
79
|
define_hooks
|
92
80
|
|
93
|
-
desc "Promote #{app} to #{to
|
81
|
+
desc "Promote #{app} to #{to}"
|
94
82
|
task name.to_s do
|
95
|
-
|
96
|
-
@before.call
|
97
|
-
promote
|
98
|
-
notify_slack
|
99
|
-
@after.call
|
83
|
+
promote_with_hooks
|
100
84
|
end
|
101
85
|
end
|
102
86
|
|
103
87
|
private
|
104
88
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def pipelines_installed?
|
110
|
-
`heroku plugins` =~ /^heroku-pipelines@/
|
89
|
+
def initialize(name)
|
90
|
+
defaults
|
91
|
+
self.name = name
|
111
92
|
end
|
112
93
|
|
113
|
-
|
114
|
-
namespace :"#{name}" do
|
115
|
-
desc "Perform after-#{name} tasks"
|
116
|
-
task :"after_#{name}" do
|
117
|
-
@after.call
|
118
|
-
end
|
94
|
+
attr_accessor :plugins
|
119
95
|
|
120
|
-
|
121
|
-
|
122
|
-
@before.call
|
123
|
-
end
|
124
|
-
end
|
96
|
+
def promoter
|
97
|
+
@promoter ||= KapostDeploy::Heroku::AppPromoter.new(pipeline, token: heroku_api_token)
|
125
98
|
end
|
126
99
|
|
127
|
-
def
|
128
|
-
|
100
|
+
def promote_with_hooks
|
101
|
+
Rake.application[:"#{name}:before_#{name}"].execute
|
102
|
+
promoter.promote(from: app, to: to)
|
103
|
+
Rake.application[:"#{name}:after_#{name}"].execute
|
129
104
|
end
|
130
105
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
addl = slack_config.fetch(:additional_message, "")
|
135
|
-
addl = "\n#{addl}" unless addl.empty?
|
136
|
-
|
137
|
-
message = "#{identity} promoted *#{app}* to *#{to.join(",")}*#{addl}"
|
138
|
-
slack.notify(message)
|
106
|
+
def shell(command)
|
107
|
+
@shell.call(command)
|
139
108
|
end
|
140
109
|
|
141
|
-
def
|
142
|
-
|
110
|
+
def define_hooks
|
111
|
+
namespace :"#{name}" do
|
112
|
+
define_hook(:before)
|
113
|
+
define_hook(:after)
|
114
|
+
end
|
143
115
|
end
|
144
116
|
|
145
|
-
def
|
146
|
-
|
117
|
+
def define_hook(kind)
|
118
|
+
desc "Perform #{kind}-#{name} tasks"
|
119
|
+
task :"#{kind}_#{name}" do
|
120
|
+
instance_variable_get(:"@#{kind}").call
|
121
|
+
plugins.each do |p|
|
122
|
+
plugin = p.new(self)
|
123
|
+
plugin.send(kind) if plugin.respond_to?(kind)
|
124
|
+
end
|
125
|
+
end
|
147
126
|
end
|
148
127
|
end
|
149
128
|
end
|
data/lib/tasks/console.rake
CHANGED
data/lib/tasks/rspec.rake
CHANGED
data/lib/tasks/rubocop.rake
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kapost_deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brandon Croft
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -25,31 +25,31 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '10.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: platform-api
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.6.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.6.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: slack-notify
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 0.4.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.4.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
@@ -272,10 +272,14 @@ extra_rdoc_files:
|
|
272
272
|
files:
|
273
273
|
- README.md
|
274
274
|
- lib/kapost_deploy.rb
|
275
|
+
- lib/kapost_deploy/heroku/app_promoter.rb
|
276
|
+
- lib/kapost_deploy/heroku/app_releases.rb
|
277
|
+
- lib/kapost_deploy/heroku/shell.rb
|
275
278
|
- lib/kapost_deploy/identity.rb
|
276
|
-
- lib/kapost_deploy/plugins/
|
279
|
+
- lib/kapost_deploy/plugins/db_migrate.rb
|
277
280
|
- lib/kapost_deploy/plugins/slack_after_promote.rb
|
278
281
|
- lib/kapost_deploy/plugins/slack_github_diff.rb
|
282
|
+
- lib/kapost_deploy/slack/notifier.rb
|
279
283
|
- lib/kapost_deploy/task.rb
|
280
284
|
- lib/tasks/console.rake
|
281
285
|
- lib/tasks/rspec.rake
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require "slack-notify"
|
2
|
-
|
3
|
-
module KapostDeploy
|
4
|
-
module Plugins
|
5
|
-
module Slack
|
6
|
-
# Wrapper for slack-notify gem
|
7
|
-
class Notifier
|
8
|
-
def initialize(slack_config)
|
9
|
-
self.slack_config = slack_config
|
10
|
-
end
|
11
|
-
|
12
|
-
def notify_slack(message)
|
13
|
-
return unless configured?
|
14
|
-
slack.notify(message)
|
15
|
-
end
|
16
|
-
|
17
|
-
def identity
|
18
|
-
@identity ||= `whoami`.chomp
|
19
|
-
end
|
20
|
-
|
21
|
-
def configured?
|
22
|
-
!slack_config.nil?
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def slack
|
28
|
-
@slack ||= SlackNotify::Client.new(slack_config)
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_accessor :slack_config
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|