git-restart 0.0.14.pre.dev → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/git-restart +2 -2
- data/lib/git-restart/runner.rb +44 -4
- data/lib/git-restart/task.rb +109 -6
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89f6a4a1fa9ad535f9a80f69fc2729e28fa4c077
|
4
|
+
data.tar.gz: '09e3329d30be30ea60511e894dc0f1e0ba44375b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e46803d3834a7fec3c2166f8864d45b746de31b0ca9d6e87c839ab806a4b5943ff822739ef209d447d7e45aa4a88d8dd77b812b478f7ac8d042b1a08983965e8
|
7
|
+
data.tar.gz: 6e883c22e0dd8b1ee5c09a2c51a193d67ff82c2abcdbc33f3ed1232bdf73d3373b8835365d1a248b242b985e0eae30226f1d008a9375318aefc43e2bc0b134a6
|
data/bin/git-restart
CHANGED
data/lib/git-restart/runner.rb
CHANGED
@@ -8,23 +8,41 @@ require_relative "task.rb"
|
|
8
8
|
|
9
9
|
module GitRestart
|
10
10
|
class Runner
|
11
|
+
# Sets a name for this Runner, used for reporting to GitHub
|
11
12
|
attr_accessor :name
|
12
13
|
|
13
|
-
|
14
|
+
# Which repository to listen to. Uses "Owner/Repo" syntax.
|
15
|
+
attr_accessor :repo
|
16
|
+
# A white- and blacklist of branches. If neither are specified, all are used.
|
17
|
+
# If the whitelist is used, only it is considered.
|
18
|
+
attr_accessor :branches, :exclude_branches
|
19
|
+
# Which branch to start on.
|
20
|
+
# This not only makes the system switch branch, but it will also execute
|
21
|
+
# ALL active tasks. Very useful for auto-updating servers.
|
22
|
+
attr_accessor :start_on
|
23
|
+
# A list of tasks that this Runner will actually look at.
|
24
|
+
# If nil, all tasks are allowed.
|
14
25
|
attr_accessor :allowed_tasks
|
15
26
|
|
16
27
|
attr_reader :next_tasks
|
17
28
|
attr_reader :current_task_file
|
18
29
|
|
30
|
+
# The MQTT::SubHandler to use to listen to GitHub updates.
|
31
|
+
# Can be specified as either MQTT::SubHandler class or String, the latter
|
32
|
+
# will be interpreted as URI
|
19
33
|
attr_reader :mqtt
|
34
|
+
# Octokit to use for optional status reporting
|
20
35
|
attr_accessor :octokit
|
21
36
|
|
37
|
+
# @return [String] Full SHA of the current commit
|
22
38
|
def current_commit()
|
23
39
|
@git.object("HEAD").sha;
|
24
40
|
end
|
41
|
+
# @return [String] Name of the current branch
|
25
42
|
def current_branch()
|
26
43
|
@git.current_branch();
|
27
44
|
end
|
45
|
+
# @return [Array<String>] A list of all files that were modified in the commit we are checking
|
28
46
|
def current_modified()
|
29
47
|
@current_modified;
|
30
48
|
end
|
@@ -77,20 +95,24 @@ module GitRestart
|
|
77
95
|
}
|
78
96
|
end
|
79
97
|
|
98
|
+
# Update the GitHub status for the task of given name, with optional status message
|
99
|
+
# Only prints a line if no octokit is specified
|
80
100
|
def update_status(name, newStatus, message = nil)
|
81
|
-
puts "Task #{
|
101
|
+
puts "Task #{name} assumed a new status: #{newStatus}#{message ? " MSG:#{message}" : ""}"
|
82
102
|
|
83
103
|
return unless @octokit;
|
84
104
|
|
85
105
|
begin
|
86
106
|
@octokit.create_status(@repo, current_commit(), newStatus, {
|
87
|
-
context: "#{
|
107
|
+
context: "#{name}/#{name}".gsub(" ", "_"),
|
88
108
|
description: message,
|
89
109
|
})
|
90
110
|
rescue
|
91
111
|
end
|
92
112
|
end
|
93
113
|
|
114
|
+
# Start the task responsible for queueing and executing the individual
|
115
|
+
# task stop, branch switch, task start cycles
|
94
116
|
def _start_task_thread()
|
95
117
|
@taskThread = Thread.new do
|
96
118
|
loop do
|
@@ -101,7 +123,9 @@ module GitRestart
|
|
101
123
|
end
|
102
124
|
end.abort_on_exception = true;
|
103
125
|
end
|
126
|
+
private :_start_task_thread
|
104
127
|
|
128
|
+
# Stop all tasks of the given hash, not list. Waits for them to stop.
|
105
129
|
def _stop_tasks(taskList)
|
106
130
|
taskList.each do |name, t|
|
107
131
|
t.stop();
|
@@ -111,19 +135,27 @@ module GitRestart
|
|
111
135
|
@current_tasks.delete(name);
|
112
136
|
end
|
113
137
|
end
|
138
|
+
private :_stop_tasks
|
114
139
|
def _stop_all_tasks()
|
115
140
|
_stop_tasks(@current_tasks);
|
116
141
|
end
|
142
|
+
private :_stop_all_tasks
|
143
|
+
# Stop all tasks that have marked themselves as affected by the
|
144
|
+
# current set of file-changes. This way, applications are only
|
145
|
+
# restarted when their own files have been altered.
|
117
146
|
def _stop_triggered_tasks()
|
118
147
|
_stop_tasks(@current_tasks.select {|k,v| v.triggered?});
|
119
148
|
end
|
149
|
+
private :_stop_triggered_tasks
|
120
150
|
|
151
|
+
# Scan through the file-tree for .gittask files, or use the @allowed_tasks
|
152
|
+
# list of tasks.
|
121
153
|
def _generate_next_tasks()
|
122
154
|
puts "Generating new tasks..."
|
123
155
|
@next_tasks = Hash.new();
|
124
156
|
|
125
157
|
taskFiles = `find ./ -nowarn -iname "*.gittask"`
|
126
|
-
taskFiles.split("\n").each do |t|
|
158
|
+
[taskFiles.split("\n"), @allowed_tasks].flatten.each do |t|
|
127
159
|
puts "Looking at: #{t}"
|
128
160
|
t.gsub!(/^\.\//,"");
|
129
161
|
@current_task_file = t;
|
@@ -145,7 +177,10 @@ module GitRestart
|
|
145
177
|
|
146
178
|
puts "Finished loading! Next tasks: #{@next_tasks.keys}"
|
147
179
|
end
|
180
|
+
private :_generate_next_tasks
|
148
181
|
|
182
|
+
# Start all new tasks that have marked themselves as affected by the current
|
183
|
+
# set of filechanges
|
149
184
|
def _start_next_tasks()
|
150
185
|
_generate_next_tasks();
|
151
186
|
|
@@ -158,7 +193,10 @@ module GitRestart
|
|
158
193
|
@current_tasks[name] = t;
|
159
194
|
end
|
160
195
|
end
|
196
|
+
private :_start_next_tasks
|
161
197
|
|
198
|
+
# Perform an entire cycle of git fetch & checkout, stop tasks, pull, restart.
|
199
|
+
# *CAUTION* A HARD RESET IS USED HERE
|
162
200
|
def _switch_to(branch, commit = nil)
|
163
201
|
puts "\n\nSwitching to branch: #{branch}#{commit ? ",commit: #{commit}" : ""}"
|
164
202
|
|
@@ -180,11 +218,13 @@ module GitRestart
|
|
180
218
|
|
181
219
|
_start_next_tasks();
|
182
220
|
end
|
221
|
+
private :_switch_to
|
183
222
|
|
184
223
|
def autostart()
|
185
224
|
return unless @start_on;
|
186
225
|
@branchQueue << {branch: @start_on};
|
187
226
|
end
|
227
|
+
private :autostart
|
188
228
|
|
189
229
|
def mqtt=(mqtt)
|
190
230
|
if(mqtt.is_a? String)
|
data/lib/git-restart/task.rb
CHANGED
@@ -1,39 +1,82 @@
|
|
1
1
|
|
2
|
+
# @author Xasin
|
2
3
|
module GitRestart
|
4
|
+
# The Error-Class used to signal when a Task is set up wrong
|
3
5
|
class TaskValidityError < StandardError
|
4
6
|
end
|
5
7
|
|
8
|
+
# This class is used to define "Tasks". Each task represents
|
9
|
+
# a set of commands, which it executes in chronological order, or until
|
10
|
+
# a task errors.
|
11
|
+
# Additionally, it will kill execution of tasks with a specified kill-signal
|
12
|
+
# when an update was detected from GitHub.
|
13
|
+
# The failure-status of the tasks can also be reported via Octokit, allowing this
|
14
|
+
# to be used as a simple CI or Test system for various languages.
|
6
15
|
class Task
|
16
|
+
# The array of tasks to execute. Each target will be executed in the given
|
17
|
+
# order via `Process.spawn`.
|
18
|
+
# @return [Array<String>]
|
7
19
|
attr_reader :targets
|
8
20
|
|
21
|
+
# The signal (as String, like Signal.list) to use to kill the process.
|
22
|
+
# Can be nil to disable killing
|
9
23
|
attr_accessor :signal
|
24
|
+
# Whether or not to report failure if the currently running target
|
25
|
+
# has a non-zero exit status after having been killed. Only makes sense
|
26
|
+
# together with report_status
|
10
27
|
attr_accessor :expect_clean_exit
|
28
|
+
# Whether or not to report failure/success status to GitHub using Octokit
|
11
29
|
attr_accessor :report_status
|
30
|
+
# Defines this as a "CI_Task". Such a task will always run on an update,
|
31
|
+
# regardless what files changed. Useful if you always want a status report
|
32
|
+
# on GitHub.
|
12
33
|
attr_accessor :ci_task
|
13
|
-
|
14
|
-
|
34
|
+
# Name of the Task. *Required*. Used as *unique* ID, and to report status to GitHub
|
35
|
+
attr_accessor :name
|
36
|
+
# The file to use to retrieve a single-line status info for the "description"
|
37
|
+
# string of the GitHub status. Only the last *non-indented* line is used,
|
38
|
+
# which allows the output of Minitest to be used directly.
|
39
|
+
attr_accessor :status_file
|
40
|
+
|
41
|
+
# Whether or not this task is active. Usually set via #on_branches,
|
42
|
+
# but can be used to manually disable or enable this task based on
|
43
|
+
# config files, ENV variables etc.
|
15
44
|
attr_accessor :active
|
16
45
|
|
46
|
+
# The last status-code of this Task. Used internally.
|
17
47
|
attr_reader :lastStatus
|
48
|
+
# The last status-message of this task. Used internally.
|
18
49
|
attr_reader :status_message
|
19
50
|
|
51
|
+
# @api private
|
20
52
|
def self.runner=(runner)
|
21
53
|
@runner = runner;
|
22
54
|
end
|
55
|
+
# @api private
|
23
56
|
def self.runner()
|
24
57
|
return @runner;
|
25
58
|
end
|
59
|
+
# @return [GitRestart::Runner] Responsible Runner class
|
26
60
|
def runner()
|
27
61
|
return self.class.runner();
|
28
62
|
end
|
29
63
|
|
64
|
+
# @return [String] Name of the current branch
|
30
65
|
def branch()
|
31
66
|
runner().current_branch();
|
32
67
|
end
|
68
|
+
# @return [String] Full SHA of the current commit
|
69
|
+
def current_commit()
|
70
|
+
runner().current_commit();
|
71
|
+
end
|
72
|
+
|
73
|
+
# @return [Array<String>] A list of all files that were modified in the commit we are checking
|
33
74
|
def modified()
|
34
75
|
runner().current_modified();
|
35
76
|
end
|
36
77
|
|
78
|
+
# Use this function to specify which files trigger a restart for this Task
|
79
|
+
# Files can be specified as a RegEx, and can be "local/like.this" or "/reference/from/project.root"
|
37
80
|
def watch(regEx)
|
38
81
|
if(regEx.is_a? String)
|
39
82
|
regEx = Regexp.quote(regEx);
|
@@ -42,12 +85,17 @@ module GitRestart
|
|
42
85
|
@watched << Regexp.new(regEx);
|
43
86
|
end
|
44
87
|
|
88
|
+
# Specify which branches to run on. Not needed if "active" is just set to true
|
45
89
|
def on_branches(branches)
|
46
90
|
[branches].flatten.each do |b|
|
47
91
|
@active |= (b == branch());
|
48
92
|
end
|
49
93
|
end
|
50
94
|
|
95
|
+
# Create a new Task. This function does not take any input values, instead,
|
96
|
+
# one has to set the class up inside the block!
|
97
|
+
# A validity check will be run directly after yield(), as such, at the very least
|
98
|
+
# the name and a valid signal must have been specified!
|
51
99
|
def initialize()
|
52
100
|
@statuschange_mutex = Mutex.new();
|
53
101
|
|
@@ -67,6 +115,8 @@ module GitRestart
|
|
67
115
|
|
68
116
|
valid?
|
69
117
|
|
118
|
+
@status_file ||= "/tmp/TaskLog_#{@name}_#{current_commit()}";
|
119
|
+
|
70
120
|
if(runner().next_tasks[@name])
|
71
121
|
raise TaskValidityError, "A task of name #{@name} already exists!"
|
72
122
|
else
|
@@ -74,20 +124,31 @@ module GitRestart
|
|
74
124
|
end
|
75
125
|
end
|
76
126
|
|
127
|
+
# Checks whether or not the current set of modified files would require this
|
128
|
+
# task to be (re)started. Always returns true if @ci_task is set, or if
|
129
|
+
# the runner just has been started using @start_on
|
130
|
+
# @api private
|
77
131
|
def triggered?
|
78
132
|
return true if modified().nil?
|
79
133
|
return true if @ci_task
|
80
134
|
|
81
135
|
@watched.each do |regEx|
|
82
136
|
modified().each do |f|
|
83
|
-
|
84
|
-
|
137
|
+
if regEx.to_s =~ /^\(\?\-mix:\\\/(.*)\)$/ then
|
138
|
+
return true if f =~ Regexp.new($1);
|
139
|
+
else
|
140
|
+
next unless f =~ /#{Regexp.quote(@chdir)}(.*)/
|
141
|
+
return true if $1 =~ regEx;
|
142
|
+
end
|
85
143
|
end
|
86
144
|
end
|
87
145
|
|
88
146
|
return false;
|
89
147
|
end
|
90
148
|
|
149
|
+
# Checks whether or not this task has been set up properly. Currently only
|
150
|
+
# checks the name and abort signal.
|
151
|
+
# @api private
|
91
152
|
def valid?()
|
92
153
|
unless Signal.list[@signal] or @signal.nil?
|
93
154
|
raise TaskValidityError, "The specified kill-signal is not valid!"
|
@@ -98,8 +159,33 @@ module GitRestart
|
|
98
159
|
end
|
99
160
|
end
|
100
161
|
|
162
|
+
def _rm_logfile()
|
163
|
+
if File.exist?("/tmp/TaskLog_#{@name}_#{current_commit()}") then
|
164
|
+
File.delete("/tmp/TaskLog_#{@name}_#{current_commit()}");
|
165
|
+
end
|
166
|
+
end
|
167
|
+
private :_rm_logfile
|
168
|
+
def _get_statusline()
|
169
|
+
return "No status specified" unless File.exist? @status_file
|
170
|
+
|
171
|
+
sMsg = ""
|
172
|
+
File.open(@status_file, "r") do |sFile|
|
173
|
+
sFile.each_line do |l|
|
174
|
+
l.chomp!
|
175
|
+
next if l == "";
|
176
|
+
next if l =~ /^\s+/;
|
177
|
+
|
178
|
+
sMsg = l;
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
return sMsg;
|
183
|
+
end
|
184
|
+
private :_rm_logfile
|
185
|
+
|
101
186
|
def _report_status(status, message = nil)
|
102
|
-
|
187
|
+
message ||= _get_statusline();
|
188
|
+
@status_message = message;
|
103
189
|
|
104
190
|
return unless @report_status
|
105
191
|
|
@@ -107,6 +193,13 @@ module GitRestart
|
|
107
193
|
end
|
108
194
|
private :_report_status
|
109
195
|
|
196
|
+
# Starts this task.
|
197
|
+
# Once the task has been started it will run each given
|
198
|
+
# target one after another, waiting for each one to finish. If @report_status
|
199
|
+
# is set, it will also do just that.
|
200
|
+
# Task execution is handled within a thread, meaning that the function
|
201
|
+
# itself does not block.
|
202
|
+
# @api private
|
110
203
|
def start()
|
111
204
|
puts "Starting Task: #{@name}"
|
112
205
|
|
@@ -118,11 +211,13 @@ module GitRestart
|
|
118
211
|
@executionThread = Thread.new do
|
119
212
|
_report_status(:pending);
|
120
213
|
|
214
|
+
_rm_logfile();
|
121
215
|
@targets.each do |target|
|
216
|
+
# Mutex to ensure there either is no task running or a PID given
|
122
217
|
@statuschange_mutex.synchronize {
|
123
218
|
break if @exiting
|
124
219
|
options = {
|
125
|
-
[:out, :err] => "/
|
220
|
+
[:out, :err] => "/tmp/TaskLog_#{@name}_#{current_commit()}"
|
126
221
|
}
|
127
222
|
options[:chdir] = @chdir if @chdir
|
128
223
|
|
@@ -138,6 +233,7 @@ module GitRestart
|
|
138
233
|
|
139
234
|
if(@lastStatus == 0)
|
140
235
|
_report_status(:success);
|
236
|
+
_rm_logfile();
|
141
237
|
elsif(!@exiting || @expect_clean_exit)
|
142
238
|
_report_status(:failure);
|
143
239
|
end
|
@@ -147,6 +243,11 @@ module GitRestart
|
|
147
243
|
sleep 0.01
|
148
244
|
end
|
149
245
|
|
246
|
+
# Stop this task.
|
247
|
+
# Stopping it means immediately killing the currently running target with
|
248
|
+
# the specified signal, and not running any further targets.
|
249
|
+
# *Except* when nil is specified as signal, in which case the stop will be ignored!
|
250
|
+
# @api private
|
150
251
|
def stop()
|
151
252
|
puts "Stopping Task: #{@name}"
|
152
253
|
return if @signal.nil?
|
@@ -159,6 +260,8 @@ module GitRestart
|
|
159
260
|
}
|
160
261
|
end
|
161
262
|
|
263
|
+
# Wait for this task to finish execution.
|
264
|
+
# Either by naturally ending, or by being killed.
|
162
265
|
def join()
|
163
266
|
@executionThread.join();
|
164
267
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-restart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Xasin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mqtt-sub_handler
|
@@ -121,12 +121,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
121
121
|
version: '0'
|
122
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
123
|
requirements:
|
124
|
-
- - "
|
124
|
+
- - ">="
|
125
125
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
126
|
+
version: '0'
|
127
127
|
requirements: []
|
128
128
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.
|
129
|
+
rubygems_version: 2.5.2.1
|
130
130
|
signing_key:
|
131
131
|
specification_version: 4
|
132
132
|
summary: "(Re)start scripts and monitor them on a GitHub push"
|