deploy-cli 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a8d3b48b9a55f7de6d23279d0878765da1a43e86
4
+ data.tar.gz: ac3d941865566ebdbfb2805c553e02f7c62953d0
5
+ SHA512:
6
+ metadata.gz: 0d8322cea80d48de105f8101f9581e257d32847fc30cc6237944aca2fc7ff4c058fee45403327829a02c6e3ba7fdd845b8d88e5a40c9871928a409f46c60a348
7
+ data.tar.gz: b7daa65860485d737dce1f5894c9d8894269fc3c177bd91fc69178d3645849689b4c2494c84fec292117d639b465a4be72e89dacd92541d4b4609b964669247e
@@ -0,0 +1,3 @@
1
+ pkg/
2
+ deploy.rb
3
+ deploy.yaml
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ deploy-cli (0.2.1)
5
+ thor
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ rake (11.2.2)
11
+ thor (0.19.1)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ deploy-cli!
18
+ rake
19
+
20
+ BUNDLED WITH
21
+ 1.11.2
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ task default: [
5
+ :release,
6
+ ]
@@ -0,0 +1,98 @@
1
+ # deploy
2
+
3
+ Deploy from a spec.
4
+
5
+ Does this by simply logging into each machine and do a `git pull origin`
6
+ followed by a `git rebase origin/<branch>`. Other strategies will follow, like
7
+ using rsync.
8
+
9
+ `before` and `after` actions can be triggered to, for example, clean up caches.
10
+
11
+ **This is very much a work in progress** to scratch an itch. Rubygems makes it
12
+ a very convenient way to share the scripts, even if it's not ready to be used en
13
+ masse ;-)
14
+
15
+
16
+ ### Installation
17
+
18
+ gem install deploy-cli
19
+
20
+
21
+ ### Usage
22
+
23
+ $ deploy
24
+ Commands:
25
+ deploy to [STAGE] # Runs a deployment
26
+ deploy help [COMMAND] # Describe available commands or one specific command
27
+ deploy version # Show the current version
28
+
29
+
30
+ This script assume there's either a `deploy.yaml` or a `deploy.rb` file on the
31
+ current directory. If not you can pass it with `--file deploy.rb`.
32
+
33
+
34
+ ### Sample yaml spec (deploy.yaml)
35
+
36
+ ```yaml
37
+ ### Working yaml code
38
+
39
+ default: &SITE
40
+ user: deploy
41
+ before:
42
+ - echo "Started at `date`"
43
+ after:
44
+ - echo "Completed at `date`"
45
+
46
+ notifications:
47
+ email:
48
+ - me@example.com
49
+ slack:
50
+ service: token-goes-here
51
+ channel: "#deployments"
52
+
53
+
54
+
55
+ production:
56
+ <<: *SITE
57
+ path: /var/www/vhosts/example.com
58
+ branch: master
59
+ servers:
60
+ - web-01.example.com
61
+ - web-02.example.com
62
+
63
+
64
+ stage:
65
+ <<: *SITE
66
+ branch: dev
67
+ path: /var/www/vhosts/stage.example.com
68
+ servers:
69
+ - stage-01.example.com
70
+
71
+ ```
72
+
73
+ ### Pseudo ruby spec (deploy.rb)
74
+
75
+ ```ruby
76
+ ### Pseudo code for a deploy DSL
77
+
78
+ stage :stage do
79
+ branch "master"
80
+ user "deploy"
81
+ path "/var/www/vhosts/stage.example.com"
82
+ servers [
83
+ "web-01.example.com",
84
+ "web-02.example.com",
85
+ ]
86
+
87
+ notify :slack do
88
+ token ENV["SLACK_TOKEN"]
89
+ channel "#deployments"
90
+ message "#{s.user} deployed commit #{s.commit} to #{s.stage}."
91
+ emoji ":rocket:"
92
+ end
93
+
94
+ hook :before "echo 'Started at $(date)'"
95
+ hook :after "./clean-caches"
96
+ hook :after "echo 'Completed at $(date)'"
97
+ end
98
+ ```
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require "thor"
5
+ require "yaml"
6
+ require "json"
7
+ require "deploy"
8
+
9
+ module Deploy
10
+ class Cli < Thor
11
+ class_option :file
12
+
13
+ desc "version", "Show the current version"
14
+ def version
15
+ puts "v#{VERSION}"
16
+ end
17
+
18
+ desc "show STAGE", "Shows the deployment spec for STAGE"
19
+ def show stage
20
+ file = _find
21
+ data = YAML.load_file(file)
22
+ spec = data[stage.to_s]
23
+ puts JSON.dump(spec)
24
+ end
25
+
26
+ desc "to STAGE", "Deploys to STAGE"
27
+ def to stage
28
+ file = _find
29
+ abort "Error: Could not find a deploy file." unless file
30
+ if File.extname(file) == ".rb"
31
+ _from_ruby file, stage
32
+ elsif File.extname(file) == ".yaml"
33
+ _from_yaml file, stage
34
+ end
35
+ end
36
+
37
+ def method_missing name
38
+ to name
39
+ end
40
+
41
+ private
42
+ def _find
43
+ return options[:file] if options[:file]
44
+
45
+ files = ["deploy.yaml"]
46
+ dirs = [ENV["HOME"], ".", "/etc/deploy-cli"]
47
+ dirs.each do |dir|
48
+ files.each do |file|
49
+ path = "#{dir}/#{file}"
50
+ if File.exists? path
51
+ return path
52
+ end
53
+ end
54
+ end
55
+ return false
56
+ end
57
+
58
+ def _from_yaml file, stage
59
+ data = YAML.load_file(file)
60
+ spec = data[stage.to_s]
61
+ Deploy::Runner.run spec
62
+ end
63
+
64
+ def _from_ruby file, stage
65
+ abort "Not ready yet"
66
+ end
67
+ end
68
+ end
69
+
70
+ Deploy::Cli.start(ARGV)
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require "deploy/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "deploy-cli"
7
+ spec.version = Deploy::VERSION
8
+ spec.summary = "Deploy from a spec."
9
+ spec.description = "Deploy from a spec"
10
+ spec.homepage = "https://github.com/ptdorf/deploy-cli"
11
+ spec.authors = ["ptdorf"]
12
+ spec.email = ["ptdorf@gmail.com"]
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split $/
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "thor"
20
+ spec.add_development_dependency "rake"
21
+ end
@@ -0,0 +1,180 @@
1
+ require "date"
2
+ require "json"
3
+
4
+ module Deploy
5
+
6
+ class Runner
7
+ BLACK = "1"
8
+ BLUE = "38;5;27;1"
9
+
10
+ def self.run(spec)
11
+ self.new(spec).deploy
12
+ end
13
+
14
+ def initialize(spec)
15
+ @spec = spec
16
+ end
17
+
18
+ def deploy
19
+ @before = @spec["before"]
20
+ @after = @spec["after"]
21
+ @cleanup = @spec["cleanup"]
22
+
23
+ ok = true
24
+ tasks "BEFORE", @before
25
+
26
+ @spec["servers"].each do |server|
27
+ log "[Server #{server}]", BLUE
28
+
29
+ ok = ok && justdoit(server)
30
+
31
+ @commit = ssh(server, "git log -1 --pretty=%s")
32
+ @author = ssh(server, "git log -1 --pretty=%an")
33
+ @hash = ssh(server, "git log -1 --pretty=%h")
34
+ @date = ssh(server, "git log -1 --pretty=%ad")
35
+
36
+ end
37
+
38
+ tasks "AFTER", @after if ok
39
+ tasks "CLEANUP", @cleanup
40
+
41
+ notify
42
+ end
43
+
44
+ def tasks(type, tasks)
45
+ return unless tasks
46
+ log "#{type} ACTIONS"
47
+ if tasks.kind_of? Array
48
+ tasks.each do |t|
49
+ task t
50
+ end
51
+ else
52
+ task tasks
53
+ end
54
+ end
55
+
56
+ def task(cmd)
57
+ puts "$ #{cmd}"
58
+ system(cmd)
59
+ puts
60
+ end
61
+
62
+ def justdoit(server)
63
+ log "CURRENT STATUS"
64
+ status = ssh(server, "git status")
65
+ puts status
66
+ puts
67
+ # return unless status.include? "working directory clean"
68
+
69
+ log "CURRENT RELEASE"
70
+ puts ssh(server, "git log -1")
71
+ puts
72
+
73
+ # TODO Figure this out
74
+ log "PULLING FROM ORIGIN"
75
+ fetched = ssh(server, "git fetch #{@spec["remote"]}")
76
+ puts fetched == "" ? "(none)" : fetched
77
+ puts
78
+ # return unless fetched.size > 0
79
+
80
+ log "REBASING"
81
+ rebased = ssh(server, "git rebase #{@spec["remote"]}/#{@spec["branch"]}")
82
+ puts rebased
83
+ puts
84
+ # return if rebased.include? "is up to date"
85
+
86
+ log "NEW STATUS"
87
+ status = ssh(server, "git status")
88
+ puts status
89
+ puts
90
+
91
+ log "NEW RELEASE"
92
+ puts ssh(server, "git log -1")
93
+ puts
94
+
95
+ true
96
+ end
97
+
98
+ def notify
99
+ return unless @spec["notifications"]
100
+ return unless @spec["notifications"]["slack"]
101
+
102
+ site = @spec["site"]
103
+ service = @spec["notifications"]["slack"]["service"]
104
+ channel = @spec["notifications"]["slack"]["channel"]
105
+ url = "https://hooks.slack.com/services/#{service}"
106
+
107
+ payload = {
108
+ "channel" => channel,
109
+ "username" => "Deployment #{DateTime.now}",
110
+ "text" => "New deployment to <#{site}>",
111
+ "icon_emoji" => ":dotser:",
112
+ "attachments" => [
113
+ {
114
+ # "fallback" => "[fallback] Required text summary of the attachment that is shown by clients that understand attachments but choose not to show them.",
115
+ # "pretext" => "[pretext] Optional text that should appear above the formatted data",
116
+ # "text" => "[text] Optional text that should appear within the attachment",
117
+ "_color" => "warning",
118
+ "fields" => [
119
+ {
120
+ "title" => "Commit",
121
+ "value" => @commit,
122
+ "short" => true,
123
+ },
124
+ {
125
+ "title" => "Date",
126
+ "value" => @date,
127
+ "short" => true,
128
+ },
129
+ {
130
+ "title" => "Author",
131
+ "value" => @author,
132
+ "short" => true,
133
+ },
134
+ {
135
+ "title" => "Hash",
136
+ "value" => @hash,
137
+ "short" => true,
138
+ },
139
+ {
140
+ "title" => "Site",
141
+ "value" => site,
142
+ "short" => true,
143
+ },
144
+ {
145
+ "title" => "Branch",
146
+ "value" => @spec["branch"],
147
+ "short" => true,
148
+ },
149
+ ]
150
+ }
151
+ ]
152
+ }.to_json
153
+
154
+ # puts "curl -s -X POST --data-urlencode 'payload=#{payload}' #{url}"
155
+ `curl -s -X POST --data-urlencode 'payload=#{payload}' #{url}`
156
+ end
157
+
158
+ private
159
+ def ssh(server, cmd)
160
+ full = "ssh -A #{@spec['user']}@#{server}"
161
+ full += " 'cd #{@spec['path']} && #{cmd}'"
162
+ output = `#{full}`.chomp
163
+ code = $?.exitstatus
164
+ abort "Command <#{full}> failed with status #{code}." if code != 0
165
+ output
166
+ end
167
+
168
+ # def which_branch
169
+ # ssh "git rev-parse --abbrev-ref HEAD"
170
+ # end
171
+ #
172
+ # def which_remote
173
+ # ssh "git rev-parse --abbrev-ref HEAD"
174
+ # end
175
+
176
+ def log(message, color = BLACK)
177
+ puts "\033[#{color}m#{message}\033[0m"
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,5 @@
1
+ module Deploy
2
+
3
+ VERSION = "0.2.4"
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: deploy-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4
5
+ platform: ruby
6
+ authors:
7
+ - ptdorf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Deploy from a spec
42
+ email:
43
+ - ptdorf@gmail.com
44
+ executables:
45
+ - deploy
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - Rakefile
53
+ - Readme.md
54
+ - bin/deploy
55
+ - deploy-cli.gemspec
56
+ - lib/deploy.rb
57
+ - lib/deploy/runner.rb
58
+ - lib/deploy/version.rb
59
+ homepage: https://github.com/ptdorf/deploy-cli
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.6.6
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Deploy from a spec.
83
+ test_files: []