travis_dpl_test 2.0.3.beta.4.ror

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +172 -0
  3. data/CODE_OF_CONDUCT.md +74 -0
  4. data/CONTRIBUTING.md +392 -0
  5. data/Gemfile +32 -0
  6. data/Gemfile.lock +611 -0
  7. data/LICENSE +19 -0
  8. data/README.md +2744 -0
  9. data/Rakefile +210 -0
  10. data/bin/dpl +11 -0
  11. data/config/transliterate.yml +733 -0
  12. data/dpl.gemspec +23 -0
  13. data/lib/dpl/assets/atlas/install +19 -0
  14. data/lib/dpl/assets/convox/install +11 -0
  15. data/lib/dpl/assets/dpl/README.erb.md +138 -0
  16. data/lib/dpl/assets/dpl/git_ssh +8 -0
  17. data/lib/dpl/assets/git/detect_private_key +8 -0
  18. data/lib/dpl/assets/hephy/filter_log +3 -0
  19. data/lib/dpl/assets/pypi/install +4 -0
  20. data/lib/dpl/assets/scalingo/install +6 -0
  21. data/lib/dpl/cli.rb +100 -0
  22. data/lib/dpl/ctx/bash.rb +549 -0
  23. data/lib/dpl/ctx/test.rb +255 -0
  24. data/lib/dpl/ctx.rb +4 -0
  25. data/lib/dpl/helper/assets.rb +38 -0
  26. data/lib/dpl/helper/cmd.rb +169 -0
  27. data/lib/dpl/helper/config_file.rb +49 -0
  28. data/lib/dpl/helper/cookbook_site_streaming_uploader.rb +249 -0
  29. data/lib/dpl/helper/env.rb +92 -0
  30. data/lib/dpl/helper/github.rb +22 -0
  31. data/lib/dpl/helper/interpolate.rb +160 -0
  32. data/lib/dpl/helper/memoize.rb +23 -0
  33. data/lib/dpl/helper/squiggle.rb +24 -0
  34. data/lib/dpl/helper/transliterate.rb +13 -0
  35. data/lib/dpl/helper/wrap.rb +11 -0
  36. data/lib/dpl/helper/zip.rb +71 -0
  37. data/lib/dpl/provider/dsl.rb +410 -0
  38. data/lib/dpl/provider/examples.rb +132 -0
  39. data/lib/dpl/provider/status.rb +61 -0
  40. data/lib/dpl/provider.rb +651 -0
  41. data/lib/dpl/providers/anynines.rb +71 -0
  42. data/lib/dpl/providers/azure_web_apps.rb +63 -0
  43. data/lib/dpl/providers/bintray.rb +324 -0
  44. data/lib/dpl/providers/bluemixcloudfoundry.rb +98 -0
  45. data/lib/dpl/providers/boxfuse.rb +52 -0
  46. data/lib/dpl/providers/cargo.rb +32 -0
  47. data/lib/dpl/providers/chef_supermarket.rb +132 -0
  48. data/lib/dpl/providers/cloud66.rb +46 -0
  49. data/lib/dpl/providers/cloudfiles.rb +62 -0
  50. data/lib/dpl/providers/cloudformation.rb +281 -0
  51. data/lib/dpl/providers/cloudfoundry.rb +89 -0
  52. data/lib/dpl/providers/codedeploy.rb +190 -0
  53. data/lib/dpl/providers/convox.rb +130 -0
  54. data/lib/dpl/providers/datica.rb +64 -0
  55. data/lib/dpl/providers/ecr.rb +129 -0
  56. data/lib/dpl/providers/elasticbeanstalk.rb +207 -0
  57. data/lib/dpl/providers/engineyard.rb +113 -0
  58. data/lib/dpl/providers/firebase.rb +45 -0
  59. data/lib/dpl/providers/flynn.rb +35 -0
  60. data/lib/dpl/providers/gae.rb +78 -0
  61. data/lib/dpl/providers/gcs.rb +132 -0
  62. data/lib/dpl/providers/git_push.rb +273 -0
  63. data/lib/dpl/providers/gleis.rb +74 -0
  64. data/lib/dpl/providers/hackage.rb +53 -0
  65. data/lib/dpl/providers/hephy.rb +107 -0
  66. data/lib/dpl/providers/heroku/api.rb +123 -0
  67. data/lib/dpl/providers/heroku/git.rb +54 -0
  68. data/lib/dpl/providers/heroku.rb +111 -0
  69. data/lib/dpl/providers/lambda.rb +211 -0
  70. data/lib/dpl/providers/launchpad.rb +80 -0
  71. data/lib/dpl/providers/netlify.rb +38 -0
  72. data/lib/dpl/providers/npm.rb +130 -0
  73. data/lib/dpl/providers/nuget.rb +41 -0
  74. data/lib/dpl/providers/openshift.rb +52 -0
  75. data/lib/dpl/providers/opsworks.rb +146 -0
  76. data/lib/dpl/providers/packagecloud.rb_ +194 -0
  77. data/lib/dpl/providers/pages/api.rb +106 -0
  78. data/lib/dpl/providers/pages/git.rb +262 -0
  79. data/lib/dpl/providers/pages.rb +18 -0
  80. data/lib/dpl/providers/puppetforge.rb +50 -0
  81. data/lib/dpl/providers/pypi.rb +125 -0
  82. data/lib/dpl/providers/releases.rb +234 -0
  83. data/lib/dpl/providers/rubygems.rb +97 -0
  84. data/lib/dpl/providers/s3.rb +251 -0
  85. data/lib/dpl/providers/scalingo.rb +69 -0
  86. data/lib/dpl/providers/script.rb +32 -0
  87. data/lib/dpl/providers/snap.rb +68 -0
  88. data/lib/dpl/providers/surge.rb +59 -0
  89. data/lib/dpl/providers/testfairy.rb +101 -0
  90. data/lib/dpl/providers/transifex.rb +72 -0
  91. data/lib/dpl/providers.rb +48 -0
  92. data/lib/dpl/string_ext.rb +23 -0
  93. data/lib/dpl/support/aws_sdk_patch.rb +26 -0
  94. data/lib/dpl/support/gems.rb +73 -0
  95. data/lib/dpl/support/gstore_patch.rb +8 -0
  96. data/lib/dpl/support/version.rb +84 -0
  97. data/lib/dpl/version.rb +5 -0
  98. data/lib/dpl.rb +23 -0
  99. data/status.json +237 -0
  100. metadata +161 -0
@@ -0,0 +1,190 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ # split this up to CodeDeploy::Github and CodeDeploy::S3 using the
6
+ # revision_type, in order to make opts more strict
7
+ class Codedeploy < Provider
8
+ register :codedeploy
9
+
10
+ status :stable
11
+
12
+ full_name 'AWS Code Deploy'
13
+
14
+ description sq(<<-STR)
15
+ tbd
16
+ STR
17
+
18
+ gem 'aws-sdk-codedeploy', '~> 1.0'
19
+ gem 'aws-sdk-s3', '~> 1'
20
+
21
+ env :aws, :codedeploy
22
+ config '~/.aws/credentials', '~/.aws/config', prefix: 'aws'
23
+
24
+ opt '--access_key_id ID', 'AWS access key', required: true, secret: true
25
+ opt '--secret_access_key KEY', 'AWS secret access key', required: true, secret: true
26
+ opt '--application NAME', 'CodeDeploy application name', required: true
27
+ opt '--deployment_group GROUP', 'CodeDeploy deployment group name'
28
+ opt '--revision_type TYPE', 'CodeDeploy revision type', enum: %w[s3 github], downcase: true
29
+ opt '--commit_id SHA', 'Commit ID in case of GitHub'
30
+ opt '--repository NAME', 'Repository name in case of GitHub'
31
+ opt '--bucket NAME', 'S3 bucket in case of S3'
32
+ opt '--region REGION', 'AWS availability zone', default: 'us-east-1'
33
+ opt '--file_exists_behavior STR', 'How to handle files that already exist in a deployment target location', enum: %w[disallow overwrite retain], default: 'disallow'
34
+ opt '--wait_until_deployed', 'Wait until the deployment has finished'
35
+ opt '--bundle_type TYPE', 'Bundle type of the revision'
36
+ opt '--key KEY', 'S3 bucket key of the revision'
37
+ opt '--description DESCR', 'Description of the revision', interpolate: true
38
+ opt '--endpoint ENDPOINT', 'S3 endpoint url'
39
+
40
+ msgs login: 'Using Access Key: %{access_key_id}',
41
+ deploy_triggered: 'Deployment triggered: %s',
42
+ register_revision: 'Registering app revision with version=%s, etag=%s',
43
+ waiting_for_deploy: 'Waiting for the deployment to finish ',
44
+ finished_deploy: 'done: %s.',
45
+ description: 'Deploy build %{build_number} via Travis CI',
46
+ missing_bucket: 'Missing required bucket for S3 deployment',
47
+ missing_key: 'Missing required key for S3 deployment',
48
+ unknown_revision_type: 'Unknown revision type %p',
49
+ unknown_bundle_type: 'Unknown bundle type'
50
+
51
+ vars :build_number
52
+
53
+ def login
54
+ info :login
55
+ end
56
+
57
+ def deploy
58
+ register_revision if revision_info[:version]
59
+ id = create_deployment
60
+ info :deploy_triggered, id
61
+ wait_until_deployed(id) if wait_until_deployed?
62
+ rescue Aws::CodeDeploy::Errors::DeploymentLimitExceededException => e
63
+ error e.message
64
+ end
65
+
66
+ def register_revision
67
+ info :register_revision, revision_info[:version], revision_info[:e_tag]
68
+ code_deploy.register_application_revision(
69
+ revision:,
70
+ application_name: application,
71
+ description:
72
+ )
73
+ end
74
+
75
+ def create_deployment
76
+ deployment = code_deploy.create_deployment(
77
+ revision:,
78
+ application_name: application,
79
+ deployment_group_name: deployment_group,
80
+ description:,
81
+ file_exists_behavior: file_exists_behavior.upcase
82
+ )
83
+ deployment.deployment_id
84
+ end
85
+
86
+ def wait_until_deployed(id)
87
+ print :waiting_for_deploy
88
+ status = poll(id) until %w[Succeeded Failed Stopped].include?(status)
89
+ case status
90
+ when 'Succeeded'
91
+ info :finished_deploy, status
92
+ else
93
+ error :finished_deploy, status
94
+ end
95
+ end
96
+
97
+ def poll(id)
98
+ sleep 5
99
+ print '.'
100
+ code_deploy.get_deployment(deployment_id: id)[:deployment_info][:status]
101
+ end
102
+
103
+ def revision_info
104
+ revision[:s3_location] || {}
105
+ end
106
+
107
+ def revision
108
+ @revision ||= case revision_type
109
+ when 's3' then s3_revision
110
+ when 'github' then github_revision
111
+ when nil then bucket? ? s3_revision : github_revision
112
+ else error :unknown_revision_type, revision_type
113
+ end
114
+ end
115
+
116
+ def s3_revision
117
+ {
118
+ revision_type: 'S3',
119
+ s3_location: compact(
120
+ bucket:,
121
+ bundle_type:,
122
+ version: revision_version_info[:version_id],
123
+ e_tag: revision_version_info[:etag],
124
+ key:
125
+ )
126
+ }
127
+ end
128
+
129
+ def revision_version_info
130
+ s3.head_object(bucket:, key:)
131
+ rescue Aws::Errors::ServiceError => e
132
+ error e.message
133
+ end
134
+
135
+ def github_revision
136
+ {
137
+ revision_type: 'GitHub',
138
+ git_hub_location: {
139
+ commit_id:,
140
+ repository:
141
+ }
142
+ }
143
+ end
144
+
145
+ def commit_id
146
+ super || git_sha
147
+ end
148
+
149
+ def repository
150
+ super || ENV['TRAVIS_REPO_SLUG'] || File.basename(Dir.pwd)
151
+ end
152
+
153
+ def bucket
154
+ super || error(:missing_bucket)
155
+ end
156
+
157
+ def key
158
+ super || error(:missing_key)
159
+ end
160
+
161
+ def bundle_type
162
+ super || key =~ /\.(tar|tgz|zip)$/ && ::Regexp.last_match(1) || error(:unknown_bundle_type)
163
+ end
164
+
165
+ def description
166
+ interpolate(super || msg(:description), vars:)
167
+ end
168
+
169
+ def build_number
170
+ ENV['TRAVIS_BUILD_NUMBER']
171
+ end
172
+
173
+ def code_deploy
174
+ @code_deploy ||= Aws::CodeDeploy::Client.new(client_options)
175
+ end
176
+
177
+ def s3
178
+ @s3 ||= Aws::S3::Client.new(client_options)
179
+ end
180
+
181
+ def client_options
182
+ compact(region:, credentials:, endpoint:)
183
+ end
184
+
185
+ def credentials
186
+ Aws::Credentials.new(access_key_id, secret_access_key)
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Convox < Provider
6
+ register :convox
7
+
8
+ status :dev
9
+
10
+ description sq(<<-STR)
11
+ tbd
12
+ STR
13
+
14
+ gem 'json'
15
+
16
+ env :convox
17
+
18
+ # needs descriptions
19
+ opt '--host HOST', default: 'console.convox.com'
20
+ opt '--app APP', required: true
21
+ opt '--rack RACK', required: true
22
+ opt '--password PASS', required: true
23
+ opt '--install_url URL', default: 'https://convox.com/cli/linux/convox'
24
+ opt '--update_cli'
25
+ opt '--create'
26
+ opt '--promote', default: true
27
+ opt '--env_names VARS', type: :array, sep: ','
28
+ opt '--env VARS', type: :array
29
+ opt '--env_file FILE'
30
+ opt '--description STR'
31
+ opt '--generation NUM', type: :int, default: '2'
32
+ opt '--prepare CMDS', 'Run commands with convox cli available just before deployment', type: :array
33
+
34
+ # if app and rack are exported to the env, do they need to be passed to these commands?
35
+ cmds login: 'convox version --rack %{rack}',
36
+ validate: 'convox apps info --rack %{rack} --app %{app}',
37
+ create: 'convox apps create %{app} --generation %{generation} --rack %{rack} --wait',
38
+ update: 'convox update',
39
+ set_env: 'convox env set %{env} --rack %{rack} --app %{app} --replace',
40
+ build: 'convox build --rack %{rack} --app %{app} --id --description %{escaped_description}',
41
+ deploy: 'convox deploy --rack %{rack} --app %{app} --wait --id --description %{escaped_description}'
42
+
43
+ msgs create: 'Application %{app} does not exist on rack %{rack}. Creating it ...',
44
+ missing: 'Application %{app} does not exist on rack %{rack}.',
45
+ env_file: 'The given env_file does not exist.',
46
+ deploy: 'Building and promoting application ...',
47
+ build: 'Building application ...'
48
+
49
+ errs login: 'Login failed.'
50
+
51
+ def install
52
+ script :install
53
+ shell :update if update_cli?
54
+ export
55
+ end
56
+
57
+ def login
58
+ shell :login
59
+ end
60
+
61
+ def validate
62
+ shell :validate, assert: false and return
63
+ error :missing unless create?
64
+ shell :create
65
+ end
66
+
67
+ def prepare
68
+ Array(super).each do |cmd|
69
+ cmd.casecmp('restart').zero? ? restart : run_cmd(cmd)
70
+ end
71
+ end
72
+
73
+ def deploy
74
+ shell :set_env, echo: false unless env.empty?
75
+ shell promote? ? :deploy : :build, echo: false
76
+ end
77
+
78
+ def env_names
79
+ env = super || []
80
+ env = env.map { |str| "#{str}=#{ENV[str]}" }
81
+ env_file.concat(env)
82
+ end
83
+
84
+ def env
85
+ env = env_names.concat(super || [])
86
+ env.map { |str| escape(str) }.join(' ')
87
+ end
88
+
89
+ def env_file
90
+ return [] unless env_file?
91
+
92
+ error :env_file unless file?(super)
93
+ lines = read(super).split("\n").map(&:strip)
94
+ lines.reject(&:empty?)
95
+ end
96
+
97
+ def description
98
+ if description?
99
+ super
100
+ else
101
+ JSON.dump(
102
+ repo_slug:,
103
+ git_commit_sha: git_sha,
104
+ git_commit_message: git_commit_msg,
105
+ git_commit_author: git_author_name,
106
+ git_tag:,
107
+ branch: git_branch,
108
+ travis_build_id: ENV['TRAVIS_BUILD_ID'],
109
+ travis_build_number: ENV['TRAVIS_BUILD_NUMBER'],
110
+ pull_request: ENV['TRAVIS_PULL_REQUEST']
111
+ )
112
+ end
113
+ end
114
+
115
+ def export
116
+ env_vars.each { |key, value| ENV[key.to_s] = value.to_s }
117
+ end
118
+
119
+ def env_vars
120
+ {
121
+ CONVOX_HOST: host,
122
+ CONVOX_PASSWORD: password,
123
+ CONVOX_APP: app,
124
+ CONVOX_RACK: rack,
125
+ CONVOX_CLI: 'convox'
126
+ }
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Datica < Provider
6
+ register :datica
7
+
8
+ status :dev
9
+
10
+ register :datica, :catalyze
11
+
12
+ description sq(<<-STR)
13
+ tbd
14
+ STR
15
+
16
+ env :datica, :catalyze
17
+
18
+ opt '--target TARGET', 'The git remote repository to deploy to', required: true
19
+ opt '--path PATH', 'Path to files to deploy', default: '.'
20
+
21
+ needs :git
22
+
23
+ cmds checkout: 'git checkout HEAD',
24
+ add: 'git add %{path} --all --force',
25
+ commit: 'git commit -m "%{message}" --quiet',
26
+ push: 'git push --force %{target} HEAD:master'
27
+
28
+ msgs commit: 'Committing build files for deployment',
29
+ push: 'Deploying to Datica: %{target}'
30
+
31
+ def setup
32
+ commit if git_dirty? && !cleanup?
33
+ end
34
+
35
+ def deploy
36
+ shell :push
37
+ end
38
+
39
+ private
40
+
41
+ def commit
42
+ info :commit
43
+ shell :checkout
44
+ shell :add
45
+ shell :commit
46
+ end
47
+
48
+ def message
49
+ vars.empty? ? 'Local build' : 'Build #%s (%s) of %s@%s' % vars
50
+ end
51
+
52
+ VARS = %w[
53
+ TRAVIS_BUILD_NUMBER
54
+ TRAVIS_COMMIT
55
+ TRAVIS_REPO_SLUG
56
+ TRAVIS_BRANCH
57
+ ].freeze
58
+
59
+ def vars
60
+ @vars ||= ENV.values_at(*VARS).compact
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Ecr < Provider
6
+ status :alpha
7
+
8
+ full_name 'AWS ECR'
9
+
10
+ description sq(<<-STR)
11
+ tbd
12
+ STR
13
+
14
+ gem 'aws-sdk-ecr', '~> 1.0'
15
+ # gem 'docker-api', '~> 1.34'
16
+ gem 'json'
17
+
18
+ env :aws
19
+
20
+ opt '--access_key_id ID', 'AWS access key', required: true, secret: true
21
+ opt '--secret_access_key KEY', 'AWS secret access key', required: true, secret: true
22
+ opt '--account_id ID', 'AWS Account ID', note: 'Required if the repository is owned by a different account than the IAM user'
23
+ opt '--source SOURCE', 'Image to push', note: 'can be the id or the name and optional tag (e.g. mysql:5.6)', required: true
24
+ opt '--target TARGET', 'Comma separated list of partial repository names to push to', eg: 'image-one:tag,image-two', required: true
25
+ opt '--region REGION', 'Comma separated list of regions to push to', default: 'us-east-1'
26
+
27
+ msgs login: 'Using Access Key: %{access_key_id}',
28
+ auth_region: 'Authenticated with %{url}',
29
+ deploy: 'Pushing image %{source} to regions %{regions} as %{targets}',
30
+ image_pushed: 'Pushed image %{source} to region %{region} as %{target}'
31
+
32
+ cmds login: 'docker login -u %{user} -p %{pass} %{url}',
33
+ tag: 'docker tag %{source} %{url}/%{repo}:%{tag}',
34
+ push: 'docker push %{url}/%{repo}'
35
+
36
+ errs unknown_image: 'Image %{source} not found in the local Docker repository'
37
+
38
+ attr_reader :endpoints
39
+
40
+ def login
41
+ info :login
42
+ auth_regions
43
+ end
44
+
45
+ def validate
46
+ # TODO: validate the image exists locally
47
+ end
48
+
49
+ def deploy
50
+ info :deploy, regions: regions.join(', '), targets: targets.join(', ')
51
+ regions.product(targets).each do |region, target|
52
+ push(region, target)
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def push(region, target)
59
+ url, repo, tag = endpoints[region], *target.split(':')
60
+ shell :tag, url:, repo:, tag: tag || 'latest'
61
+ shell(:push, url:, repo:)
62
+ info :image_pushed, region:, target:
63
+ end
64
+
65
+ def auth_regions
66
+ @endpoints = regions.map { |region| [region, auth_region(region)] }.to_h
67
+ end
68
+
69
+ def auth_region(region)
70
+ token = auth_token(region)
71
+ user, pass = parse_auth(token.authorization_token)
72
+ url = token.proxy_endpoint
73
+ shell :login, user:, pass:, url:, echo: false, silent: true
74
+ info(:auth_region, url:)
75
+ strip_protocol(url)
76
+ end
77
+
78
+ def auth_token(region)
79
+ ecr(region).get_authorization_token(registry_ids).authorization_data[0]
80
+ end
81
+
82
+ def registry_ids
83
+ account_id? ? { registry_ids: [account_id] } : {}
84
+ end
85
+
86
+ def regions
87
+ # not sure how this was meant to be normalized when being a YAML list
88
+ region.split(',')
89
+ end
90
+
91
+ def targets
92
+ # not sure how this was meant to be normalized when being a YAML list
93
+ target.split(',')
94
+ end
95
+
96
+ def creds
97
+ @creds ||= only(opts, :access_key_id, :secret_access_key)
98
+ end
99
+
100
+ def ecr(region)
101
+ Aws::ECR::Client.new(region:, **creds)
102
+ end
103
+
104
+ def parse_auth(str)
105
+ user, pass = Base64.decode64(str).split(':')
106
+ [user, pass.chomp]
107
+ end
108
+
109
+ def strip_protocol(url)
110
+ url.sub(%r{^https?://}, '')
111
+ end
112
+
113
+ def progress(events)
114
+ events.split("\r\n").each do |event|
115
+ event = JSON.parse(event)
116
+ if e = event['error']
117
+ error e
118
+ elsif %w[Preparing Pushing].include?(event['status'])
119
+ nil
120
+ elsif event['id']
121
+ info "#{event['status']} [#{event['id']}]"
122
+ elsif event['status']
123
+ info event['status']
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end