deploy-cli 0.2.4

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.
@@ -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: []