class GithubActions::Container

Manage a Docker container

Constants

ENV_VARIABLES

the default environment variables in the container

TIMEOUT

the default timeout in seconds, maximum time for the running container, after the time runs out the container is automatically stopped and removed unless ‘KEEP_CONTAINER` option is set

Attributes

container[R]
image[R]
options[R]

Public Class Methods

new(image, options = nil) click to toggle source

constructor @param image [String] name of the Docker image to use @param options [String, nil] extra docker options

# File lib/tasks/github_actions/github_actions/container.rb, line 47
def initialize(image, options = nil)
  @image = image
  @options = options
end

Public Instance Methods

copy_current_dir() click to toggle source

copy the current directory to the current directory in the container

# File lib/tasks/github_actions/github_actions/container.rb, line 134
def copy_current_dir
  copy_files(Dir.pwd, cwd)
end
copy_files(from, to) click to toggle source

copy the files from host into the container @param from [String] the source path, if it is a directory all content

is copied (including subdirectories)

@param to [String] the target location in the container

# File lib/tasks/github_actions/github_actions/container.rb, line 120
def copy_files(from, to)
  stage("Copying #{from} to #{to} in the container...")

  if File.directory?(from)
    # Dir.children is similar to Dir.entries but it omits the "." and ".." values
    Dir.children(from).each do |f|
      system("docker cp #{f.shellescape} #{container.shellescape}:#{to.shellescape}")
    end
  else
    system("docker cp #{from.shellescape} #{container.shellescape}:#{to.shellescape}")
  end
end
cwd() click to toggle source

get the current working directory in the container @return [String] the path

# File lib/tasks/github_actions/github_actions/container.rb, line 112
def cwd
  `docker exec #{container.shellescape} pwd`.chomp
end
pull() click to toggle source

pull the Docker image, ensure that the latest version is used

# File lib/tasks/github_actions/github_actions/container.rb, line 53
def pull
  stage("Pulling the #{image} image...")
  # if the latest image is already present it does nothing
  system("docker pull #{image.shellescape}")
end
run(cmd, env = {}) click to toggle source

run a command in the container, runs “docker exec” the command is executed in a shell, so shell metacharacters like “&&” can be used to join several commands @param cmd [String] the command to run, it is passed to a shell to it might

contain multiple commands or shell meta characters

@param env [Hash] optional environment variables (with mapping “name” => “value”) @return [Boolean] ‘true` if the command succeeded (exit status 0),

`false` otherwise
# File lib/tasks/github_actions/github_actions/container.rb, line 103
def run(cmd, env = {})
  stage("Running command: #{cmd}")
  system("docker exec -it #{env_options(env)} #{container.shellescape} " \
         "sh -c #{cmd.shellescape}")
  $CHILD_STATUS.success?
end
start() click to toggle source

start the container, runs “docker create” and “docker start”

# File lib/tasks/github_actions/github_actions/container.rb, line 60
def start
  stage("Starting the container...")

  # define the initial command for the container to start
  if keep_container?
    # running "tail -f /dev/null" does nothing and gets stuck forever,
    # this ensures the container keeps running and we can execute
    # the other commands there via "docker exec"
    run = "tail"
    args = "-f /dev/null"
  else
    # the "sleep" command ensures the container shuts down automatically after
    # the timeout (to abort frozen jobs or avoid hanging containers after a crash)
    run = "sleep"
    args = TIMEOUT
  end

  cmd = "docker create #{env_options(ENV_VARIABLES)} --rm --entrypoint " \
        "#{run} #{options} #{ENV["DOCKER_OPTIONS"]} #{image.shellescape} #{args}"

  # contains the container ID
  @container = `#{cmd}`.chomp
  system("docker start #{container.shellescape} > /dev/null")
end
stop() click to toggle source

stop and remove the container from the system, runs “docker rm”

# File lib/tasks/github_actions/github_actions/container.rb, line 86
def stop
  if keep_container?
    print_container_usage
  else
    stage("Stopping the container...")
    system("docker rm --force #{container.shellescape} > /dev/null")
  end
end

Private Instance Methods

env_options(mapping) click to toggle source

build the docker environment command line options @param mapping [Hash] environment variables @return [String] the built Docker options

# File lib/tasks/github_actions/github_actions/container.rb, line 158
def env_options(mapping)
  mapping.map do |name, value|
    "-e #{name.shellescape}=#{value.shellescape}"
  end.join(" ")
end
keep_container?() click to toggle source

should we keep the container at the end or remove it?

# File lib/tasks/github_actions/github_actions/container.rb, line 141
def keep_container?
  ENV["KEEP_CONTAINER"] == "1" || ENV["KEEP_CONTAINER"] == "true"
end
print_container_usage() click to toggle source

when we keep the container running print some hints how to use it