Class: GithubActions::Container

Inherits:
Object
  • Object
show all
Includes:
Colorizer
Defined in:
lib/tasks/github_actions/github_actions/container.rb

Overview

Manage a Docker container

Constant Summary collapse

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

3600
ENV_VARIABLES =

the default environment variables in the container

{
  # this is a CI environment
  "CI"             => "true",
  # skip the modified check in the "rake osc:build" task
  "CHECK_MODIFIED" => "0"
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Colorizer

#error, #info, #stage, #success, #warning

Constructor Details

#initialize(image, options = nil) ⇒ Container

constructor

Parameters:

  • image (String)

    name of the Docker image to use

  • options (String, nil) (defaults to: nil)

    extra docker options



47
48
49
50
# File 'lib/tasks/github_actions/github_actions/container.rb', line 47

def initialize(image, options = nil)
  @image = image
  @options = options
end

Instance Attribute Details

#containerObject (readonly)

Returns the value of attribute container.



29
30
31
# File 'lib/tasks/github_actions/github_actions/container.rb', line 29

def container
  @container
end

#imageObject (readonly)

Returns the value of attribute image.



29
30
31
# File 'lib/tasks/github_actions/github_actions/container.rb', line 29

def image
  @image
end

#optionsObject (readonly)

Returns the value of attribute options.



29
30
31
# File 'lib/tasks/github_actions/github_actions/container.rb', line 29

def options
  @options
end

Instance Method Details

#copy_current_dirObject

copy the current directory to the current directory in the container



134
135
136
# 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) ⇒ Object

copy the files from host into the container

Parameters:

  • from (String)

    the source path, if it is a directory all content is copied (including subdirectories)

  • to (String)

    the target location in the container



120
121
122
123
124
125
126
127
128
129
130
131
# 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

#cwdString

get the current working directory in the container

Returns:

  • (String)

    the path



112
113
114
# File 'lib/tasks/github_actions/github_actions/container.rb', line 112

def cwd
  `docker exec #{container.shellescape} pwd`.chomp
end

#pullObject

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



53
54
55
56
57
# 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 = {}) ⇒ Boolean

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

Parameters:

  • cmd (String)

    the command to run, it is passed to a shell to it might contain multiple commands or shell meta characters

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

    optional environment variables (with mapping “name” => “value”)

Returns:

  • (Boolean)

    ‘true` if the command succeeded (exit status 0), `false` otherwise



103
104
105
106
107
108
# 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

#startObject

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



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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

#stopObject

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



86
87
88
89
90
91
92
93
# 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