module QB

Definitions

Namespace

Declarations

Definitions

Namespace

Namespace

Definitions

Declarations

Declarations

Namespace

Namespace

This class doesn't do anything… at least not yet. It serves as a marker for classes that are data (which must be {NRSER::Props}).

@example Testing Membership

object.is_a? QB::Data

Abstract base class for immutable data classes. Based off {Hamster::Hash}.

Using {Hamster::Hash}

@todo document QB::Docker::CLI class.

@todo document Docker::Image class.

Image name.

Input format will be one of:

  1. name

  2. repository/name

  3. registry_server:port/name

Namespace

Definitions

Declarations

Namespace

Namespace

Namespace

Definitions

Namespace

An attempt to unify NPM and Gem version schemes to a reasonable extend, and hopefully cover whatever else the cat may drag in.

Intended to be immutable for practical purposes.

Based off [SemVer 2][] and - in particular - the [Node semver package][] interpretation / implementation, though we don't use that package at all at this point (sub-shelling out became too expensive, and explorations into Ruby Racer, etc. didn't pan out (don't remember exactly why)).

[SemVer 2]: semver.org/spec/v2.0.0.html [Node semver package]: www.npmjs.com/package/semver

Let's start the show with some fun…

Terminology


Working off what's in the [SemVer 2][] spec as much as possible.

We're going to start from the bottom and build up…

### Identifiers

Identifiers ([SemVer 2][] spec term) are the atoms of the version: the values that will not be further divided.

They come in two types (my terms):

  1. *Number Identifiers*

    Non-negative integers. Their string representations may not include leading zeros.

  2. *Name Identifiers*

    Non-empty strings that contain only `a-z`, `A-Z` and `-` and are not number identifiers.

All identifiers must be exclusively one type or the other.

Parse and validate identifiers with {QB::Package::Version::From.identifier_for}.

### Segments

Segments (my term) are sequences of zero or more identifiers.

In string representation, the identifiers in a segment are separated by the dot (`.`) character.

> NOTE > > As identifiers can not be empty, a segment's string representation may not > start or end with `.`, and may not contain consecutive `.`.

There are three types of segments:

  1. *Release Segment*

    Composed of exactly three *number identifiers*:

    1. Major

    2. Minor

    3. Patch

    > NOTE > > Ruby's Gem version format doesn't require anything but the major > identifier, in which case we default missing ones to `0`.

  2. *Prerelease Segment*

    Composed of zero or more identifiers - number or name, in any order.

  3. *Build Segment*

    Composed of zero or more identifiers - number or name, in any order.

### Versions

A version is exactly one release segment, prerelease segment and build segment, in which the prerelease and build segments may be empty as noted above.

In SemVer string representation, the release segment is always present, and a non-empty prerelease segment may follow it, separated by a `-` character.

A non-empty build segment may follow those, separated by a `+` character.

Encapsulate information about a Git repository and expose useful operations as instance methods.

The main entry point is {QB::Repo::Git.from_path}, which creates a

Namespace

Declarations

Definitions

Namespace

Python-style decorators using the `method_decorators` gem.

@see rubygems.org/gems/method_decorators

@example Usage

class A
  extend MethodDecorators

  +QB::Util::Decorators::EnumFor
  def get_stuff
    yield 1
    yield 2
    yield 3
  end

end

A.new.get_stuff.class
# => Enumerator

Declarations

Constants

GEM_NAME

The gem's name.

@return [String]

GEM_ROLES_DIR

Absolute path to `//roles`.

@return [Pathname]

MIN_ANSIBLE_VERSION

Minimum version of Ansible required. Encoded as a {Gem::Version} so we can compare it.

@return [Gem::Version]

ROOT

Absolute path to the gem's root directory.

@return [Pathname]

USER_ROLES_DIR

Absolute path to the user's roles dir, which is `~/.ansible/roles`.

@return [Pathname]

VERSION

String version read from `//VERSION`

@return [String]

YAML_FILE_EXTS

Extensions we recognize for YAML files.

See {Util.find_yaml_file!}.

@return [::Array<::String>]

Public Class Methods

ansible_version() click to toggle source

@return [Gem::Version]

the Ansible executable version parsed into a Gem version so we can
compare it.
# File lib/qb/version.rb, line 77
  def self.ansible_version
    out = Cmds.out! 'ansible --version'
    version_str = out[/ansible\ ([\d\.]+)/, 1]
    
    if version_str.nil?
      raise NRSER.dedent <<-END
        could not parse ansible version from `ansible --version` output:
        
        #{ out }
      END
    end
    
    Gem::Version.new version_str
  end
ask_for_options(role:, options: options.select { |opt| opt.value.nil? }) click to toggle source
# File lib/qb/cli.rb, line 142
def self.ask_for_options role:, options:
  options.select { |opt| opt.value.nil? }.each { |option|
    ask_for_option role: role, option: option
  }
end
check_ansible_version() click to toggle source

Check that the Ansible version is not less than {QB::MIN_ANSIBLE_VERSION}.

@raise [QB::AnsibleVersionError]

If the version of Ansible found is less than {QB::MIN_ANSIBLE_VERSION}.
# File lib/qb/version.rb, line 98
  def self.check_ansible_version
    if ansible_version < QB::MIN_ANSIBLE_VERSION
      raise QB::AnsibleVersionError, NRSER.squish(
        <<-END
          QB #{ QB::VERSION } requires Ansible #{ QB::MIN_ANSIBLE_VERSION },
          found version #{ version_str } at #{ `which ansible` }
        END
      )
    end
  end
debug(*args) click to toggle source

Support for the old custom debug logging, now sent to {SemanticLogger}.

# File lib/qb.rb, line 68
def self.debug *args
  if args[0].is_a? String
    logger.debug *args
  else
    # De-array if there's only one arg
    args = args[0] if args.length == 1
    # And send the args to SM as the payload
    logger.debug payload: args
  end
end
dynamic_width() click to toggle source

Calculate the dynamic width of the terminal

# File lib/qb/cli.rb, line 172
def self.dynamic_width
  @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
end
dynamic_width_stty() click to toggle source
# File lib/qb/cli.rb, line 177
def self.dynamic_width_stty
  `stty size 2>/dev/null`.split[1].to_i
end
dynamic_width_tput() click to toggle source
# File lib/qb/cli.rb, line 182
def self.dynamic_width_tput
  `tput cols 2>/dev/null`.to_i
end
gem_version() click to toggle source

Get the {Gem::Version} parse of {QB::VERSION}.

@return [Gem::Version]

# File lib/qb/version.rb, line 68
def self.gem_version
  Gem::Version.new VERSION
end
gemspec() click to toggle source
# File lib/qb/version.rb, line 59
def self.gemspec
  Gem.loaded_specs[GEM_NAME]
end
local_dev?() click to toggle source

Are we running in local development? Looks for the `//dev` directory's presence.

@return [Boolean]

# File lib/qb/version.rb, line 42
def self.local_dev?
  (QB::ROOT / 'dev').directory?
end
terminal_width() click to toggle source

This code was copied from Rake, available under MIT-LICENSE Copyright © 2003, 2004 Jim Weirich

# File lib/qb/cli.rb, line 159
def self.terminal_width
  result = if ENV["QB_COLUMNS"]
    ENV["QB_COLUMNS"].to_i
  else
    unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
  end
  result < 10 ? DEFAULT_TERMINAL_WIDTH : result
rescue
  DEFAULT_TERMINAL_WIDTH
end
testing?() click to toggle source

Are we running the tests (RSpec)?

Sees if the `QB_IS_TEST_ENV` environment is “truthy”.

@return [Boolean]

# File lib/qb/version.rb, line 53
def self.testing?
  require 'nrser'
  ENV['QB_IS_TEST_ENV'].truthy?
end
unix?() click to toggle source
# File lib/qb/cli.rb, line 187
def self.unix?
  RUBY_PLATFORM =~ \
    /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
end