miniexec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/miniexec +49 -0
  3. data/lib/miniexec.rb +130 -0
  4. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0f7e4e2e4cd3529c3d39ba72db21f2290c51dffdfedef503bc7423b95a8afe5e
4
+ data.tar.gz: 28a58aad14b944600fe64573df8869b5de3a5dc94ecf1844ab7405fe4cb30be0
5
+ SHA512:
6
+ metadata.gz: 0eec63f1bcaacc2e548f8e2381069fba8fe8ebbad998e843a2ecbc56f26852f308332f879946cb55c59aeee9d9be94cca76c35dc1ebe89472a2ad8e2c9664a77
7
+ data.tar.gz: 5c7a796c761e8c7ef3423bf4d4d81020fdc29995345b22015337578c0319623077a7ff110395bf74af02e1c3afb82b85166a2074f91422d845e46913ffcb3057
data/bin/miniexec ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'miniexec'
5
+ require 'optparse'
6
+
7
+ options = {
8
+ binds: [],
9
+ env: []
10
+ }
11
+
12
+ OptionParser.new do |opts|
13
+ opts.banner = 'Usage: miniexec.rb [options]'
14
+ opts.separator ''
15
+ opts.separator 'specific options:'
16
+
17
+ opts.on('-p', '--path PATH', 'Path to the repository containing a valid .gitlab-ci.yml') do |path|
18
+ options[:path] = path
19
+ end
20
+
21
+ opts.on('-j', '--job JOBNAME', 'Specify the gitlab job to run') do |job|
22
+ options[:job] = job
23
+ end
24
+
25
+ opts.on('-b', '--bind BIND', 'Specify a bind mapping',
26
+ 'Example: /some/local/dir:/mapping/in/container') do |bind|
27
+ options[:binds].push bind
28
+ end
29
+ opts.on('-e', '--environment VARIABLE',
30
+ 'Specify an environment variable to be passed to the container',
31
+ 'Example: SOMEVAR=thing') do |env|
32
+ options[:env].push env
33
+ end
34
+ opts.on('-d', '--docker-url URL',
35
+ 'Location of the docker socket') do |sock|
36
+ options[:docker] = sock || ENV['DOCKER_HOST'] || '/run/docker.sock'
37
+ end
38
+ end.parse!
39
+
40
+ raise OptionParser::MissingArgument, 'Specify a job with -j' if options[:job].nil?
41
+ raise OptionParser::MissingArgument, 'Specify a job with -p' if options[:path].nil?
42
+
43
+ MiniExec.config(project_path: options[:path])
44
+ exec = MiniExec.new options[:job],
45
+ docker_url: options[:docker],
46
+ binds: options[:binds],
47
+ env: options[:env]
48
+
49
+ exec.run_job
data/lib/miniexec.rb ADDED
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Main class
4
+ class MiniExec
5
+ require 'logger'
6
+ require 'docker-api'
7
+ require 'json'
8
+ require 'tempfile'
9
+ require 'yaml'
10
+ # Class instance variables
11
+ @project_path = '.'
12
+ @workflow_file = '.gitlab-ci.yml'
13
+
14
+ class << self
15
+ attr_accessor :project_path, :workflow_file
16
+ end
17
+
18
+ def self.config(project_path: @project_path, workflow_file: @workflow_file)
19
+ @project_path = project_path
20
+ @class = workflow_file
21
+ self
22
+ end
23
+
24
+ attr_accessor :script
25
+
26
+ def initialize(job,
27
+ project_path: self.class.project_path,
28
+ workflow_file: self.class.workflow_file,
29
+ docker_url: nil,
30
+ binds: [],
31
+ env: [])
32
+ @job_name = job
33
+ @project_path = project_path
34
+ workflow = YAML.load(File.read("#{@project_path}/#{workflow_file}"))
35
+ @job = workflow[job]
36
+ @job['name'] = job
37
+ @default_image = workflow['image'] || 'debian:buster-slim'
38
+ @image = set_job_image
39
+ @script = compile_script
40
+ @binds = binds
41
+ @env = env
42
+
43
+ configure_logger
44
+
45
+ Docker.options[:read_timeout] = 6000
46
+ Docker.url = docker_url if docker_url
47
+ end
48
+
49
+ def run_job
50
+ script_path = "/tmp/#{@job['name']}.sh"
51
+ @logger.debug "Fetching image #{@image}"
52
+ Docker::Image.create(fromImage: @image)
53
+ @logger.debug 'Image fetched'
54
+ Dir.chdir(@project_path) do
55
+ @logger.debug 'Creating container'
56
+ container = Docker::Container.create(
57
+ Cmd: ['/bin/bash', script_path],
58
+ Image: @image,
59
+ Volumes: @binds.map { |b| { b => { path_parent: 'rw' } } }.inject(:merge),
60
+ Env: @env
61
+ )
62
+ container.store_file(script_path, @script)
63
+ container.start({ Binds: [@binds] })
64
+ container.tap(&:start).attach { |_, chunk| @logger.info chunk }
65
+ end
66
+ end
67
+
68
+ private
69
+
70
+ def set_job_image
71
+ return @job['image'] if @job['image']
72
+
73
+ @default_image
74
+ end
75
+
76
+ def configure_logger
77
+ @logger = Logger.new($stdout)
78
+ @logger.formatter = proc do |severity, _, _, msg|
79
+ "[#{severity}]: #{msg}\n"
80
+ end
81
+ @logger.level = ENV['LOGLEVEL'] || Logger::WARN
82
+ end
83
+
84
+ def compile_script
85
+ before_script = @job['before_script'] || []
86
+ script = @job['script'] || []
87
+ after_script = @job['after_script'] || []
88
+ (before_script + script + after_script).flatten.join("\n")
89
+ end
90
+ end
91
+
92
+ options = {
93
+ binds: [],
94
+ env: []
95
+ }
96
+
97
+ OptionParser.new do |opts|
98
+ opts.banner = 'Usage: miniexec.rb [options]'
99
+ opts.separator ''
100
+ opts.separator 'specific options:'
101
+
102
+ opts.on('-p', '--path PATH', 'Path to the repository containing a valid .gitlab-ci.yml') do |path|
103
+ options[:path] = path
104
+ end
105
+
106
+ opts.on('-j', '--job JOBNAME', 'Specify the gitlab job to run') do |job|
107
+ options[:job] = job
108
+ end
109
+
110
+ opts.on('-b', '--bind BIND', 'Specify a bind mapping',
111
+ 'Example: /some/local/dir:/mapping/in/container') do |bind|
112
+ options[:binds].push bind
113
+ end
114
+ opts.on('-e', '--environment VARIABLE',
115
+ 'Specify an environment variable to be passed to the container',
116
+ 'Example: SOMEVAR=thing') do |env|
117
+ options[:env].push env
118
+ end
119
+ end.parse!
120
+
121
+ raise OptionParser::MissingArgument, 'Specify a job with -j' if options[:job].nil?
122
+ raise OptionParser::MissingArgument, 'Specify a job with -p' if options[:path].nil?
123
+
124
+ MiniExec.config(project_path: options[:path])
125
+ exec = MiniExec.new options[:job],
126
+ docker_url: 'unix:///var/run/user/1000/podman/podman.sock',
127
+ binds: options[:binds],
128
+ env: options[:env]
129
+
130
+ exec.run_job
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: miniexec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Martin Pugh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A minimal interpretor/executor for .gitlab-ci.yml
14
+ email: pugh@s3kr.it
15
+ executables:
16
+ - miniexec
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - bin/miniexec
21
+ - lib/miniexec.rb
22
+ homepage: https://github.com/s3krit/miniexec
23
+ licenses:
24
+ - AGPL-3.0-or-later
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubygems_version: 3.1.2
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: exec a gitlab job
45
+ test_files: []