travis_dpl_test 2.0.3.beta.4.ror

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.
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