leanci 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem "serverengine", github: 'frsyuki/serverengine'
4
-
4
+ gem "rb-inotify"
data/bin/leanci CHANGED
@@ -4,17 +4,25 @@ require 'rubygems'
4
4
  require 'leanci'
5
5
 
6
6
  config = {
7
+ daemonize: false,
7
8
  script: 'default.leanci',
8
9
  pid_path: 'leanci.pid',
9
10
  log: 'leanci.log'
10
11
  }
11
12
  OptionParser.new do |opt|
13
+ opt.on('-d', 'daemonize') do
14
+ config[:daemonize] = true
15
+ config[:supervisor] = true
16
+ end
12
17
  opt.on('-f VALUE', 'specify leanci file') do |f|
13
18
  config[:script] = f
14
19
  end
15
- opt.on('--pid VALUE', 'pid file') do |f|
20
+ opt.on('--pidfile VALUE', 'pid file') do |f|
16
21
  config[:pid_path] = f
17
22
  end
23
+ opt.on('--logfile VALUE', 'log file') do |f|
24
+ config[:log] = f
25
+ end
18
26
  opt.parse!(ARGV)
19
27
  end
20
28
 
data/default.leanci CHANGED
@@ -1,18 +1,26 @@
1
- per_sec(10) do
2
- bash do
3
- code <<-EOC
4
- cd crape-proto
5
- hg incoming
6
- EOC
7
- success do
8
- bash do
9
- log "pull --update crape-proto"
10
- echo true
11
- code <<-EOC
12
- cd crape-proto
13
- hg pull --update
14
- EOC
15
- end
1
+ trigger :poll_mercurial do
2
+ mercurial 'test-repo2' do
3
+ interval 5
4
+ user 'hirayama'
5
+ group 'hirayama'
6
+ action :hg_update
7
+ end
8
+ end
9
+
10
+ action :hg_update do
11
+ echo 'repository updated'
12
+ end
13
+
14
+ =begin
15
+ trigger :watch_file do
16
+ watch 't.txt' do
17
+ modify do
18
+ run :file_update
16
19
  end
17
20
  end
18
21
  end
22
+
23
+ action :file_update do
24
+ echo 'file updated'
25
+ end
26
+ =end
data/leanci.gemspec CHANGED
@@ -22,4 +22,5 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake"
23
23
 
24
24
  spec.add_runtime_dependency "serverengine"
25
+ spec.add_runtime_dependency "rb-inotify"
25
26
  end
data/lib/daemon.rb CHANGED
@@ -1,25 +1,23 @@
1
- require_relative 'script'
2
-
3
1
  module MyWorker
4
2
  def run
5
3
  reload
6
4
  until @stop
7
- if @script_source
8
- Script.new(logger, @script_source)
9
- else
10
- sleep 1
5
+ if @script
6
+ @script.doit
11
7
  end
8
+ sleep 1
12
9
  end
13
10
  end
14
11
 
15
12
  def reload
16
13
  begin
17
- @script_source = nil
14
+ @script = nil
18
15
  File.open(config[:script]) do |f|
19
- @script_source = f.read
16
+ @script = Script::TopLevel.new(logger, f.read)
20
17
  end
21
- rescue
18
+ rescue => e
22
19
  logger.fatal "can't open script file"
20
+ logger.fatal e.to_s
23
21
  end
24
22
  end
25
23
 
@@ -1,3 +1,3 @@
1
1
  module Leanci
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/leanci.rb CHANGED
@@ -2,4 +2,8 @@ require 'serverengine'
2
2
  require 'optparse'
3
3
  require 'logger'
4
4
 
5
+ require_relative 'script'
6
+ Dir.glob("#{File.dirname(__FILE__)}/plugins/*") do |file|
7
+ require_relative file
8
+ end
5
9
  require_relative 'daemon'
@@ -0,0 +1,64 @@
1
+ module Script
2
+ class Prog
3
+ def bash(injection = nil, &block)
4
+ @prog.push Bash.new(@toplevel, injection, &block)
5
+ end
6
+ end
7
+
8
+ class Bash
9
+ def initialize(toplevel, injection = nil, &block)
10
+ @toplevel = toplevel
11
+ @injection = injection
12
+ instance_eval(&block)
13
+ end
14
+
15
+ attr_reader :injection
16
+
17
+ def doit
18
+ if @code
19
+ command = nil
20
+ if @user
21
+ if @user == 'root'
22
+ command = "sudo /bin/bash"
23
+ else
24
+ group = @group || @user
25
+ command = "sudo -u #{@user} -g #{group} /bin/bash"
26
+ end
27
+ else
28
+ command = "/bin/bash"
29
+ end
30
+
31
+ if exec_code(command) == 0
32
+ @success && @success.doit
33
+ else
34
+ @failure && @failure.doit
35
+ end
36
+ end
37
+ end
38
+
39
+ #---------------------------------------------------------------
40
+ # DSL
41
+ def user(s); @user = s end
42
+ def group(s); @group = s end
43
+ def code(s); @code = s end
44
+ def log(s); @log = s end
45
+ def echo(s); @echo = s end
46
+
47
+ def success(inj = nil, &block)
48
+ @success = Prog.new(@toplevel, inj, &block)
49
+ end
50
+ def failure(inj = nil, &block)
51
+ @failure = Prog.new(@toplevel, inj, &block)
52
+ end
53
+
54
+ private
55
+ def exec_code(cmd)
56
+ logger = @toplevel.logger
57
+ logger.info @log if @log
58
+ logger.info @code.chomp if @echo
59
+ o, e, s = Open3.capture3(cmd, stdin_data: @code)
60
+ logger.info o.chomp if @echo
61
+ s
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ module Script
2
+ class Trigger
3
+ def mercurial(repository, &block)
4
+ @crawler = Mercurial.new(@toplevel, repository, &block)
5
+ end
6
+ end
7
+
8
+ class Mercurial
9
+ def initialize(toplevel, repository, &block)
10
+ @toplevel = toplevel
11
+ @repository = repository
12
+ @m = 0
13
+ @interval = 5
14
+ instance_eval(&block)
15
+ end
16
+
17
+ attr_reader :username, :groupname, :repository, :actiontag
18
+
19
+ def doit
20
+ @m += 1
21
+ if @interval <= @m
22
+ Dir.chdir(repository) do
23
+ Bash.new(@toplevel, self) do
24
+ code <<-EOC
25
+ hg incoming
26
+ EOC
27
+ success(injection) do
28
+ bash(injection) do
29
+ log "hg: pull --update #{injection.repository}"
30
+ user injection.username
31
+ group injection.groupname
32
+ echo true
33
+ code <<-EOC
34
+ HGENCODING=utf-8 hg pull --update
35
+ EOC
36
+ end
37
+ run injection.actiontag
38
+ end
39
+ end.doit
40
+ end
41
+ @m = 0
42
+ end
43
+ end
44
+
45
+ #---------------------------------------------------------------
46
+ # DSL
47
+ def interval(n)
48
+ @interval = n
49
+ end
50
+
51
+ def user(username)
52
+ @username = username
53
+ end
54
+
55
+ def group(groupname)
56
+ @groupname = groupname
57
+ end
58
+
59
+ def action(tag)
60
+ @actiontag = tag
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,33 @@
1
+ # -*- coding: utf-8 -*-
2
+ module Script
3
+ class Trigger
4
+ def watch(filename, &block)
5
+ @crawler = Watch.new(@toplevel, filename, &block)
6
+ end
7
+ end
8
+
9
+ class Watch
10
+ def initialize(toplevel, filename, &block)
11
+ @toplevel = toplevel
12
+ @filename = filename
13
+ @notifier = INotify::Notifier.new
14
+ instance_eval(&block)
15
+ end
16
+
17
+ def doit
18
+ @notifier.to_io.tap do |io|
19
+ rs, = IO.select([io], nil, nil, 0)
20
+ @notifier.process if rs
21
+ end
22
+ end
23
+
24
+ #---------------------------------------------------------------
25
+ # DSL
26
+ def modify(&block)
27
+ @modify = Prog.new(@toplevel, &block)
28
+ @notifier.watch(@filename, :modify) do
29
+ @modify.doit
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/script.rb CHANGED
@@ -1,92 +1,131 @@
1
1
  require 'open3'
2
2
 
3
- class Bash
4
- def initialize(logger, &block)
5
- @logger = logger
6
- instance_eval(&block)
7
-
8
- if @code
9
- if @user
10
- if @user == 'root'
11
- exec_code("sudo /bin/bash")
12
- else
13
- group = @group || @user
14
- exec_code("sudo -u #{@user} -g #{group} /bin/bash", stdin_data: @code)
15
- end
16
- else
17
- exec_code("/bin/bash")
18
- end
19
- if status == 0
20
- InnerScript.new(@logger, &@success) if @success
21
- else
22
- InnerScript.new(@logger, &@failure) if @failure
3
+ module Script
4
+ class TopLevel
5
+ def initialize(logger, script_source)
6
+ @logger = logger
7
+ @triggers = {}
8
+ @actions = {}
9
+ instance_eval(script_source)
10
+ end
11
+
12
+ attr_reader :logger, :triggers, :actions
13
+
14
+ def doit
15
+ @triggers.each do |k, t|
16
+ t.doit
23
17
  end
24
18
  end
25
- end
26
19
 
27
- def exec_code(cmd)
28
- @logger.info @logtext if @logtext
29
- @logger.info @code.chomp if @echo
30
- o, e, s = Open3.capture3(cmd, stdin_data: @code)
31
- @logger.info o.chomp if @echo
32
- @status = s
20
+ #---------------------------------------------------------------
21
+ # DSL
22
+ def trigger(tag, &block)
23
+ @triggers[tag] = Trigger.new(self, &block)
24
+ end
25
+
26
+ def action(tag, &block)
27
+ @actions[tag] = Action.new(self, &block)
28
+ end
33
29
  end
34
30
 
35
- attr_reader :status
31
+ ################################################################
32
+ # in TopLevel
33
+ class Trigger
34
+ def initialize(toplevel, &block)
35
+ @toplevel = toplevel
36
+ instance_eval(&block)
37
+ end
36
38
 
37
- def user(s)
38
- @user = s
39
- end
39
+ def doit
40
+ @crawler.doit
41
+ end
40
42
 
41
- def group(s)
42
- @group = s
43
+ #---------------------------------------------------------------
44
+ # DSL
45
+ def interval(n, &block)
46
+ @crawler = Interval.new(@toplevel, n, &block)
47
+ end
43
48
  end
44
49
 
45
- def code(s)
46
- @code = s
47
- end
50
+ class Action
51
+ def initialize(toplevel, &block)
52
+ @prog = Prog.new(toplevel, &block)
53
+ end
48
54
 
49
- def success(&block)
50
- @success = block
55
+ def doit
56
+ @prog.doit
57
+ end
51
58
  end
52
59
 
53
- def failure(&block)
54
- @failure = block
55
- end
60
+ ################################################################
61
+ # in Trigger
62
+ class Interval
63
+ def initialize(toplevel, n, &block)
64
+ @toplevel = toplevel
65
+ @n = n
66
+ @m = 0
67
+ @prog = Prog.new(@toplevel, &block)
68
+ end
56
69
 
57
- def log(logtext)
58
- @logtext = logtext
70
+ def doit
71
+ @m += 1
72
+ if @m == @n
73
+ @prog.doit
74
+ @m = 0
75
+ end
76
+ end
59
77
  end
60
78
 
61
- def echo(flag)
62
- @echo = flag
63
- end
64
- end
79
+ ################################################################
80
+ # where procedure required
81
+ class Prog
82
+ def initialize(toplevel, injection = nil, &block)
83
+ @toplevel = toplevel
84
+ @injection = injection
85
+ @prog = []
86
+ instance_eval(&block)
87
+ end
65
88
 
66
- class InnerScript
67
- def initialize(logger, &block)
68
- @logger = logger
69
- instance_eval(&block)
70
- end
89
+ attr_reader :injection
71
90
 
72
- def bash(&block)
73
- Bash.new(@logger, &block).status
74
- end
75
- end
91
+ def doit
92
+ @prog.each do |p|
93
+ p.doit
94
+ end
95
+ end
76
96
 
97
+ #---------------------------------------------------------------
98
+ # DSL
99
+ def echo(s)
100
+ @prog.push Echo.new(@toplevel, s)
101
+ end
77
102
 
78
- class Script
79
- def initialize(logger, script_source)
80
- @logger = logger
81
- instance_eval(script_source)
103
+ def run(tag)
104
+ @prog.push Run.new(@toplevel, tag)
105
+ end
82
106
  end
83
107
 
84
- def per_sec(sec = 1, &block)
85
- sleep sec
86
- instance_eval(&block)
108
+ ################################################################
109
+ # in Prog
110
+ class Echo
111
+ def initialize(toplevel, s)
112
+ @toplevel = toplevel
113
+ @s = s
114
+ end
115
+
116
+ def doit
117
+ @toplevel.logger.info @s
118
+ end
87
119
  end
88
120
 
89
- def bash(&block)
90
- Bash.new(@logger, &block).status
121
+ class Run
122
+ def initialize(toplevel, tag)
123
+ @toplevel = toplevel
124
+ @tag = tag
125
+ end
126
+
127
+ def doit
128
+ @toplevel.actions[@tag].doit
129
+ end
91
130
  end
92
131
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leanci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-01 00:00:00.000000000 Z
12
+ date: 2013-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rb-inotify
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  description: minimal CI servant
63
79
  email:
64
80
  - naoyuki.hirayama@gmail.com
@@ -79,6 +95,9 @@ files:
79
95
  - lib/daemon.rb
80
96
  - lib/leanci.rb
81
97
  - lib/leanci/version.rb
98
+ - lib/plugins/bash.rb
99
+ - lib/plugins/mercurial.rb
100
+ - lib/plugins/watch.rb
82
101
  - lib/script.rb
83
102
  homepage: https://github.com/jonigata/leanci
84
103
  licenses: