class Shiplane::Build

Attributes

postfix[RW]
sha[RW]
tag_latest[RW]

Public Class Methods

build!(sha, postfix = nil) click to toggle source

API Helper Methods

# File lib/shiplane/build.rb, line 190
def self.build!(sha, postfix = nil)
  new(sha, postfix: postfix).build!
end
build_latest!(sha, postfix = nil) click to toggle source
# File lib/shiplane/build.rb, line 194
def self.build_latest!(sha, postfix = nil)
  new(sha, postfix: postfix, tag_latest: true).build!
end
new(sha, postfix:, tag_latest: false) click to toggle source
# File lib/shiplane/build.rb, line 16
def initialize(sha, postfix:, tag_latest: false)
  @sha = sha
  @tag_latest = tag_latest
  @postfix = postfix

  Dotenv.overload File.join(Dir.pwd, build_config.fetch('environment_file', '.env'))

  # Add any ENV variable overrides from the capistrano configuration
  environment_variable_overrides = fetch(:shiplane_build_environment_variables, {})
  environment_variable_overrides.each do |key, value|
    if value.is_a? Proc
      ENV[key.to_s] = value.call
    else
      ENV[key.to_s] = value
    end
  end
end

Public Instance Methods

appname() click to toggle source

Properties

# File lib/shiplane/build.rb, line 115
def appname
  @appname ||= project_config['appname']
end
build!() click to toggle source
# File lib/shiplane/build.rb, line 34
def build!
  unless File.exist?(File.join(project_folder, Shiplane::SHIPLANE_CONFIG_FILENAME))
    Shiplane::CheckoutArtifact.checkout!(sha)
    Shiplane::ConvertComposeFile.convert_output!(project_folder, sha)
  end

  buildable_artifacts.each do |(artifact_name, attributes)|
    compose_context = docker_config.fetch('services', {}).fetch(artifact_name.to_s, {})
    Shiplane::ConvertDockerfile.convert_output!(project_folder, attributes, compose_context)

    FileUtils.cd project_folder do
      steps(artifact_name, attributes).select{|step| step.fetch(:condition, true) }.each do |step|
        puts step[:notify_before] if step.has_key? :notify_before
        success = system(step[:command])
        raise StepFailureException.new(step[:command], artifact_name) unless success
        puts step[:notify_after] if step.has_key? :notify_after
      end
    end
  end
rescue StepFailureException => e
  puts e.message
  raise if ENV['RAISE_EXCEPTIONS_ON_FAILED_BUILD']
end
build_cache_option() click to toggle source
# File lib/shiplane/build.rb, line 185
def build_cache_option
  ENV['USE_BUILD_CACHE'] == 'true' ? nil : "--no-cache"
end
build_command(artifact_name) click to toggle source

Commands

# File lib/shiplane/build.rb, line 74
def build_command(artifact_name)
  [
    'docker-compose',
    'build',
    build_cache_option,
    artifact_name,
  ].compact.join(' ')
end
build_output_image_name(artifact_name) click to toggle source
# File lib/shiplane/build.rb, line 181
def build_output_image_name(artifact_name)
  @build_output_image_name ||= "#{appname}-#{sha}_#{artifact_name}:latest"
end
buildable_artifacts() click to toggle source
# File lib/shiplane/build.rb, line 135
def buildable_artifacts
  build_config.fetch('artifacts', {})
end
default_registry_configuration() click to toggle source
# File lib/shiplane/build.rb, line 139
def default_registry_configuration
  {
    'url' => :dockerhub,
    'auth_method' => 'token',
  }
end
docker_config() click to toggle source
# File lib/shiplane/build.rb, line 131
def docker_config
  @docker_config ||= YAML.load(File.new(File.join(project_folder, 'docker-compose.yml')))
end
dockerhub?() click to toggle source
# File lib/shiplane/build.rb, line 146
def dockerhub?
  registry_configuration['url'] == :dockerhub
end
login_token() click to toggle source
# File lib/shiplane/build.rb, line 169
def login_token
  return ENV['DOCKERHUB_PASSWORD'] if dockerhub? && token_auth?

  ENV['SHIPLANE_CONTAINER_REGISTRY_TOKEN']
end
login_username() click to toggle source
# File lib/shiplane/build.rb, line 175
def login_username
  return ENV['DOCKERHUB_USERNAME'] if dockerhub? && token_auth?

  ENV['SHIPLANE_CONTAINER_REGISTRY_USERNAME']
end
project_folder() click to toggle source
# File lib/shiplane/build.rb, line 123
def project_folder
  @project_folder ||= File.join(Dir.pwd, 'docker_builds', appname, project_folder_name)
end
project_folder_name() click to toggle source
# File lib/shiplane/build.rb, line 119
def project_folder_name
  @project_folder_name ||= "#{appname}-#{sha}"
end
push_command(attributes, tag='latest') click to toggle source
# File lib/shiplane/build.rb, line 106
def push_command(attributes, tag='latest')
  [
    'docker',
    'push',
    "#{repo_name(attributes)}:#{tag}",
  ].compact.join(' ')
end
registry_configuration() click to toggle source
# File lib/shiplane/build.rb, line 154
def registry_configuration
  @registry_configuration ||= default_registry_configuration.merge(build_config.fetch('registry', {}))
end
registry_url() click to toggle source
# File lib/shiplane/build.rb, line 158
def registry_url
  @registry_url ||= dockerhub? ? nil : registry_configuration['url']
end
repo_name(attributes) click to toggle source
# File lib/shiplane/build.rb, line 162
def repo_name(attributes)
  [
    registry_url,
    attributes['repo'],
  ].compact.join('/')
end
shiplane_config() click to toggle source
# File lib/shiplane/build.rb, line 127
def shiplane_config
  @shiplane_config ||= Shiplane::Configuration.new
end
steps(artifact_name, attributes) click to toggle source
# File lib/shiplane/build.rb, line 58
def steps(artifact_name, attributes)
  [
    { command: build_command(artifact_name), notify_before: "Building Artifact: #{artifact_name}...", notify_after: "Docker Compose Built", stop_on_failure: true },
    { command: tag_command(artifact_name, attributes, sha), notify_before: "Tagging Build [#{sha}]...", stop_on_failure: true },
    { command: tag_command(artifact_name, attributes, "#{postfix}-#{sha}"), notify_before: "Tagging Build [#{postfix}-#{sha}]...", stop_on_failure: true, condition: !!postfix },
    { command: tag_command(artifact_name, attributes, "#{postfix}-latest"), notify_before: "Tagging Build [#{postfix}-latest]...", stop_on_failure: true, condition: !!postfix && tag_latest },
    { command: tag_command(artifact_name, attributes), notify_before: "Tagging Build [latest]...", stop_on_failure: true, condition: tag_latest },
    { command: token_login_command , notify_before: "Logging into Container Registry...", stop_on_failure: true },
    { command: push_command(attributes, "#{sha}"), notify_before: "Pushing Image", notify_after: "Completed Artifact: #{artifact_name}...", stop_on_failure: true },
    { command: push_command(attributes, "#{postfix}-#{sha}"), notify_before: "Pushing #{postfix} Image", notify_after: "Completed Artifact: #{artifact_name}...", stop_on_failure: true, condition: !!postfix },
    { command: push_command(attributes, "#{postfix}-latest"), notify_before: "Pushing Latest #{postfix} Image", notify_after: "Completed Latest Artifact: #{artifact_name}...", stop_on_failure: true, condition: !!postfix && tag_latest },
    { command: push_command(attributes, "latest"), notify_before: "Pushing Latest Image", notify_after: "Completed Latest Artifact: #{artifact_name}...", stop_on_failure: true, condition: tag_latest },
  ]
end
tag_command(artifact_name, attributes, tag='latest') click to toggle source
# File lib/shiplane/build.rb, line 97
def tag_command(artifact_name, attributes, tag='latest')
  [
    'docker',
    'tag',
    build_output_image_name(artifact_name),
    "#{repo_name(attributes)}:#{tag}",
  ].compact.join(' ')
end
token_auth?() click to toggle source
# File lib/shiplane/build.rb, line 150
def token_auth?
  registry_configuration['auth_method'] == 'token'
end
token_login_command() click to toggle source
# File lib/shiplane/build.rb, line 83
def token_login_command
  @token_login_command ||= [
    'echo',
    "\"#{login_token}\"",
    '|',
    'docker',
    'login',
    registry_url,
    '--username',
    login_username,
    '--password-stdin',
  ].compact.join(' ')
end