Class: RakeCompilerDock::Starter

Inherits:
Object
  • Object
show all
Defined in:
lib/rake_compiler_dock/starter.rb

Constant Summary collapse

@@docker_checked_lock =
Mutex.new
@@docker_checked =
{}

Class Method Summary collapse

Class Method Details

.check_docker(pwd) ⇒ Object

[View source]

143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/rake_compiler_dock/starter.rb', line 143

def check_docker(pwd)
  @@docker_checked_lock.synchronize do
    @@docker_checked[pwd] ||= begin
      check = DockerCheck.new($stderr, pwd)
      unless check.ok?
        at_exit do
          check.print_help_text
        end
        raise DockerIsNotAvailable, "Docker is not available"
      end
      check
    end
  end
end

.container_image_name(options = {}) ⇒ Object

[View source]

163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/rake_compiler_dock/starter.rb', line 163

def container_image_name(options={})
  options.fetch(:image) do
    image_name = ENV['RCD_IMAGE'] || ENV['RAKE_COMPILER_DOCK_IMAGE']
    return image_name unless image_name.nil?

    "%s/rake-compiler-dock-image:%s-%s%s" % [
      container_registry,
      options.fetch(:version) { IMAGE_VERSION },
      container_rubyvm(options),
      container_jrubyvm?(options) ? "" : "-#{options.fetch(:platform)}",
    ]
  end
end

.container_jrubyvm?(options = {}) ⇒ Boolean

Returns:

  • (Boolean)
[View source]

186
187
188
# File 'lib/rake_compiler_dock/starter.rb', line 186

def container_jrubyvm?(options={})
  container_rubyvm(options).to_s == "jruby"
end

.container_registryObject

[View source]

177
178
179
# File 'lib/rake_compiler_dock/starter.rb', line 177

def container_registry
  ENV['CONTAINER_REGISTRY'] || "ghcr.io/rake-compiler"
end

.container_rubyvm(options = {}) ⇒ Object

[View source]

181
182
183
184
# File 'lib/rake_compiler_dock/starter.rb', line 181

def container_rubyvm(options={})
  return "jruby" if options[:platform] == "jruby"
  options.fetch(:rubyvm) { ENV['RCD_RUBYVM'] } || "mri"
end

.current_groupObject

[View source]

106
107
108
109
# File 'lib/rake_compiler_dock/starter.rb', line 106

def current_group
  group_obj = Etc.getgrgid rescue nil
  make_valid_group_name(group_obj ? group_obj.name : "dummygroup")
end

.current_userObject

[View source]

102
103
104
# File 'lib/rake_compiler_dock/starter.rb', line 102

def current_user
  make_valid_user_name(Etc.getlogin)
end

.exec(*args) ⇒ Object

[View source]

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/rake_compiler_dock/starter.rb', line 20

def exec(*args)
  options = (Hash === args.last) ? args.pop : {}

  mountdir = options.fetch(:mountdir){ ENV['RCD_MOUNTDIR'] || Dir.pwd }
  workdir = options.fetch(:workdir){ ENV['RCD_WORKDIR'] || Dir.pwd }
  case RUBY_PLATFORM
  when /mingw|mswin/
    mountdir = sanitize_windows_path(mountdir)
    workdir = sanitize_windows_path(workdir)
    # Virtualbox shared folders don't care about file permissions, so we use generic ids.
    uid = 1000
    gid = 1000
  when /darwin/
    uid = 1000
    gid = 1000
  else
    # Docker mounted volumes also share file uid/gid and permissions with the host.
    # Therefore we use the same attributes inside and outside the container.
    uid = Process.uid
    gid = Process.gid
  end
  user = options.fetch(:username){ current_user }
  group = options.fetch(:groupname){ current_group }

  platforms(options).split(" ").each do |platform|
    image_name = container_image_name(options.merge(platform: platform))

    check = check_docker(mountdir) if options.fetch(:check_docker){ true }
    docker_opts = options.fetch(:options) do
      opts = ["--rm", "-i"]
      opts << "-t" if $stdin.tty?
      opts
    end

    if verbose_flag(options) && args.size == 3 && args[0] == "bash" && args[1] == "-c"
      $stderr.puts "rake-compiler-dock bash -c #{ args[2].inspect }"
    end

    runargs = args.dup
    runargs.unshift("sigfw") if options.fetch(:sigfw){ true }
    runargs.unshift("runas") if options.fetch(:runas){ true }

    cmd = [check.docker_command, "run",
        "-v", "#{mountdir}:#{make_valid_path(mountdir)}",
        "-e", "UID=#{uid}",
        "-e", "GID=#{gid}",
        "-e", "USER=#{user}",
        "-e", "GROUP=#{group}",
        "-e", "GEM_PRIVATE_KEY_PASSPHRASE",
        "-e", "SOURCE_DATE_EPOCH",
        "-e", "ftp_proxy",
        "-e", "http_proxy",
        "-e", "https_proxy",
        "-e", "RCD_HOST_RUBY_PLATFORM=#{RUBY_PLATFORM}",
        "-e", "RCD_HOST_RUBY_VERSION=#{RUBY_VERSION}",
        "-e", "RCD_IMAGE=#{image_name}",
        "-w", make_valid_path(workdir),
        *docker_opts,
        image_name,
        *runargs]

    cmdline = Shellwords.join(cmd)
    if verbose_flag(options) == true
      $stderr.puts cmdline
    end

    ok = system(*cmd)
    if block_given?
      yield(ok, $?)
    elsif !ok
      fail "Command failed with status (#{$?.exitstatus}): " +
      "[#{cmdline}]"
    end
  end
end

.make_valid_group_name(name) ⇒ Object

[View source]

130
131
132
133
# File 'lib/rake_compiler_dock/starter.rb', line 130

def make_valid_group_name(name)
  name = make_valid_name(name)
  PredefinedGroups.include?(name) ? make_valid_name("_#{name}") : name
end

.make_valid_name(name) ⇒ Object

[View source]

111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rake_compiler_dock/starter.rb', line 111

def make_valid_name(name)
  name = name.to_s.downcase
  name = "_" if name.empty?
  # Convert disallowed characters
  if name.length > 1
    name = name[0..0].gsub(/[^a-z_]/, "_") + name[1..-2].to_s.gsub(/[^a-z0-9_-]/, "_") + name[-1..-1].to_s.gsub(/[^a-z0-9_$-]/, "_")
  else
    name = name.gsub(/[^a-z_]/, "_")
  end

  # Limit to 32 characters
  name.sub( /^(.{16}).{2,}(.{15})$/ ){ $1+"-"+$2 }
end

.make_valid_path(name) ⇒ Object

[View source]

135
136
137
138
# File 'lib/rake_compiler_dock/starter.rb', line 135

def make_valid_path(name)
  # Convert problematic characters
  name = name.gsub(/[ ]/i, "_")
end

.make_valid_user_name(name) ⇒ Object

[View source]

125
126
127
128
# File 'lib/rake_compiler_dock/starter.rb', line 125

def make_valid_user_name(name)
  name = make_valid_name(name)
  PredefinedUsers.include?(name) ? make_valid_name("_#{name}") : name
end

.platforms(options = {}) ⇒ Object

[View source]

190
191
192
193
# File 'lib/rake_compiler_dock/starter.rb', line 190

def platforms(options={})
  options.fetch(:platform) { ENV['RCD_PLATFORM'] } ||
    (container_jrubyvm?(options) ? "jruby" : "x86-mingw32 x64-mingw32")
end

.sanitize_windows_path(path) ⇒ Object

Change Path from “C:Path” to “/c/Path” as used by boot2docker

[View source]

159
160
161
# File 'lib/rake_compiler_dock/starter.rb', line 159

def sanitize_windows_path(path)
  path.gsub(/^([a-z]):/i){ "/#{$1.downcase}" }
end

.sh(cmd, options = {}, &block) ⇒ Object

[View source]

12
13
14
15
16
17
18
# File 'lib/rake_compiler_dock/starter.rb', line 12

def sh(cmd, options={}, &block)
  begin
    exec('bash', '-c', cmd, options, &block)
  ensure
    STDIN.cooked! if STDIN.tty?
  end
end

.verbose_flag(options) ⇒ Object

[View source]

96
97
98
99
100
# File 'lib/rake_compiler_dock/starter.rb', line 96

def verbose_flag(options)
  options.fetch(:verbose) do
    Object.const_defined?(:Rake) && Rake.const_defined?(:FileUtilsExt) ? Rake::FileUtilsExt.verbose_flag : false
  end
end