dpl 1.10.17.travis.6637.6 → 2.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +74 -0
- data/CONTRIBUTING.md +392 -0
- data/Gemfile +17 -3
- data/Gemfile.lock +373 -0
- data/LICENSE +16 -19
- data/NOTES.md +275 -0
- data/README.md +1977 -707
- data/Rakefile +2 -2
- data/bin/dpl +7 -3
- data/lib/dpl.rb +20 -0
- data/lib/dpl/assets/atlas/install +19 -0
- data/lib/dpl/assets/dpl/README.erb.md +133 -0
- data/lib/dpl/assets/dpl/git_ssh +2 -0
- data/lib/dpl/assets/git/detect_private_key +8 -0
- data/lib/dpl/assets/hephy/filter_log +3 -0
- data/lib/dpl/assets/pypi/install +4 -0
- data/lib/dpl/assets/scalingo/install +6 -0
- data/lib/dpl/cli.rb +36 -48
- data/lib/dpl/ctx.rb +2 -0
- data/lib/dpl/ctx/bash.rb +543 -0
- data/lib/dpl/ctx/test.rb +242 -0
- data/lib/dpl/helper/assets.rb +36 -0
- data/lib/dpl/helper/cmd.rb +167 -0
- data/lib/dpl/helper/config_file.rb +47 -0
- data/lib/dpl/helper/env.rb +39 -0
- data/lib/dpl/helper/interpolate.rb +126 -0
- data/lib/dpl/helper/memoize.rb +20 -0
- data/lib/dpl/helper/squiggle.rb +22 -0
- data/lib/dpl/helper/zip.rb +69 -0
- data/lib/dpl/provider.rb +562 -234
- data/lib/dpl/provider/dsl.rb +369 -0
- data/lib/dpl/provider/examples.rb +128 -0
- data/lib/dpl/provider/status.rb +59 -0
- data/lib/dpl/providers.rb +40 -0
- data/lib/dpl/providers/anynines.rb +65 -0
- data/lib/dpl/providers/atlas.rb +49 -0
- data/lib/dpl/providers/azure_web_apps.rb +59 -0
- data/lib/dpl/providers/bintray.rb +313 -0
- data/lib/dpl/providers/bluemixcloudfoundry.rb +92 -0
- data/lib/dpl/providers/boxfuse.rb +48 -0
- data/lib/dpl/providers/cargo.rb +19 -0
- data/lib/dpl/providers/chef_supermarket.rb +128 -0
- data/lib/dpl/providers/cloud66.rb +40 -0
- data/lib/dpl/providers/cloudfiles.rb +56 -0
- data/lib/dpl/providers/cloudfoundry.rb +81 -0
- data/lib/dpl/providers/codedeploy.rb +179 -0
- data/lib/dpl/providers/datica.rb +60 -0
- data/lib/dpl/providers/elasticbeanstalk.rb +195 -0
- data/lib/dpl/providers/engineyard.rb +107 -0
- data/lib/dpl/providers/firebase.rb +41 -0
- data/lib/dpl/providers/gae.rb +74 -0
- data/lib/dpl/providers/gcs.rb +105 -0
- data/lib/dpl/providers/hackage.rb +47 -0
- data/lib/dpl/providers/hephy.rb +101 -0
- data/lib/dpl/providers/heroku.rb +111 -0
- data/lib/dpl/providers/heroku/api.rb +119 -0
- data/lib/dpl/providers/heroku/git.rb +50 -0
- data/lib/dpl/providers/lambda.rb +202 -0
- data/lib/dpl/providers/launchpad.rb +74 -0
- data/lib/dpl/providers/netlify.rb +30 -0
- data/lib/dpl/providers/npm.rb +88 -0
- data/lib/dpl/providers/openshift.rb +46 -0
- data/lib/dpl/providers/opsworks.rb +142 -0
- data/lib/dpl/providers/packagecloud.rb +190 -0
- data/lib/dpl/providers/pages.rb +17 -0
- data/lib/dpl/providers/pages/api.rb +102 -0
- data/lib/dpl/providers/pages/git.rb +251 -0
- data/lib/dpl/providers/puppetforge.rb +44 -0
- data/lib/dpl/providers/pypi.rb +120 -0
- data/lib/dpl/providers/releases.rb +214 -0
- data/lib/dpl/providers/rubygems.rb +89 -0
- data/lib/dpl/providers/s3.rb +243 -0
- data/lib/dpl/providers/scalingo.rb +63 -0
- data/lib/dpl/providers/script.rb +28 -0
- data/lib/dpl/providers/snap.rb +59 -0
- data/lib/dpl/providers/surge.rb +55 -0
- data/lib/dpl/providers/testfairy.rb +93 -0
- data/lib/dpl/providers/transifex.rb +66 -0
- data/lib/dpl/support/aws_sdk_patch.rb +23 -0
- data/lib/dpl/support/gems.rb +69 -0
- data/lib/dpl/support/gstore_patch.rb +6 -0
- data/lib/dpl/support/version.rb +83 -0
- data/lib/dpl/version.rb +2 -2
- metadata +98 -169
- data/.coveralls.yml +0 -1
- data/.github/CONTRIBUTING.md +0 -173
- data/.github/stale.yml +0 -53
- data/.gitignore +0 -13
- data/.rspec +0 -2
- data/.travis.yml +0 -56
- data/dpl-anynines.gemspec +0 -3
- data/dpl-atlas.gemspec +0 -3
- data/dpl-azure_webapps.gemspec +0 -3
- data/dpl-bintray.gemspec +0 -3
- data/dpl-bitballoon.gemspec +0 -3
- data/dpl-bluemix_cloud_foundry.gemspec +0 -3
- data/dpl-boxfuse.gemspec +0 -3
- data/dpl-cargo.gemspec +0 -3
- data/dpl-catalyze.gemspec +0 -3
- data/dpl-chef_supermarket.gemspec +0 -20
- data/dpl-cloud66.gemspec +0 -3
- data/dpl-cloud_files.gemspec +0 -3
- data/dpl-cloud_foundry.gemspec +0 -3
- data/dpl-code_deploy.gemspec +0 -3
- data/dpl-deis.gemspec +0 -3
- data/dpl-elastic_beanstalk.gemspec +0 -3
- data/dpl-engine_yard.gemspec +0 -3
- data/dpl-firebase.gemspec +0 -3
- data/dpl-gae.gemspec +0 -3
- data/dpl-gcs.gemspec +0 -3
- data/dpl-hackage.gemspec +0 -3
- data/dpl-hephy.gemspec +0 -3
- data/dpl-heroku.gemspec +0 -3
- data/dpl-lambda.gemspec +0 -3
- data/dpl-launchpad.gemspec +0 -3
- data/dpl-npm.gemspec +0 -3
- data/dpl-openshift.gemspec +0 -3
- data/dpl-ops_works.gemspec +0 -3
- data/dpl-packagecloud.gemspec +0 -3
- data/dpl-pages.gemspec +0 -3
- data/dpl-puppet_forge.gemspec +0 -3
- data/dpl-pypi.gemspec +0 -3
- data/dpl-releases.gemspec +0 -8
- data/dpl-rubygems.gemspec +0 -3
- data/dpl-s3.gemspec +0 -3
- data/dpl-scalingo.gemspec +0 -3
- data/dpl-script.gemspec +0 -3
- data/dpl-snap.gemspec +0 -3
- data/dpl-surge.gemspec +0 -3
- data/dpl-testfairy.gemspec +0 -3
- data/dpl-transifex.gemspec +0 -3
- data/dpl.gemspec +0 -3
- data/gemspec_helper.rb +0 -51
- data/lib/dpl/error.rb +0 -3
- data/notes/engine_yard.md +0 -1
- data/notes/heroku.md +0 -3
- data/spec/cli_spec.rb +0 -36
- data/spec/provider_spec.rb +0 -191
- data/spec/spec_helper.rb +0 -20
@@ -0,0 +1,41 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Firebase < Provider
|
4
|
+
status :alpha
|
5
|
+
|
6
|
+
description sq(<<-str)
|
7
|
+
tbd
|
8
|
+
str
|
9
|
+
|
10
|
+
node_js '>= 8.0.0'
|
11
|
+
|
12
|
+
npm 'firebase-tools@^6.3', 'firebase'
|
13
|
+
|
14
|
+
path 'node_modules/.bin'
|
15
|
+
|
16
|
+
env :firebase
|
17
|
+
|
18
|
+
opt '--token TOKEN', 'Firebase CI access token (generate with firebase login:ci)', required: true, secret: true
|
19
|
+
opt '--project NAME', 'Firebase project to deploy to (defaults to the one specified in your firebase.json)'
|
20
|
+
opt '--message MSG', 'Message describing this deployment.'
|
21
|
+
opt '--only SERVICES', 'Firebase services to deploy', note: 'can be a comma-separated list'
|
22
|
+
opt '--force', 'Whether or not to delete Cloud Functions missing from the current working directory'
|
23
|
+
|
24
|
+
cmds deploy: 'firebase deploy --non-interactive %{deploy_opts}'
|
25
|
+
errs deploy: 'Firebase deployment failed'
|
26
|
+
msgs missing_config: 'Missing firebase.json'
|
27
|
+
|
28
|
+
def validate
|
29
|
+
error :missing_config unless File.exists?('firebase.json')
|
30
|
+
end
|
31
|
+
|
32
|
+
def deploy
|
33
|
+
shell :deploy
|
34
|
+
end
|
35
|
+
|
36
|
+
def deploy_opts
|
37
|
+
opts_for(%i(project message token only force))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Gae < Provider
|
4
|
+
status :alpha
|
5
|
+
|
6
|
+
full_name 'Google App Engine'
|
7
|
+
|
8
|
+
description sq(<<-str)
|
9
|
+
tbd
|
10
|
+
str
|
11
|
+
|
12
|
+
python '>= 2.7.9'
|
13
|
+
|
14
|
+
env :googlecloud, :cloudsdk_core, allow_skip_underscore: true
|
15
|
+
|
16
|
+
opt '--project ID', 'Project ID used to identify the project on Google Cloud', required: true
|
17
|
+
opt '--keyfile FILE', 'Path to the JSON file containing your Service Account credentials in JSON Web Token format. To be obtained via the Google Developers Console. Should be handled with care as it contains authorization keys.', default: 'service-account.json'
|
18
|
+
opt '--config FILE', 'Path to your service configuration file', type: :array, default: 'app.yaml'
|
19
|
+
opt '--version VER', 'The version of the app that will be created or replaced by this deployment. If you do not specify a version, one will be generated for you'
|
20
|
+
opt '--verbosity LEVEL', 'Adjust the log verbosity', default: 'warning'
|
21
|
+
opt '--promote', 'Do not promote the deployed version', default: true
|
22
|
+
opt '--stop_previous_version', 'Prevent your deployment from stopping the previously promoted version. This is from the future, so might not work (yet).', default: true
|
23
|
+
opt '--install_sdk', 'Do not install the Google Cloud SDK', default: true
|
24
|
+
|
25
|
+
cmds install: 'curl -L https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz | gzip -d | tar -x -C ~',
|
26
|
+
bootstrap: '~/google-cloud-sdk/bin/bootstrapping/install.py --usage-reporting=false --command-completion=false --path-update=false',
|
27
|
+
login: 'gcloud -q auth activate-service-account --key-file %{keyfile}',
|
28
|
+
deploy: 'gcloud -q app deploy %{config} %{deploy_opts}',
|
29
|
+
cat_logs: 'find $HOME/.config/gcloud/logs -type f -print -exec cat {} \;'
|
30
|
+
|
31
|
+
errs install: 'Failed to download Google Cloud SDK.',
|
32
|
+
login: 'Failed to authenticate.',
|
33
|
+
bootstrap: 'Failed bootstrap Google Cloud SDK.'
|
34
|
+
|
35
|
+
msgs failed: 'Deployment failed.'
|
36
|
+
|
37
|
+
path '~/google-cloud-sdk/bin'
|
38
|
+
|
39
|
+
def install
|
40
|
+
return unless install_sdk?
|
41
|
+
shell :install
|
42
|
+
shell :bootstrap
|
43
|
+
end
|
44
|
+
|
45
|
+
def login
|
46
|
+
shell :login
|
47
|
+
end
|
48
|
+
|
49
|
+
def deploy
|
50
|
+
shell :deploy
|
51
|
+
failed unless success?
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def deploy_opts
|
57
|
+
opts = [*opts_for(%i(project verbosity version))]
|
58
|
+
opts << '--no-promote' unless promote?
|
59
|
+
opts << '--no-stop-previous-version' unless stop_previous_version?
|
60
|
+
opts.join(' ')
|
61
|
+
end
|
62
|
+
|
63
|
+
def failed
|
64
|
+
warn :failed
|
65
|
+
shell :cat_logs
|
66
|
+
error ''
|
67
|
+
end
|
68
|
+
|
69
|
+
def project
|
70
|
+
super || File.dirname(build_dir)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'kconv'
|
2
|
+
|
3
|
+
module Dpl
|
4
|
+
module Providers
|
5
|
+
class Gcs < Provider
|
6
|
+
status :alpha
|
7
|
+
|
8
|
+
full_name 'Google Cloud Store'
|
9
|
+
|
10
|
+
description sq(<<-str)
|
11
|
+
tbd
|
12
|
+
str
|
13
|
+
|
14
|
+
gem 'mime-types', '~> 3.2.2'
|
15
|
+
|
16
|
+
python '>= 2.7.9'
|
17
|
+
|
18
|
+
opt '--access_key_id ID', 'GCS Interoperable Access Key ID', required: true, secret: true
|
19
|
+
opt '--secret_access_key KEY', 'GCS Interoperable Access Secret', required: true, secret: true
|
20
|
+
opt '--bucket BUCKET', 'GCS Bucket', required: true
|
21
|
+
opt '--local_dir DIR', 'Local directory to upload from', default: '.'
|
22
|
+
opt '--upload_dir DIR', 'GCS directory to upload to'
|
23
|
+
opt '--dot_match', 'Upload hidden files starting with a dot'
|
24
|
+
opt '--acl ACL', 'Access control to set for uploaded objects'
|
25
|
+
opt '--detect_encoding', 'HTTP header Content-Encoding to set for files compressed with gzip and compress utilities.'
|
26
|
+
opt '--cache_control HEADER', 'HTTP header Cache-Control to suggest that the browser cache the file.'
|
27
|
+
|
28
|
+
cmds install: 'curl -L %{URL} | tar xz -C ~ && ~/google-cloud-sdk/install.sh --path-update false --usage-reporting false --command-completion false',
|
29
|
+
copy: 'gsutil %{gs_opts}cp %{copy_opts}-r %{source} %{target}'
|
30
|
+
|
31
|
+
msgs login: 'Authenticating with access key: %{access_key_id}'
|
32
|
+
|
33
|
+
errs copy: 'Failed uploading files.'
|
34
|
+
|
35
|
+
URL = 'https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-252.0.0-linux-x86_64.tar.gz'
|
36
|
+
|
37
|
+
BOTO = sq(<<-str)
|
38
|
+
[Credentials]
|
39
|
+
gs_access_key_id = %{access_key_id}
|
40
|
+
gs_secret_access_key = %{secret_access_key}
|
41
|
+
str
|
42
|
+
|
43
|
+
path '~/google-cloud-sdk'
|
44
|
+
move '/etc/boto.cfg'
|
45
|
+
|
46
|
+
def install
|
47
|
+
shell :install
|
48
|
+
end
|
49
|
+
|
50
|
+
def login
|
51
|
+
info :login
|
52
|
+
write_boto
|
53
|
+
end
|
54
|
+
|
55
|
+
def deploy
|
56
|
+
Dir.chdir(local_dir) do
|
57
|
+
source_files.each { |file| copy(file) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def write_boto
|
64
|
+
write_file '~/.boto', interpolate(BOTO, opts, secure: true), 0600
|
65
|
+
end
|
66
|
+
|
67
|
+
def source_files
|
68
|
+
Dir.glob(*glob).select { |path| File.file?(path) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def copy(source)
|
72
|
+
shell :copy, gs_opts: gs_opts(source), source: source
|
73
|
+
end
|
74
|
+
|
75
|
+
def gs_opts(path)
|
76
|
+
opts = []
|
77
|
+
opts << %(-h "Cache-Control:#{cache_control}") if cache_control?
|
78
|
+
opts << %(-h "Content-Encoding:#{encoding(path)}") if detect_encoding?
|
79
|
+
opts << %(-h "Content-type:#{mime_type(path)}") if mime_type(path)
|
80
|
+
opts.join(' ') + ' ' if opts.any?
|
81
|
+
end
|
82
|
+
|
83
|
+
def copy_opts
|
84
|
+
opts = []
|
85
|
+
opts << %(-a "#{acl}") if acl?
|
86
|
+
opts.join(' ') + ' ' if opts.any?
|
87
|
+
end
|
88
|
+
|
89
|
+
def target
|
90
|
+
"gs://#{bucket}/#{upload_dir}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def mime_type(path)
|
94
|
+
type = MIME::Types.type_for(path).first
|
95
|
+
type.to_s if type
|
96
|
+
end
|
97
|
+
|
98
|
+
def glob
|
99
|
+
glob = ['**/*']
|
100
|
+
glob << File::FNM_DOTMATCH if dot_match?
|
101
|
+
glob
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Hackage < Provider
|
4
|
+
status :alpha
|
5
|
+
|
6
|
+
description sq(<<-str)
|
7
|
+
tbd
|
8
|
+
str
|
9
|
+
|
10
|
+
opt '--username USER', 'Hackage username', required: true
|
11
|
+
opt '--password USER', 'Hackage password', required: true, secret: true
|
12
|
+
opt '--publish', 'Whether or not to publish the package'
|
13
|
+
|
14
|
+
cmds check: 'cabal check',
|
15
|
+
sdist: 'cabal sdist',
|
16
|
+
upload: 'cabal upload %{upload_opts} %{path}'
|
17
|
+
|
18
|
+
errs check: 'cabal check failed',
|
19
|
+
sdist: 'cabal sdist failed',
|
20
|
+
upload: 'cabal upload failed'
|
21
|
+
|
22
|
+
def validate
|
23
|
+
shell :check
|
24
|
+
end
|
25
|
+
|
26
|
+
def prepare
|
27
|
+
shell :sdist
|
28
|
+
end
|
29
|
+
|
30
|
+
def deploy
|
31
|
+
tar_files.each do |path|
|
32
|
+
shell :upload, path: path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def upload_opts
|
39
|
+
opts_for(%i(publish username password))
|
40
|
+
end
|
41
|
+
|
42
|
+
def tar_files
|
43
|
+
Dir.glob('dist/*.tar.gz').sort
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Hephy < Provider
|
4
|
+
status :alpha
|
5
|
+
|
6
|
+
description sq(<<-str)
|
7
|
+
tbd
|
8
|
+
str
|
9
|
+
|
10
|
+
opt '--controller NAME', 'Hephy controller', required: true, example: 'hephy.hephyapps.com'
|
11
|
+
opt '--username USER', 'Hephy username', required: true
|
12
|
+
opt '--password PASS', 'Hephy password', required: true, secret: true
|
13
|
+
opt '--app APP', 'Deis app', required: true
|
14
|
+
opt '--cli_version VER', 'Install a specific hephy cli version', default: 'stable'
|
15
|
+
opt '--verbose', 'Verbose log output'
|
16
|
+
|
17
|
+
needs :git, :ssh_key
|
18
|
+
path '~/.dpl'
|
19
|
+
|
20
|
+
INSTALL = 'https://raw.githubusercontent.com/teamhephy/workflow-cli/master/install-v2.sh'
|
21
|
+
|
22
|
+
cmds install: 'curl -sSL %{INSTALL} | bash -x -s %{cli_version} && mv deis ~/.dpl',
|
23
|
+
login: 'deis login %{controller} --username=%{username} --password=%{password}',
|
24
|
+
add_key: 'deis keys:add %{key}',
|
25
|
+
validate: 'deis apps:info --app=%{app}',
|
26
|
+
deploy: 'filter_log git push %{verbose} %{url} HEAD:refs/heads/master -f',
|
27
|
+
run: 'deis run -a %{app} -- %{cmd}',
|
28
|
+
remove_key: 'deis keys:remove %{key_name}'
|
29
|
+
|
30
|
+
errs login: 'Login failed.',
|
31
|
+
add_key: 'Adding keys failed.',
|
32
|
+
validate: 'Application could not be verified.',
|
33
|
+
deploy: 'Deploying application failed.',
|
34
|
+
run: 'Running command failed.',
|
35
|
+
remove_key: 'Removing keys failed.'
|
36
|
+
|
37
|
+
def install
|
38
|
+
shell :install
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup
|
42
|
+
install_hephy_log_filter
|
43
|
+
end
|
44
|
+
|
45
|
+
def login
|
46
|
+
shell :login
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_key(key)
|
50
|
+
shell :add_key, key: key
|
51
|
+
wait_for_ssh_access(host, port)
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate
|
55
|
+
shell :validate
|
56
|
+
end
|
57
|
+
|
58
|
+
def deploy
|
59
|
+
shell :deploy
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_cmd(cmd)
|
63
|
+
shell :run, app: app, cmd: cmd
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_key
|
67
|
+
shell :remove_key
|
68
|
+
end
|
69
|
+
|
70
|
+
def verbose
|
71
|
+
verbose? ? '-v' : ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def host
|
75
|
+
url.host
|
76
|
+
end
|
77
|
+
|
78
|
+
def port
|
79
|
+
url.port
|
80
|
+
end
|
81
|
+
|
82
|
+
def url
|
83
|
+
@url ||= URI.parse("ssh://git@#{builder}:2222/#{app}.git")
|
84
|
+
end
|
85
|
+
|
86
|
+
def builder
|
87
|
+
parts = host.split('.')
|
88
|
+
parts[0] = [parts[0], 'builder'].join('-')
|
89
|
+
parts.join('.')
|
90
|
+
end
|
91
|
+
|
92
|
+
def host
|
93
|
+
controller.gsub(/https?:\/\//, '').split(':')[0]
|
94
|
+
end
|
95
|
+
|
96
|
+
def install_hephy_log_filter
|
97
|
+
asset(:filter_log).copy('~/.dpl/')
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Dpl
|
2
|
+
module Providers
|
3
|
+
class Heroku < Provider
|
4
|
+
def self.new(ctx, args)
|
5
|
+
# can this be a generic dispatch feature in Cl?
|
6
|
+
return super unless registry_key.to_sym == :heroku
|
7
|
+
arg = args.detect { |arg| arg.include?('--strategy') }
|
8
|
+
strategy = arg ? arg.split('=').last : 'api'
|
9
|
+
Provider[:"heroku:#{strategy}"].new(ctx, args)
|
10
|
+
end
|
11
|
+
|
12
|
+
gem 'faraday', '~> 0.9.2'
|
13
|
+
gem 'json'
|
14
|
+
gem 'netrc', '~> 0.11.0'
|
15
|
+
gem 'rendezvous', '~> 0.1.3'
|
16
|
+
|
17
|
+
opt '--strategy NAME', 'Heroku deployment strategy', default: 'api', enum: %w(api git), internal: true
|
18
|
+
opt '--app APP', 'Heroku app name', default: :repo_name
|
19
|
+
opt '--log_level LEVEL', internal: true
|
20
|
+
|
21
|
+
msgs login: 'Authenticating ... ',
|
22
|
+
restart: 'Restarting dynos ... ',
|
23
|
+
validate: 'Checking for app %{app} ... ',
|
24
|
+
run_cmd: 'Running command %s ... ',
|
25
|
+
success: 'success.',
|
26
|
+
api_error: 'API request failed: %s (see %s)'
|
27
|
+
|
28
|
+
URL = 'https://api.heroku.com'
|
29
|
+
|
30
|
+
HEADERS = {
|
31
|
+
'Accept': 'application/vnd.heroku+json; version=3',
|
32
|
+
'User-Agent': user_agent,
|
33
|
+
}
|
34
|
+
|
35
|
+
attr_reader :email
|
36
|
+
|
37
|
+
def login
|
38
|
+
print :login
|
39
|
+
res = http.get('/account')
|
40
|
+
handle_error(res) unless res.success?
|
41
|
+
@email = JSON.parse(res.body)["email"]
|
42
|
+
info :success
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate
|
46
|
+
print :validate
|
47
|
+
res = http.get("/apps/#{app}")
|
48
|
+
handle_error(res) unless res.success?
|
49
|
+
info :success
|
50
|
+
end
|
51
|
+
|
52
|
+
def restart
|
53
|
+
print :restart
|
54
|
+
res = http.delete "/apps/#{app}/dynos" do |req|
|
55
|
+
req.headers['Content-Type'] = 'application/json'
|
56
|
+
end
|
57
|
+
handle_error(res) unless res.success?
|
58
|
+
info :success
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_cmd(cmd)
|
62
|
+
print :run_cmd, cmd
|
63
|
+
res = http.post "/apps/#{app}/dynos" do |req|
|
64
|
+
req.headers['Content-Type'] = 'application/json'
|
65
|
+
req.body = { command: cmd, attach: true}.to_json
|
66
|
+
end
|
67
|
+
handle_error(res) unless res.success?
|
68
|
+
rendezvous(JSON.parse(res.body)['attach_url'])
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def http
|
74
|
+
@http ||= Faraday.new(url: URL, headers: headers) do |http|
|
75
|
+
http.basic_auth(username, password) if username && password
|
76
|
+
http.response :logger, logger, &method(:filter) if log_level?
|
77
|
+
http.adapter Faraday.default_adapter
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def headers
|
82
|
+
return HEADERS.dup if username && password
|
83
|
+
HEADERS.merge('Authorization': "Bearer #{api_key}")
|
84
|
+
end
|
85
|
+
|
86
|
+
def filter(logger)
|
87
|
+
logger.filter(/(.*Authorization: ).*/,'\1[REDACTED]')
|
88
|
+
end
|
89
|
+
|
90
|
+
def logger
|
91
|
+
super(log_level)
|
92
|
+
end
|
93
|
+
|
94
|
+
def handle_error(response)
|
95
|
+
body = JSON.parse(response.body)
|
96
|
+
error :api_error, body['message'], body['url']
|
97
|
+
end
|
98
|
+
|
99
|
+
def rendezvous(url)
|
100
|
+
Rendezvous.start(url: url)
|
101
|
+
end
|
102
|
+
|
103
|
+
# overwritten in Git, meaningless in Api
|
104
|
+
def username; end
|
105
|
+
def password; end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
require 'dpl/providers/heroku/api'
|
111
|
+
require 'dpl/providers/heroku/git'
|