Commit 645dceb0 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Run plugins as separate process and pass data via STDIN

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
parent eff5746b
......@@ -66,4 +66,4 @@ eslint-report.html
/locale/**/LC_MESSAGES
/locale/**/*.time_stamp
/.rspec
/plugins/*
/plugins/enabled/*
......@@ -28,7 +28,6 @@ module Gitlab
config.eager_load_paths.push(*%W[#{config.root}/lib
#{config.root}/app/models/hooks
#{config.root}/app/models/members
#{config.root}/plugins
#{config.root}/app/models/project_services
#{config.root}/app/workers/concerns
#{config.root}/app/services/concerns
......
# Requirements
# * File name must end with _s.rb. For example, jenkins_plugin.rb.
# * All code should be inside class. No code should be executed on file load.
# * Class name must be same as file name.
# If file name is jenkins_plugin.rb then class name must be JenkinsPlugin.
#
# Reccomendations
# * Code should not depend on or use GitLab classes and other code.
# * Consider contributing your plugin to GitLab source code so we can test it
# and make sure it will work in further version.
#
class $NAMEPlugin
def execute(data)
# TODO: Implement me
end
end
module Gitlab
module Plugin
def self.files
Dir.glob(Rails.root.join('plugins', '*_plugin.rb'))
Dir.glob(Rails.root.join('plugins/enabled/*'))
end
def self.execute_all_async(data)
files.each do |file|
puts file
PluginWorker.perform_async(file, data)
end
end
def self.execute(file, data)
# TODO: Implement
#
# Reuse some code from gitlab-shell https://gitlab.com/gitlab-org/gitlab-shell/blob/master/lib/gitlab_custom_hook.rb#L40
# Pass data as STDIN (or JSON encode?)
#
# 1. Return true if 0 exit code
# 2. Return false if non-zero exit code
# Prepare the hook subprocess. Attach a pipe to its stdin, and merge
# both its stdout and stderr into our own stdout.
stdin_reader, stdin_writer = IO.pipe
hook_pid = spawn({}, file, in: stdin_reader, err: :out)
stdin_reader.close
# Submit changes to the hook via its stdin.
begin
IO.copy_stream(StringIO.new(data.to_json), stdin_writer)
rescue Errno::EPIPE
# It is not an error if the hook does not consume all of its input.
end
# Close the pipe to let the hook know there is no further input.
stdin_writer.close
Process.wait(hook_pid)
$?.success?
end
end
end
namespace :plugins do
desc 'Generate skeleton for new plugin'
task generate: :environment do
ARGV.each { |a| task a.to_sym { } }
name = ARGV[1]
unless name.present?
puts 'Error. You need to specify a name for the plugin'
exit 1
end
class_name = name.classify
param = name.underscore
file_path = Rails.root.join('plugins', param + '_plugin.rb')
template = File.read(Rails.root.join('generator_templates', 'plugins', 'template.rb'))
template.gsub!('$NAME', class_name)
if File.write(file_path, template)
puts "Done. Your plugin saved under #{file_path}."
puts 'Feel free to edit it.'
else
puts "Failed to save #{file_path}."
end
end
desc 'Validate existing plugins'
task validate: :environment do
puts 'Validating plugins from /plugins directory'
......
#!/usr/bin/env clojure
(let [in (slurp *in*)]
(spit "/tmp/clj-data.txt" in))
#!/usr/bin/env ruby
x = STDIN.read
File.write('/tmp/rb-data.txt', x)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment