Module: Dpl::Provider::Dsl

Includes:
Squiggle
Included in:
Dpl::Provider
Defined in:
lib/dpl/provider/dsl.rb

Overview

DSL available on the provider’s class body.

Use this to declare various features, requirements, and attributes that apply to your provider.

Instance Method Summary collapse

Methods included from Squiggle

#sq

Instance Method Details

#apt(package = nil, cmd = nil) ⇒ Object

Declare APT packages the provider depends on. These will be installed during the ‘before_install` stage using `apt-get install`, unless the given cmd is already available according to `which [cmd]`.

Parameters:

  • package (String) (defaults to: nil)

    Package name (required).

  • cmd (String) (defaults to: nil)

    Executable command installed by that package (optional, defaults to the package name).

Returns:

  • Previously declared apt packages if no arguments were given.



126
127
128
129
130
# File 'lib/dpl/provider/dsl.rb', line 126

def apt(package = nil, cmd = nil)
  return apt << [package, cmd].compact if package

  @apt ||= self == Provider ? [] : superclass.apt.dup
end

#apt?Boolean

Whether or not the provider depends on any apt packages.

Returns:

  • (Boolean)


133
134
135
# File 'lib/dpl/provider/dsl.rb', line 133

def apt?
  apt.any?
end

#cmds(cmds = nil) ⇒ Object

Declare shell commands used by the provider.

This exists so shell commands used can be separated from the implementation that runs them. This is useful in order to easily get an overview of all shell commands used by a provider on one hand, and in order to keep the implementation code focussed on the logic and functionality it provides, rather than the details of (potentially long winded) shell commands.

For example, a shell command declared on the class body like so:

```ruby
cmds git_push: 'git push -f %{target}'
```

can be used in the deploy stage like so:

```ruby
def deploy
  shell :git_push
end
```

The variable ‘%target` will be interpolated by calling the method `target` on the provider instance, so it will expect that method to exist.

commands.

Parameters:

  • cmds (Hash) (defaults to: nil)

    Commands to declare.

Returns:

  • Previously declared cmds if no argument is given.

See Also:



232
233
234
235
236
# File 'lib/dpl/provider/dsl.rb', line 232

def cmds(cmds = nil)
  return self.cmds.update(cmds) if cmds

  @cmds ||= self == Provider ? {} : superclass.cmds.dup
end

#description(str = nil) ⇒ Object

Summary of the provider’s functionality.



40
41
42
43
# File 'lib/dpl/provider/dsl.rb', line 40

def description(str = nil)
  str = str.strip if str
  super
end

#envObject

Declare an environment variable prefix to accept env vars as options

This method is defined in ‘Env::ClassMethods`.

Declares an environment variable prefix that imports environment variables into ‘opts` if they match declared options.

For example, with the following declaration on the class body:

```ruby
env :aws
opt '--access_key_id ID'
```

if the environment variable ‘AWS_ACCESS_KEY_ID` is set then the option `opts` will default to the value given on that variable (i.e. it could still be overwritten by the user by passing the `–access_key_id` option).



# File 'lib/dpl/provider/dsl.rb', line 67

#errs(errs = nil) ⇒ Object

Declare error messages that are raised if a shell command fails.

This exists so error messages can be separated from the implementation that uses them. This is useful in order to easily get an overview of all error messages used by a provider on one hand, and in order to keep the implementation code focussed on the logic and functionality it provides, rather than the details of (potentially long winded) error message strings.

The method ‘shell` will raise an error if the given shell command fails (returns a non-zero exit code) unless it is called with the option `assert: false`. The error message declared using `errs` will be used to raise with the eror.

For example, an error message declared on the class body like so:

```ruby
errs git_push: 'Failed to push to %{target}'
```

will be included to the raised error if the given command has failed:

```ruby
def deploy
  shell :git_push
end
```

The variable ‘%target` will be interpolated by calling the method `target` on the provider instance, so it will expect that method to exist.

See Dpl::Ctx::Bash#shell for more details on how to call shell commands.

Parameters:

  • errs (Hash) (defaults to: nil)

    Error messages to declare.

Returns:

  • Previously declared errs if no argument is given.



275
276
277
278
279
# File 'lib/dpl/provider/dsl.rb', line 275

def errs(errs = nil)
  return self.errs.update(errs) if errs

  @errs ||= self == Provider ? {} : superclass.errs.dup
end

#full_name(name = nil) ⇒ Object

Declare the full name of the provider. Required if the proper provider name does not match the provider’s class name.

Parameters:

  • name (String) (defaults to: nil)

    The provider’s full name

Returns:

  • The previously declared full name if no argument is given



30
31
32
# File 'lib/dpl/provider/dsl.rb', line 30

def full_name(name = nil)
  name ? @full_name = name : @full_name || self.name.split('::').last
end

#gem(name = nil, version = nil, opts = {}) ⇒ Object

Declare additional paths to Ruby gem source code that this provider requires.

These gems will be installed, and files required at runtime, during the ‘before_init` stage (not at install time, and/or load time), unless they are already installed.

Parameters:

  • name (String) (defaults to: nil)

    Ruby gem name (required)

  • version (String) (defaults to: nil)

    Ruby gem version (required)

  • opts (Hash) (defaults to: {})

    options

Options Hash (opts):

  • :require (Array<String>, String)

    A single path or a list of paths to source files to require from this Ruby gem. If not given the name of the gem will be assumed to be the path to be required.

Returns:

  • Previously declared gems if no arguments were given



150
151
152
153
154
# File 'lib/dpl/provider/dsl.rb', line 150

def gem(name = nil, version = nil, opts = {})
  return gem << [name, version, opts] if name

  @gem ||= self == Provider ? [] : superclass.gem.dup
end

#gem?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/dpl/provider/dsl.rb', line 156

def gem?
  gem.any?
end

#keep(*paths) ⇒ Object

Declare artifacts, such as executables during the ‘install` stage that need to be kept during `cleanup`.

Parameters:

  • paths (String)

    Paths to artifacts to keep during ‘cleanup`

Returns:

  • Previously declared artifacts to keep if no argument is given.



355
356
357
358
359
# File 'lib/dpl/provider/dsl.rb', line 355

def keep(*paths)
  return keep.concat(paths) if paths.any?

  @keep ||= self == Provider ? [] : superclass.keep.dup
end

#move(*paths) ⇒ Object



100
101
102
# File 'lib/dpl/provider/dsl.rb', line 100

def move(*paths)
  paths.any? ? @move = paths : @move ||= []
end

#msgs(msgs = nil) ⇒ Object

Declare other messages, such as info level log output, warnings, or custom strings, such as commit messages or descriptions.

This exists so various messages can be separated from the implementation that uses them. This is useful in order to easily get an overview of all error messages used by a provider on one hand, and in order to keep the implementation code focussed on the logic and functionality it provides, rather than the details of (potentially long winded) message strings.

For example, a message declared on the class body like so:

```ruby
msgs login: 'Logging in to the service %{full_name}'
```

could be used by the implementation like so:

```ruby
def login
  info :login
end
```

The variable ‘%#full_name` will be interpolated by calling the method `full_name` on the provider instance, so it will expect that method to exist.

It is possible to use msgs in order to declare and use custom messages, e.g. for the commit message on a commit a provider needs to create, or a description that needs to be included to an API call.

For example, a message declared on the class body like so:

```ruby
cmds git_commit: 'git commit -am "%{commit_msg}"'
msgs commit_msg: 'Commit build artifacts on build %{build_number}'
```

could be used by the implementation like so:

```ruby
def create_commit
  shell :git_commit
end

def commit_msg
  interpolate(msg(:commit_msg))
end
```

Note that in cases where builtin methods such as ‘shell`, `info`, `warn` etc. are not used the method `interpolate` needs to be used in order to interpolate variables used in a message (if any).

Parameters:

  • msgs (Hash) (defaults to: nil)

    Messages to declare.

Returns:

  • Previously declared msgs if no argument is given.



338
339
340
341
342
# File 'lib/dpl/provider/dsl.rb', line 338

def msgs(msgs = nil)
  return self.msgs.update(msgs) if msgs

  @msgs ||= self == Provider ? {} : superclass.msgs.dup
end

#needs(*features) ⇒ Object

Declare features that the provider needs.

Known features currently are:

  • ‘ssh_key`: Generates a temporary, per-build SSH key, and calls the methods `add_key` and `remove_key` if the provider defines them. This gives providers the opportunity to install this key on their service, and remove it after the deployment has finished.

  • ‘git`: Populates the git config.user and config.email attributes, unless present.

  • ‘git_http_user_agent`: Changes the environment variable `GIT_HTTP_USER_AGENT` to the one generated by `user_agent`. This gives providers the opportunity to identify and track coming from Travis CI and/or dpl.

Parameters:

  • features (Symbol)

    Features to activate for this provider

Returns:

  • Previously declared features needed if no argument is given.



378
379
380
381
382
# File 'lib/dpl/provider/dsl.rb', line 378

def needs(*features)
  return needs.concat(features) if features.any?

  @needs ||= self == Provider ? [] : superclass.needs.dup
end

#needs?(feature) ⇒ Boolean

Whether or not the provider has declared any features it needs.

Returns:

  • (Boolean)


385
386
387
# File 'lib/dpl/provider/dsl.rb', line 385

def needs?(feature)
  needs.include?(feature)
end

#node_js(*requirements) ⇒ Object



104
105
106
# File 'lib/dpl/provider/dsl.rb', line 104

def node_js(*requirements)
  runtimes(:node_js, requirements)
end

#npm(package = nil, cmd = nil) ⇒ Object

Declare NPM packages the provider depends on. These will be installed during the ‘before_install` stage using `npm install -g`, unless the given cmd is already available according to `which [cmd]`.

Parameters:

  • package (String) (defaults to: nil)

    Package name (required).

  • cmd (String) (defaults to: nil)

    Executable command installed by that package (optional, defaults to the package name).

Returns:

  • Previously declared NPM packages if no arguments are given.



168
169
170
171
172
# File 'lib/dpl/provider/dsl.rb', line 168

def npm(package = nil, cmd = nil)
  return npm << [package, cmd].compact if package

  @npm ||= self == Provider ? [] : superclass.npm.dup
end

#npm?Boolean

Whether or not the provider depends on any NPM packages.

Returns:

  • (Boolean)


175
176
177
# File 'lib/dpl/provider/dsl.rb', line 175

def npm?
  npm.any?
end

#optObject

Declare command line options that the provider supports.

This method is inherited from the base class ‘Cl::Cmd` which is defined in the Rubygem `Cl`. See the gem’s documentation for details on how to declare command line options.



96
97
98
# File 'lib/dpl/provider/dsl.rb', line 96

def path(path)
  ENV['PATH'] = "#{File.expand_path(path)}:#{ENV['PATH']}"
end

#path(path) ⇒ Object

Declare command line options that the provider supports.

This method is inherited from the base class ‘Cl::Cmd` which is defined in the Rubygem `Cl`. See the gem’s documentation for details on how to declare command line options.



96
97
98
# File 'lib/dpl/provider/dsl.rb', line 96

def path(path)
  ENV['PATH'] = "#{File.expand_path(path)}:#{ENV['PATH']}"
end

#pip(package = nil, cmd = nil, version = nil) ⇒ Object

Declare Python packages the provider depends on. These will be installed during the ‘before_install` stage using `pip install –user`. A previously installed package is uninstalled before that, but only if `version` was given.

Parameters:

  • package (String) (defaults to: nil)

    Package name (required).

  • cmd (String) (defaults to: nil)

    Executable command installed by that package (optional, defaults to the package name).

  • version (String) (defaults to: nil)

    Package version (optional).

Returns:

  • Previously declared Python packages if no arguments are given.



189
190
191
192
193
# File 'lib/dpl/provider/dsl.rb', line 189

def pip(package = nil, cmd = nil, version = nil)
  return pip << [package, cmd, version].compact if package

  @pip ||= self == Provider ? [] : superclass.pip.dup
end

#pip?Boolean

Whether or not the provider depends on any Python packages.

Returns:

  • (Boolean)


196
197
198
# File 'lib/dpl/provider/dsl.rb', line 196

def pip?
  pip.any?
end

#python(*requirements) ⇒ Object



108
109
110
# File 'lib/dpl/provider/dsl.rb', line 108

def python(*requirements)
  runtimes(:python, requirements)
end

#ruby_pre?(version) ⇒ Boolean

Returns:

  • (Boolean)


405
406
407
# File 'lib/dpl/provider/dsl.rb', line 405

def ruby_pre?(version)
  ruby_version < Gem::Version.new(version)
end

#ruby_versionObject



401
402
403
# File 'lib/dpl/provider/dsl.rb', line 401

def ruby_version
  Gem::Version.new(RUBY_VERSION)
end

#runtimes(name = nil, requirements = nil) ⇒ Object



112
113
114
115
116
# File 'lib/dpl/provider/dsl.rb', line 112

def runtimes(name = nil, requirements = nil)
  return @runtimes ||= [] unless name

  runtimes << [name, requirements]
end

#status(status = nil, msg = nil) ⇒ Object

Set or read the provider’s maturity status with an optional message



46
47
48
# File 'lib/dpl/provider/dsl.rb', line 46

def status(status = nil, msg = nil)
  status ? @status = Status.new(self, status, msg) : @status
end

#strs(strs = nil) ⇒ Object



344
345
346
347
348
# File 'lib/dpl/provider/dsl.rb', line 344

def strs(strs = nil)
  return self.strs.update(strs) if strs

  @strs ||= self == Provider ? {} : superclass.strs.dup
end

#summary(summary = nil) ⇒ Object

Summary of the provider’s functionality.



35
36
37
# File 'lib/dpl/provider/dsl.rb', line 35

def summary(summary = nil)
  summary ? super : @summary || "#{full_name} deployment provider"
end

#user_agent(*strs) ⇒ String

Generates a useragent string that identifies the current dpl version, and whether it runs int he context of Travis CI. Can include arbitrary extra strings or key value pairs (passed as String or Hash arguments).

Parameters:

  • strs (String(s) or Hash(es))

    Additional strings or key value pairs to include to the useragent string.

Returns:

  • (String)

    The useragent string



394
395
396
397
398
399
# File 'lib/dpl/provider/dsl.rb', line 394

def user_agent(*strs)
  strs.unshift "dpl/#{Dpl::VERSION}"
  strs.unshift 'travis/0.1.0' if ENV['TRAVIS']
  strs = strs.flat_map { |e| e.is_a?(Hash) ? e.map { |k, v| "#{k}/#{v}" } : e }
  strs.join(' ').gsub(/\s+/, ' ').strip
end

#vars(*vars) ⇒ Object

Declare additional variables available for interpolation.

Interpolating strings, when these exposed to the user, should safelist which variables are available. Options declared on a provider are always available, except if they are flags, arrays, internal, or secrets. This method can be used to allow additional variables, e.g. from the git context.



57
58
59
60
61
62
63
64
65
# File 'lib/dpl/provider/dsl.rb', line 57

def vars(*vars)
  return self.vars.concat(vars) if vars.any?
  return @vars if instance_variable_defined?(:@vars)

  vars = superclass.respond_to?(:vars) ? superclass.vars : []
  reject = %i[flag array internal interpolate secret]
  opts = reject.inject(self.opts) { |options, attr| options.reject(&:"#{attr}?") }
  @vars = vars.dup.concat(opts.map(&:name)).uniq.sort - [:strategy]
end