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.
Files changed (140) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +74 -0
  3. data/CONTRIBUTING.md +392 -0
  4. data/Gemfile +17 -3
  5. data/Gemfile.lock +373 -0
  6. data/LICENSE +16 -19
  7. data/NOTES.md +275 -0
  8. data/README.md +1977 -707
  9. data/Rakefile +2 -2
  10. data/bin/dpl +7 -3
  11. data/lib/dpl.rb +20 -0
  12. data/lib/dpl/assets/atlas/install +19 -0
  13. data/lib/dpl/assets/dpl/README.erb.md +133 -0
  14. data/lib/dpl/assets/dpl/git_ssh +2 -0
  15. data/lib/dpl/assets/git/detect_private_key +8 -0
  16. data/lib/dpl/assets/hephy/filter_log +3 -0
  17. data/lib/dpl/assets/pypi/install +4 -0
  18. data/lib/dpl/assets/scalingo/install +6 -0
  19. data/lib/dpl/cli.rb +36 -48
  20. data/lib/dpl/ctx.rb +2 -0
  21. data/lib/dpl/ctx/bash.rb +543 -0
  22. data/lib/dpl/ctx/test.rb +242 -0
  23. data/lib/dpl/helper/assets.rb +36 -0
  24. data/lib/dpl/helper/cmd.rb +167 -0
  25. data/lib/dpl/helper/config_file.rb +47 -0
  26. data/lib/dpl/helper/env.rb +39 -0
  27. data/lib/dpl/helper/interpolate.rb +126 -0
  28. data/lib/dpl/helper/memoize.rb +20 -0
  29. data/lib/dpl/helper/squiggle.rb +22 -0
  30. data/lib/dpl/helper/zip.rb +69 -0
  31. data/lib/dpl/provider.rb +562 -234
  32. data/lib/dpl/provider/dsl.rb +369 -0
  33. data/lib/dpl/provider/examples.rb +128 -0
  34. data/lib/dpl/provider/status.rb +59 -0
  35. data/lib/dpl/providers.rb +40 -0
  36. data/lib/dpl/providers/anynines.rb +65 -0
  37. data/lib/dpl/providers/atlas.rb +49 -0
  38. data/lib/dpl/providers/azure_web_apps.rb +59 -0
  39. data/lib/dpl/providers/bintray.rb +313 -0
  40. data/lib/dpl/providers/bluemixcloudfoundry.rb +92 -0
  41. data/lib/dpl/providers/boxfuse.rb +48 -0
  42. data/lib/dpl/providers/cargo.rb +19 -0
  43. data/lib/dpl/providers/chef_supermarket.rb +128 -0
  44. data/lib/dpl/providers/cloud66.rb +40 -0
  45. data/lib/dpl/providers/cloudfiles.rb +56 -0
  46. data/lib/dpl/providers/cloudfoundry.rb +81 -0
  47. data/lib/dpl/providers/codedeploy.rb +179 -0
  48. data/lib/dpl/providers/datica.rb +60 -0
  49. data/lib/dpl/providers/elasticbeanstalk.rb +195 -0
  50. data/lib/dpl/providers/engineyard.rb +107 -0
  51. data/lib/dpl/providers/firebase.rb +41 -0
  52. data/lib/dpl/providers/gae.rb +74 -0
  53. data/lib/dpl/providers/gcs.rb +105 -0
  54. data/lib/dpl/providers/hackage.rb +47 -0
  55. data/lib/dpl/providers/hephy.rb +101 -0
  56. data/lib/dpl/providers/heroku.rb +111 -0
  57. data/lib/dpl/providers/heroku/api.rb +119 -0
  58. data/lib/dpl/providers/heroku/git.rb +50 -0
  59. data/lib/dpl/providers/lambda.rb +202 -0
  60. data/lib/dpl/providers/launchpad.rb +74 -0
  61. data/lib/dpl/providers/netlify.rb +30 -0
  62. data/lib/dpl/providers/npm.rb +88 -0
  63. data/lib/dpl/providers/openshift.rb +46 -0
  64. data/lib/dpl/providers/opsworks.rb +142 -0
  65. data/lib/dpl/providers/packagecloud.rb +190 -0
  66. data/lib/dpl/providers/pages.rb +17 -0
  67. data/lib/dpl/providers/pages/api.rb +102 -0
  68. data/lib/dpl/providers/pages/git.rb +251 -0
  69. data/lib/dpl/providers/puppetforge.rb +44 -0
  70. data/lib/dpl/providers/pypi.rb +120 -0
  71. data/lib/dpl/providers/releases.rb +214 -0
  72. data/lib/dpl/providers/rubygems.rb +89 -0
  73. data/lib/dpl/providers/s3.rb +243 -0
  74. data/lib/dpl/providers/scalingo.rb +63 -0
  75. data/lib/dpl/providers/script.rb +28 -0
  76. data/lib/dpl/providers/snap.rb +59 -0
  77. data/lib/dpl/providers/surge.rb +55 -0
  78. data/lib/dpl/providers/testfairy.rb +93 -0
  79. data/lib/dpl/providers/transifex.rb +66 -0
  80. data/lib/dpl/support/aws_sdk_patch.rb +23 -0
  81. data/lib/dpl/support/gems.rb +69 -0
  82. data/lib/dpl/support/gstore_patch.rb +6 -0
  83. data/lib/dpl/support/version.rb +83 -0
  84. data/lib/dpl/version.rb +2 -2
  85. metadata +98 -169
  86. data/.coveralls.yml +0 -1
  87. data/.github/CONTRIBUTING.md +0 -173
  88. data/.github/stale.yml +0 -53
  89. data/.gitignore +0 -13
  90. data/.rspec +0 -2
  91. data/.travis.yml +0 -56
  92. data/dpl-anynines.gemspec +0 -3
  93. data/dpl-atlas.gemspec +0 -3
  94. data/dpl-azure_webapps.gemspec +0 -3
  95. data/dpl-bintray.gemspec +0 -3
  96. data/dpl-bitballoon.gemspec +0 -3
  97. data/dpl-bluemix_cloud_foundry.gemspec +0 -3
  98. data/dpl-boxfuse.gemspec +0 -3
  99. data/dpl-cargo.gemspec +0 -3
  100. data/dpl-catalyze.gemspec +0 -3
  101. data/dpl-chef_supermarket.gemspec +0 -20
  102. data/dpl-cloud66.gemspec +0 -3
  103. data/dpl-cloud_files.gemspec +0 -3
  104. data/dpl-cloud_foundry.gemspec +0 -3
  105. data/dpl-code_deploy.gemspec +0 -3
  106. data/dpl-deis.gemspec +0 -3
  107. data/dpl-elastic_beanstalk.gemspec +0 -3
  108. data/dpl-engine_yard.gemspec +0 -3
  109. data/dpl-firebase.gemspec +0 -3
  110. data/dpl-gae.gemspec +0 -3
  111. data/dpl-gcs.gemspec +0 -3
  112. data/dpl-hackage.gemspec +0 -3
  113. data/dpl-hephy.gemspec +0 -3
  114. data/dpl-heroku.gemspec +0 -3
  115. data/dpl-lambda.gemspec +0 -3
  116. data/dpl-launchpad.gemspec +0 -3
  117. data/dpl-npm.gemspec +0 -3
  118. data/dpl-openshift.gemspec +0 -3
  119. data/dpl-ops_works.gemspec +0 -3
  120. data/dpl-packagecloud.gemspec +0 -3
  121. data/dpl-pages.gemspec +0 -3
  122. data/dpl-puppet_forge.gemspec +0 -3
  123. data/dpl-pypi.gemspec +0 -3
  124. data/dpl-releases.gemspec +0 -8
  125. data/dpl-rubygems.gemspec +0 -3
  126. data/dpl-s3.gemspec +0 -3
  127. data/dpl-scalingo.gemspec +0 -3
  128. data/dpl-script.gemspec +0 -3
  129. data/dpl-snap.gemspec +0 -3
  130. data/dpl-surge.gemspec +0 -3
  131. data/dpl-testfairy.gemspec +0 -3
  132. data/dpl-transifex.gemspec +0 -3
  133. data/dpl.gemspec +0 -3
  134. data/gemspec_helper.rb +0 -51
  135. data/lib/dpl/error.rb +0 -3
  136. data/notes/engine_yard.md +0 -1
  137. data/notes/heroku.md +0 -3
  138. data/spec/cli_spec.rb +0 -36
  139. data/spec/provider_spec.rb +0 -191
  140. data/spec/spec_helper.rb +0 -20
@@ -0,0 +1,17 @@
1
+ module Dpl
2
+ module Providers
3
+ class Pages < Provider
4
+ def self.new(ctx, args)
5
+ return super unless registry_key.to_sym == :pages
6
+ arg = args.detect { |arg| arg.include? '--strategy' }
7
+ strategy = arg ? arg.split('=', 2).last : 'git'
8
+ Provider[:"pages:#{strategy}"].new(ctx, args)
9
+ end
10
+
11
+ opt '--strategy NAME', 'GitHub Pages deployment strategy', default: 'git', enum: %w(api git), internal: true
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'dpl/providers/pages/git'
17
+ require 'dpl/providers/pages/api'
@@ -0,0 +1,102 @@
1
+ require 'timeout'
2
+
3
+ module Dpl
4
+ module Providers
5
+ class Pages
6
+ class Api < Pages
7
+ PAGES_PREVIEW_MEDIA_TYPE = 'application/vnd.github.mister-fantastic-preview+json'
8
+
9
+ # suppress warnings about preview API
10
+ ENV['OCTOKIT_SILENT'] = 'true'
11
+
12
+ TIMEOUTS = {
13
+ timeout: 180,
14
+ open_timeout: 180
15
+ }
16
+
17
+ gem 'octokit', '~> 4.14.0'
18
+
19
+ status :alpha
20
+
21
+ full_name 'GitHub Pages (API)'
22
+
23
+ description sq(<<-str)
24
+ This provider requests GitHub Pages build for the repository given by
25
+ the `--repo` flag, or the current one, if the flag is not given.
26
+ Note that `dpl` does not perform any check about the fitness of the request;
27
+ it is assumed that the target repository (and the branch that GitHub Pages is
28
+ configured to use) is ready for building.
29
+ For example, if your GitHub Pages is configured to use `gh-pages` but the
30
+ deployment is run on the `master` branch, you would have to ensure that the
31
+ `gh-pages` would be updated accordingly during the build.
32
+ str
33
+
34
+ opt '--repo SLUG', 'GitHub repo slug', default: :repo_slug
35
+ opt '--github_token TOKEN', 'GitHub oauth token with repo permission', required: true, secret: true
36
+
37
+ msgs pages_not_found: 'GitHub Pages not found for %{slug}. ' \
38
+ 'Given token has insufficient scope (\'repo\' or \'public_repo\'), ' \
39
+ 'or GitHub Pages is not enabled for this repo (see https://github.com/%{slug}/settings)',
40
+ build_pages_request_timeout: 'GitHub Pages build request timed out',
41
+ deploy_start: 'Requesting GitHub Pages build using API'
42
+
43
+ def validate
44
+ error :pages_not_found unless pages_enabled?
45
+ end
46
+
47
+ def deploy
48
+ info :deploy_start
49
+
50
+ api.request_page_build slug
51
+
52
+ response = api.pages slug
53
+ logger.debug response
54
+
55
+ Timeout::timeout(30) do
56
+ until response.status == 'built'
57
+ response = api.pages slug
58
+ logger.debug response
59
+ sleep 1
60
+ end
61
+ end
62
+
63
+ latest_pages_build = api.latest_pages_build slug
64
+ if msg = latest_pages_build.error.message
65
+ error "Build failed: #{msg}"
66
+ end
67
+
68
+ info "Pages deployed to #{response.html_url}, using commit #{latest_pages_build.commit}"
69
+ logger.debug latest_pages_build
70
+
71
+ rescue Octokit::Forbidden => fb
72
+ error fb.message
73
+ rescue Timeout::Error => to
74
+ error :build_pages_request_timeout
75
+ end
76
+
77
+ private
78
+
79
+ def slug
80
+ repo || repo_slug
81
+ end
82
+
83
+ def api
84
+ ::Octokit.default_media_type = PAGES_PREVIEW_MEDIA_TYPE unless @api
85
+
86
+ @api ||= Octokit::Client.new(**creds, auto_paginate: true, connection_options: { request: TIMEOUTS })
87
+ end
88
+
89
+ def creds
90
+ { access_token: github_token }
91
+ end
92
+
93
+ def pages_enabled?
94
+ api.pages slug
95
+ rescue Octokit::NotFound => e
96
+ false
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,251 @@
1
+ module Dpl
2
+ module Providers
3
+ class Pages
4
+ class Git < Pages
5
+ status :alpha
6
+
7
+ full_name 'GitHub Pages'
8
+
9
+ description sq(<<-str)
10
+ tbd
11
+ str
12
+
13
+ gem 'octokit', '~> 4.14.0'
14
+ gem 'public_suffix', '~> 3.0.3'
15
+
16
+ required :github_token, :deploy_key
17
+
18
+ opt '--repo SLUG', 'Repo slug', default: :repo_slug
19
+ opt '--github_token TOKEN', 'GitHub oauth token with repo permission', secret: true
20
+ opt '--deploy_key PATH', 'Path to a file containing a private deploy key with write access to the repository', see: 'https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys'
21
+ opt '--target_branch BRANCH', 'Branch to push force to', default: 'gh-pages'
22
+ opt '--keep_history', 'Create incremental commit instead of doing push force', default: true
23
+ opt '--commit_message MSG', default: 'Deploy %{project_name} to %{url}:%{target_branch}'
24
+ opt '--allow_empty_commit', 'Allow an empty commit to be created', requires: :keep_history
25
+ opt '--verbose', 'Be verbose about the deploy process'
26
+ opt '--local_dir DIR', 'Directory to push to GitHub Pages', default: '.'
27
+ opt '--fqdn FQDN', 'Write the given domain name to the CNAME file'
28
+ opt '--project_name NAME', 'Used in the commit message only (defaults to fqdn or the current repo slug)'
29
+ opt '--name NAME', 'Committer name', note: 'defaults to the current git commit author name'
30
+ opt '--email EMAIL', 'Committer email', note: 'defaults to the current git commit author email'
31
+ opt '--committer_from_gh', 'Use the token\'s owner name and email for the commit', requires: :github_token
32
+ opt '--deployment_file', 'Enable creation of a deployment-info file'
33
+ opt '--github_url URL', default: 'github.com'
34
+
35
+ needs :git
36
+
37
+ msgs login: 'Authenticated as %s',
38
+ invalid_token: 'The provided GitHub token is invalid (error: %s)',
39
+ insufficient_scopes: 'Dpl does not have permission to access %{url} using the provided GitHub token. Please make sure the token have the repo or public_repo scope.',
40
+ setup_deploy_key: 'Moving deploy key %{deploy_key} to %{path}',
41
+ check_deploy_key: 'Checking deploy key',
42
+ deploy: 'Deploying branch %{target_branch} to %{github_url}',
43
+ keep_history: 'The deployment is configured to preserve the target branch if it exists on remote.',
44
+ work_dir: 'Using temporary work directory %{work_dir}',
45
+ committer_from_gh: 'The repo is configured to use committer user and email.',
46
+ setup_dir: 'The source dir for deployment is %s',
47
+ git_clone: 'Cloning the branch %{target_branch} from the remote repo',
48
+ git_init: 'Initializing local git repo',
49
+ git_checkout: 'Checking out orphan branch %{target_branch}',
50
+ copy_files: 'Copying %{src_dir} contents to %{work_dir}',
51
+ git_config: 'Configuring git committer to be %{name} <%{email}>',
52
+ prepare: 'Preparing to deploy %{target_branch} branch to gh-pages',
53
+ git_push: 'Pushing to %{url}'
54
+
55
+ cmds git_clone: 'git clone --quiet --branch="%{target_branch}" --depth=1 "%{remote_url}" . > /dev/null 2>&1',
56
+ git_init: 'git init .',
57
+ git_checkout: 'git checkout --orphan "%{target_branch}"',
58
+ check_deploy_key: 'ssh -i %{key} -T git@github.com 2>&1 | grep successful > /dev/null',
59
+ copy_files: 'rsync -rl --exclude .git --delete "%{src_dir}/" .',
60
+ git_config_email: 'git config user.email %{quoted_email}',
61
+ git_config_name: 'git config user.name %{quoted_name}',
62
+ deployment_file: 'touch "deployed at %{now} by %{name}"',
63
+ cname: 'echo "%{fqdn}" > CNAME',
64
+ git_add: 'git add -A .',
65
+ git_commit_hook: 'cp %{path} .git/hooks/pre-commit',
66
+ git_commit: 'git commit %{git_commit_opts} -qm %{quoted_commit_message}',
67
+ git_show: 'git show --stat-count=10 HEAD',
68
+ git_push: 'git push%{git_push_opts} --quiet "%{remote_url}" "%{target_branch}":"%{target_branch}" > /dev/null 2>&1'
69
+
70
+ errs copy_files: 'Failed to copy %{src_dir}.',
71
+ check_deploy_key: 'Failed to authenticate using the deploy key',
72
+ git_init: 'Failed to create new git repo',
73
+ git_checkout: 'Failed to create the orphan branch',
74
+ git_push: 'Failed to push the build to %{url}:%{target_branch}'
75
+
76
+ def login
77
+ github_token? ? login_token : setup_deploy_key
78
+ end
79
+
80
+ def setup
81
+ info :setup_dir, src_dir
82
+ info :committer_from_gh if committer_from_gh?
83
+ info :git_config
84
+ end
85
+
86
+ def prepare
87
+ info :deploy
88
+ info :keep_history if keep_history?
89
+ debug :work_dir
90
+ Dir.chdir(work_dir)
91
+ end
92
+
93
+ def deploy
94
+ git_clone? ? git_clone : git_init
95
+ copy_files
96
+ git_config
97
+ git_commit
98
+ git_push
99
+ git_status if verbose?
100
+ end
101
+
102
+ private
103
+
104
+ def login_token
105
+ user.login
106
+ info :login, user.login
107
+ error :insufficient_scopes unless sufficient_scopes?
108
+ rescue Octokit::Unauthorized => e
109
+ error :invalid_token, e.message
110
+ end
111
+
112
+ def setup_deploy_key
113
+ path = '~/.dpl/deploy_key'
114
+ info :setup_deploy_key, path: path
115
+ mv deploy_key, path
116
+ chmod 0600, path
117
+ setup_git_ssh path
118
+ shell :check_deploy_key, key: path
119
+ end
120
+
121
+ def git_clone?
122
+ keep_history? && git_branch_exists?
123
+ end
124
+
125
+ def git_clone
126
+ shell :git_clone, echo: false
127
+ end
128
+
129
+ def git_init
130
+ shell :git_init
131
+ shell :git_checkout
132
+ end
133
+
134
+ def copy_files
135
+ shell :copy_files
136
+ end
137
+
138
+ def git_config
139
+ shell :git_config_name, echo: false
140
+ shell :git_config_email, echo: false
141
+ end
142
+
143
+ def git_commit
144
+ info :prepare
145
+ shell :git_commit_hook, path: asset(:git, :detect_private_key).path, echo: false if deploy_key?
146
+ shell :deployment_file if deployment_file?
147
+ shell :cname if fqdn?
148
+ shell :git_add
149
+ shell :git_commit
150
+ shell :git_show
151
+ end
152
+
153
+ def git_push
154
+ shell :git_push, echo: false
155
+ end
156
+
157
+ def git_status
158
+ shell 'git status'
159
+ end
160
+
161
+ def git_branch_exists?
162
+ git_ls_remote?(remote_url, target_branch)
163
+ end
164
+
165
+ def git_commit_opts
166
+ ' --allow-empty' if allow_empty_commit?
167
+ end
168
+
169
+ def git_push_opts
170
+ ' --force' unless keep_history?
171
+ end
172
+
173
+ def name
174
+ str = super if name?
175
+ str ||= user.name if committer_from_gh?
176
+ str ||= git_author_name
177
+ str = "#{str} (via Travis CI)" if ENV['TRAVIS'] && !name?
178
+ str
179
+ end
180
+ memoize :name
181
+
182
+ def email
183
+ str = super if email?
184
+ str ||= user.email if committer_from_gh?
185
+ str || git_author_email
186
+ end
187
+ memoize :email
188
+
189
+ def commit_message
190
+ interpolate(super)
191
+ end
192
+
193
+ def project_name
194
+ super || fqdn || repo_slug
195
+ end
196
+
197
+ def sufficient_scopes?
198
+ api.scopes.include?('public_repo') || api.scopes.include?('repo')
199
+ end
200
+
201
+ def remote_url
202
+ github_token? ? https_url_with_token : git_url
203
+ end
204
+
205
+ def https_url_with_token
206
+ "https://#{github_token}@#{url}"
207
+ end
208
+
209
+ def git_url
210
+ "git@#{github_url}:#{slug}.git"
211
+ end
212
+
213
+ def url
214
+ "#{github_url}/#{slug}.git"
215
+ end
216
+
217
+ def slug
218
+ repo || repo_slug
219
+ end
220
+
221
+ def user
222
+ @user ||= api.user
223
+ end
224
+
225
+ def src_dir
226
+ @src_dir ||= expand(local_dir)
227
+ end
228
+
229
+ def work_dir
230
+ @work_dir ||= tmp_dir
231
+ end
232
+
233
+ def api
234
+ @api ||= Octokit::Client.new(access_token: github_token, api_endpoint: api_endpoint)
235
+ end
236
+
237
+ def api_endpoint
238
+ github_url == 'github.com' ? 'https://api.github.com/' : "https://#{github_url}/api/v3/"
239
+ end
240
+
241
+ def now
242
+ Time.now
243
+ end
244
+
245
+ def debug(*args)
246
+ info *args if verbose?
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,44 @@
1
+ module Dpl
2
+ module Providers
3
+ class Puppetforge < Provider
4
+ status :alpha
5
+
6
+ full_name 'Puppet Forge'
7
+
8
+ description sq(<<-str)
9
+ tbd
10
+ str
11
+
12
+ gem 'puppet', '~> 5.5.14', require: 'puppet/face'
13
+ gem 'puppet-blacksmith', '~> 3.3.1', require: 'puppet_blacksmith'
14
+
15
+ opt '--username NAME', 'Puppet Forge user name', required: true, alias: :user
16
+ opt '--password PASS', 'Puppet Forge password', required: true, secret: true
17
+ opt '--url URL', 'Puppet Forge URL to deploy to', default: 'https://forgeapi.puppetlabs.com/'
18
+
19
+ msgs upload: 'Uploading to Puppet Forge %s/%s'
20
+
21
+ def validate
22
+ file.metadata
23
+ end
24
+
25
+ def deploy
26
+ build
27
+ info :upload, forge.username, file.name
28
+ forge.push!(file.name)
29
+ end
30
+
31
+ def file
32
+ @file ||= Blacksmith::Modulefile.new
33
+ end
34
+
35
+ def build
36
+ Puppet::Face['module', :current].build('./')
37
+ end
38
+
39
+ def forge
40
+ @forge ||= Blacksmith::Forge.new(username, password, url)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,120 @@
1
+ module Dpl
2
+ module Providers
3
+ class Pypi < Provider
4
+ status :alpha
5
+
6
+ full_name 'PyPI'
7
+
8
+ description sq(<<-str)
9
+ tbd
10
+ str
11
+
12
+ env :pypi
13
+
14
+ VERSION = /\A\d+(?:\.\d+)*\z/
15
+
16
+ opt '--username NAME', 'PyPI Username', required: true, alias: :user
17
+ opt '--password PASS', 'PyPI Password', required: true, secret: true
18
+ opt '--server SERVER', 'Release to a different index', default: 'https://upload.pypi.org/legacy/'
19
+ opt '--distributions DISTS', 'Space-separated list of distributions to be uploaded to PyPI', default: 'sdist'
20
+ opt '--docs_dir DIR', 'Path to the directory to upload documentation from', default: 'build/docs'
21
+ opt '--skip_existing', 'Do not overwrite an existing file with the same name on the server.'
22
+ opt '--upload_docs', 'Upload documentation', default: false, type: :boolean, note: 'most PyPI servers, including upload.pypi.org, do not support uploading documentation'
23
+ opt '--twine_check', 'Whether to run twine check', default: true
24
+ opt '--remove_build_dir', 'Remove the build dir after the upload', default: true
25
+ opt '--setuptools_version VER', format: VERSION
26
+ opt '--twine_version VER', format: VERSION
27
+ opt '--wheel_version VER', format: VERSION
28
+
29
+ msgs login: 'Authenticated as %{username}',
30
+ upload_docs: 'Uploading documentation (skip using "skip_upload_docs: true")'
31
+
32
+ cmds setup_py: 'python setup.py %{distributions}',
33
+ twine_check: 'twine check dist/*',
34
+ twine_upload: 'twine upload %{skip_existing_option} -r pypi dist/*',
35
+ rm_dist: 'rm -rf dist/*',
36
+ upload_docs: 'python setup.py upload_docs %{docs_dir_option} -r %{server}'
37
+
38
+ errs install: 'Failed to install pip, setuptools, twine or wheel.',
39
+ setup_py: 'setup.py failed',
40
+ twine_check: 'Twine check failed',
41
+ twine_upload: 'Twine upload failed.',
42
+ upload_docs: 'Uploading docs failed.'
43
+
44
+
45
+ def install
46
+ script :install
47
+ end
48
+
49
+ def login
50
+ write_config
51
+ info :login
52
+ end
53
+
54
+ def setup
55
+ shell :setup_py
56
+ end
57
+
58
+ def validate
59
+ shell :twine_check if twine_check?
60
+ end
61
+
62
+ def deploy
63
+ shell :twine_upload
64
+ upload_docs if upload_docs?
65
+ shell :rm_dist if remove_build_dir?
66
+ end
67
+
68
+ private
69
+
70
+ PYPIRC = sq(<<-rc)
71
+ [distutils]
72
+ index-servers = pypi
73
+ pypi
74
+ [pypi]
75
+ repository: %{server}
76
+ username: %{username}
77
+ password: %{password}
78
+ rc
79
+
80
+ def write_config
81
+ write_file('~/.pypirc', pypirc)
82
+ end
83
+
84
+ def pypirc
85
+ interpolate(PYPIRC, opts, secure: true)
86
+ end
87
+
88
+ def upload_docs
89
+ info :upload_docs
90
+ shell :upload_docs
91
+ end
92
+
93
+ def skip_existing_option
94
+ '--skip-existing' if skip_existing?
95
+ end
96
+
97
+ def docs_dir_option
98
+ '--upload-dir ' + docs_dir if docs_dir
99
+ end
100
+
101
+ def setuptools_arg
102
+ version_arg(:setuptools)
103
+ end
104
+
105
+ def twine_arg
106
+ version_arg(:twine)
107
+ end
108
+
109
+ def wheel_arg
110
+ version_arg(:wheel)
111
+ end
112
+
113
+ def version_arg(name)
114
+ arg = name.to_s
115
+ arg << "==#{send(:"#{name}_version")}" if send(:"#{name}_version") =~ VERSION
116
+ arg
117
+ end
118
+ end
119
+ end
120
+ end